summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rwxr-xr-xBUILD/build_mccge.sh2
-rwxr-xr-xCMakeLists.txt10
-rw-r--r--Makefile.am38
-rwxr-xr-xclient/CMakeLists.txt27
-rw-r--r--client/mysqlbinlog.cc2
-rw-r--r--client/mysqldump.c4
-rw-r--r--client/mysqlimport.c4
-rw-r--r--client/mysqlslap.c6
-rw-r--r--client/mysqltest.cc2
-rw-r--r--client/readline.cc2
-rw-r--r--configure.in16
-rwxr-xr-xdbug/CMakeLists.txt1
-rwxr-xr-xextra/CMakeLists.txt12
-rw-r--r--include/config-win.h15
-rw-r--r--include/m_ctype.h2
-rw-r--r--include/my_dir.h4
-rw-r--r--include/my_global.h41
-rw-r--r--include/my_pthread.h36
-rw-r--r--include/my_sys.h57
-rw-r--r--include/mysql.h8
-rwxr-xr-xlibmysql/CMakeLists.txt26
-rw-r--r--libmysqld/CMakeLists.txt10
-rw-r--r--libmysqld/Makefile.am2
-rw-r--r--libmysqld/emb_qcache.cc3
-rw-r--r--libmysqld/examples/CMakeLists.txt3
-rw-r--r--libmysqld/lib_sql.cc66
-rw-r--r--libmysqld/libmysqld.c2
-rw-r--r--mysql-test/collections/default.experimental71
-rw-r--r--mysql-test/collections/mysql-next-mr.push5
-rw-r--r--mysql-test/collections/mysql-trunk.push5
-rw-r--r--mysql-test/include/wait_for_slave_param.inc4
-rwxr-xr-xmysql-test/mysql-test-run.pl1
-rw-r--r--mysql-test/r/bench_count_distinct.result2
-rw-r--r--mysql-test/r/bigint.result6
-rw-r--r--mysql-test/r/cast.result2
-rw-r--r--mysql-test/r/ctype_utf8.result126
-rw-r--r--mysql-test/r/date_formats.result64
-rw-r--r--mysql-test/r/func_compress.result14
-rw-r--r--mysql-test/r/func_encrypt.result8
-rw-r--r--mysql-test/r/func_encrypt_nossl.result42
-rw-r--r--mysql-test/r/func_gconcat.result64
-rw-r--r--mysql-test/r/func_math.result10
-rw-r--r--mysql-test/r/func_str.result386
-rw-r--r--mysql-test/r/group_min_max.result270
-rw-r--r--mysql-test/r/index_merge_innodb.result326
-rw-r--r--mysql-test/r/information_schema-big.result93
-rw-r--r--mysql-test/r/information_schema.result88
-rw-r--r--mysql-test/r/join_outer.result12
-rw-r--r--mysql-test/r/loadxml.result79
-rw-r--r--mysql-test/r/locale.result49
-rw-r--r--mysql-test/r/merge.result2
-rw-r--r--mysql-test/r/metadata.result96
-rw-r--r--mysql-test/r/myisam-system.result2
-rw-r--r--mysql-test/r/mysqldump.result10
-rw-r--r--mysql-test/r/partition.result1
-rw-r--r--mysql-test/r/partition_hash.result2
-rw-r--r--mysql-test/r/partition_pruning.result19
-rw-r--r--mysql-test/r/partition_truncate.result18
-rw-r--r--mysql-test/r/ps.result4
-rw-r--r--mysql-test/r/ps_2myisam.result42
-rw-r--r--mysql-test/r/ps_3innodb.result42
-rw-r--r--mysql-test/r/ps_4heap.result42
-rw-r--r--mysql-test/r/ps_5merge.result84
-rw-r--r--mysql-test/r/query_cache.result8
-rw-r--r--mysql-test/r/signal.result2362
-rw-r--r--mysql-test/r/signal_code.result35
-rw-r--r--mysql-test/r/signal_demo1.result270
-rw-r--r--mysql-test/r/signal_demo2.result197
-rw-r--r--mysql-test/r/signal_demo3.result143
-rw-r--r--mysql-test/r/signal_sqlmode.result86
-rw-r--r--mysql-test/r/sp-dynamic.result8
-rw-r--r--mysql-test/r/sp-vars.result70
-rw-r--r--mysql-test/r/sp.result51
-rw-r--r--mysql-test/r/sp_notembedded.result2
-rw-r--r--mysql-test/r/strict.result52
-rw-r--r--mysql-test/r/trigger.result14
-rw-r--r--mysql-test/r/type_newdecimal.result76
-rw-r--r--mysql-test/r/variables.result10
-rw-r--r--mysql-test/r/view.result20
-rw-r--r--mysql-test/std_data/loadxml.dat64
-rw-r--r--mysql-test/std_data/loadxml2.dat19
-rw-r--r--mysql-test/suite/binlog/r/binlog_index.result2
-rw-r--r--mysql-test/suite/binlog/r/binlog_unsafe.result27
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_func_view.result92
-rw-r--r--mysql-test/suite/funcs_1/r/innodb_storedproc_02.result3
-rw-r--r--mysql-test/suite/funcs_1/r/memory_func_view.result92
-rw-r--r--mysql-test/suite/funcs_1/r/memory_storedproc_02.result3
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_func_view.result92
-rw-r--r--mysql-test/suite/funcs_1/r/myisam_storedproc_02.result3
-rw-r--r--mysql-test/suite/funcs_1/r/ndb_func_view.result92
-rw-r--r--mysql-test/suite/funcs_1/r/ndb_storedproc_02.result3
-rw-r--r--mysql-test/suite/funcs_1/r/storedproc.result73
-rw-r--r--mysql-test/suite/funcs_1/t/disabled.def2
-rw-r--r--mysql-test/suite/im/r/im_cmd_line.result47
-rw-r--r--mysql-test/suite/im/r/im_daemon_life_cycle.result26
-rw-r--r--mysql-test/suite/im/r/im_instance_conf.result225
-rw-r--r--mysql-test/suite/im/r/im_life_cycle.result73
-rw-r--r--mysql-test/suite/im/r/im_options.result151
-rw-r--r--mysql-test/suite/im/r/im_utils.result96
-rw-r--r--mysql-test/suite/im/t/disabled.def20
-rw-r--r--mysql-test/suite/im/t/im_check_env.inc26
-rw-r--r--mysql-test/suite/im/t/im_cmd_line.imtest68
-rw-r--r--mysql-test/suite/im/t/im_daemon_life_cycle-im.opt3
-rw-r--r--mysql-test/suite/im/t/im_daemon_life_cycle.imtest100
-rw-r--r--mysql-test/suite/im/t/im_instance_conf-im.opt1
-rw-r--r--mysql-test/suite/im/t/im_instance_conf.imtest244
-rw-r--r--mysql-test/suite/im/t/im_life_cycle-im.opt1
-rw-r--r--mysql-test/suite/im/t/im_life_cycle.imtest205
-rw-r--r--mysql-test/suite/im/t/im_options-im.opt1
-rw-r--r--mysql-test/suite/im/t/im_options.imtest248
-rw-r--r--mysql-test/suite/im/t/im_utils-im.opt1
-rw-r--r--mysql-test/suite/im/t/im_utils.imtest107
-rwxr-xr-xmysql-test/suite/im/t/kill_n_check.sh147
-rwxr-xr-xmysql-test/suite/im/t/log.sh24
-rw-r--r--mysql-test/suite/im/t/utils.sh55
-rwxr-xr-xmysql-test/suite/im/t/wait_for_process.sh114
-rwxr-xr-xmysql-test/suite/im/t/wait_for_socket.sh94
-rw-r--r--mysql-test/suite/innodb/r/innodb-zip.result26
-rw-r--r--mysql-test/suite/innodb/t/disabled.def2
-rw-r--r--mysql-test/suite/large_tests/r/lock_tables_big.result1
-rw-r--r--mysql-test/suite/large_tests/t/lock_tables_big.test32
-rw-r--r--mysql-test/suite/ndb/r/ndb_bitfield.result4
-rw-r--r--mysql-test/suite/ndb/r/ndb_dd_basic.result6
-rw-r--r--mysql-test/suite/ndb/r/ndb_dd_ddl.result2
-rw-r--r--mysql-test/suite/ndb/r/ndb_gis.result4
-rw-r--r--mysql-test/suite/ndb/r/ndb_multi_row.result6
-rw-r--r--mysql-test/suite/ndb/r/ndb_partition_error.result2
-rw-r--r--mysql-test/suite/ndb/r/ndb_row_format.result2
-rw-r--r--mysql-test/suite/ndb/r/ndb_single_user.result10
-rw-r--r--mysql-test/suite/ndb/r/ps_7ndb.result42
-rw-r--r--mysql-test/suite/parts/inc/partition_mgm.inc90
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc0_archive.result12
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc0_memory.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result12
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc1_archive.result12
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc1_memory.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result12
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc2_archive.result12
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc2_memory.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result164
-rw-r--r--mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result12
-rw-r--r--mysql-test/suite/parts/t/disabled.def2
-rw-r--r--mysql-test/suite/parts/t/partition_mgm_lc0_archive.test1
-rw-r--r--mysql-test/suite/parts/t/partition_mgm_lc0_ndb.test2
-rw-r--r--mysql-test/suite/parts/t/partition_mgm_lc1_archive.test1
-rw-r--r--mysql-test/suite/parts/t/partition_mgm_lc1_ndb.test2
-rw-r--r--mysql-test/suite/parts/t/partition_mgm_lc2_archive.test1
-rw-r--r--mysql-test/suite/parts/t/partition_mgm_lc2_ndb.test2
-rw-r--r--mysql-test/suite/rpl/r/rpl_EE_err.result2
-rw-r--r--mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result4
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_sp007_innodb.result2
-rw-r--r--mysql-test/suite/rpl/t/disabled.def2
-rw-r--r--mysql-test/t/ctype_utf8.test19
-rw-r--r--mysql-test/t/func_gconcat.test32
-rw-r--r--mysql-test/t/func_str.test42
-rw-r--r--mysql-test/t/group_min_max.test125
-rw-r--r--mysql-test/t/index_merge_innodb.test8
-rw-r--r--mysql-test/t/information_schema-big.test48
-rw-r--r--mysql-test/t/information_schema.test35
-rw-r--r--mysql-test/t/loadxml.test107
-rw-r--r--mysql-test/t/locale.test34
-rw-r--r--mysql-test/t/metadata.test57
-rw-r--r--mysql-test/t/partition_pruning.test19
-rw-r--r--mysql-test/t/partition_truncate.test26
-rw-r--r--mysql-test/t/signal.test2685
-rw-r--r--mysql-test/t/signal_code.test57
-rw-r--r--mysql-test/t/signal_demo1.test345
-rw-r--r--mysql-test/t/signal_demo2.test207
-rw-r--r--mysql-test/t/signal_demo3.test159
-rw-r--r--mysql-test/t/signal_sqlmode.test123
-rw-r--r--mysql-test/t/variables.test10
-rwxr-xr-xmysys/CMakeLists.txt4
-rw-r--r--mysys/Makefile.am14
-rw-r--r--mysys/charset-def.c4
-rw-r--r--mysys/charset.c3
-rw-r--r--mysys/default_modify.c6
-rw-r--r--mysys/my_chsize.c19
-rw-r--r--mysys/my_create.c15
-rw-r--r--mysys/my_delete.c2
-rw-r--r--mysys/my_dup.c6
-rw-r--r--mysys/my_error.c18
-rw-r--r--mysys/my_file.c1
-rw-r--r--mysys/my_fopen.c49
-rw-r--r--mysys/my_fstream.c17
-rw-r--r--mysys/my_gethwaddr.c100
-rw-r--r--mysys/my_init.c2
-rw-r--r--mysys/my_lib.c26
-rw-r--r--mysys/my_lock.c140
-rw-r--r--mysys/my_messnc.c6
-rw-r--r--mysys/my_mmap.c6
-rw-r--r--mysys/my_open.c223
-rw-r--r--mysys/my_pread.c103
-rw-r--r--mysys/my_quick.c22
-rw-r--r--mysys/my_read.c21
-rw-r--r--mysys/my_seek.c38
-rw-r--r--mysys/my_static.c8
-rw-r--r--mysys/my_sync.c4
-rw-r--r--mysys/my_thr_init.c69
-rw-r--r--mysys/my_wincond.c3
-rw-r--r--mysys/my_winerr.c123
-rw-r--r--mysys/my_winfile.c672
-rw-r--r--mysys/my_winthread.c132
-rw-r--r--mysys/my_write.c39
-rw-r--r--mysys/mysys_priv.h24
-rwxr-xr-xnetware/BUILD/compile-netware-START1
-rwxr-xr-xregex/CMakeLists.txt2
-rwxr-xr-xscripts/CMakeLists.txt2
-rw-r--r--server-tools/CMakeLists.txt33
-rw-r--r--server-tools/Makefile.am20
-rwxr-xr-xserver-tools/instance-manager/CMakeLists.txt38
-rw-r--r--server-tools/instance-manager/IMService.cpp124
-rw-r--r--server-tools/instance-manager/IMService.h32
-rw-r--r--server-tools/instance-manager/Makefile.am103
-rw-r--r--server-tools/instance-manager/README11
-rw-r--r--server-tools/instance-manager/WindowsService.cpp231
-rw-r--r--server-tools/instance-manager/WindowsService.h56
-rw-r--r--server-tools/instance-manager/angel.cc407
-rw-r--r--server-tools/instance-manager/angel.h34
-rw-r--r--server-tools/instance-manager/buffer.cc110
-rw-r--r--server-tools/instance-manager/buffer.h65
-rw-r--r--server-tools/instance-manager/command.cc30
-rw-r--r--server-tools/instance-manager/command.h60
-rw-r--r--server-tools/instance-manager/commands.cc1752
-rw-r--r--server-tools/instance-manager/commands.h393
-rw-r--r--server-tools/instance-manager/exit_codes.h40
-rw-r--r--server-tools/instance-manager/guardian.cc496
-rw-r--r--server-tools/instance-manager/guardian.h110
-rw-r--r--server-tools/instance-manager/instance.cc944
-rw-r--r--server-tools/instance-manager/instance.h273
-rw-r--r--server-tools/instance-manager/instance_map.cc649
-rw-r--r--server-tools/instance-manager/instance_map.h102
-rw-r--r--server-tools/instance-manager/instance_options.cc753
-rw-r--r--server-tools/instance-manager/instance_options.h126
-rw-r--r--server-tools/instance-manager/listener.cc337
-rw-r--r--server-tools/instance-manager/listener.h61
-rw-r--r--server-tools/instance-manager/log.cc196
-rw-r--r--server-tools/instance-manager/log.h59
-rw-r--r--server-tools/instance-manager/manager.cc526
-rw-r--r--server-tools/instance-manager/manager.h71
-rw-r--r--server-tools/instance-manager/messages.cc104
-rw-r--r--server-tools/instance-manager/messages.h23
-rw-r--r--server-tools/instance-manager/mysql_connection.cc376
-rw-r--r--server-tools/instance-manager/mysql_connection.h74
-rw-r--r--server-tools/instance-manager/mysql_manager_error.h40
-rw-r--r--server-tools/instance-manager/mysqlmanager.cc232
-rw-r--r--server-tools/instance-manager/options.cc558
-rw-r--r--server-tools/instance-manager/options.h108
-rw-r--r--server-tools/instance-manager/parse.cc509
-rw-r--r--server-tools/instance-manager/parse.h212
-rw-r--r--server-tools/instance-manager/parse_output.cc407
-rw-r--r--server-tools/instance-manager/parse_output.h33
-rw-r--r--server-tools/instance-manager/portability.h65
-rw-r--r--server-tools/instance-manager/priv.cc76
-rw-r--r--server-tools/instance-manager/priv.h99
-rw-r--r--server-tools/instance-manager/protocol.cc217
-rw-r--r--server-tools/instance-manager/protocol.h47
-rw-r--r--server-tools/instance-manager/thread_registry.cc419
-rw-r--r--server-tools/instance-manager/thread_registry.h176
-rw-r--r--server-tools/instance-manager/user_management_commands.cc421
-rw-r--r--server-tools/instance-manager/user_management_commands.h167
-rw-r--r--server-tools/instance-manager/user_map.cc395
-rw-r--r--server-tools/instance-manager/user_map.h103
-rw-r--r--sql-common/client.c81
-rwxr-xr-xsql/CMakeLists.txt10
-rw-r--r--sql/Makefile.am4
-rw-r--r--sql/authors.h1
-rw-r--r--sql/event_scheduler.cc13
-rw-r--r--sql/field.cc29
-rw-r--r--sql/field.h9
-rw-r--r--sql/ha_ndbcluster.cc18
-rw-r--r--sql/ha_ndbcluster_binlog.cc68
-rw-r--r--sql/ha_partition.cc141
-rw-r--r--sql/ha_partition.h5
-rw-r--r--sql/handler.cc32
-rw-r--r--sql/item.cc5
-rw-r--r--sql/item_create.cc33
-rw-r--r--sql/item_func.cc12
-rw-r--r--sql/item_strfunc.cc112
-rw-r--r--sql/item_strfunc.h7
-rw-r--r--sql/item_sum.cc1244
-rw-r--r--sql/item_sum.h538
-rw-r--r--sql/item_timefunc.cc2
-rw-r--r--sql/lex.h15
-rw-r--r--sql/log.cc55
-rw-r--r--sql/log_event.cc35
-rw-r--r--sql/log_event_old.cc12
-rw-r--r--sql/my_decimal.cc6
-rw-r--r--sql/mysql_priv.h16
-rw-r--r--sql/mysqld.cc167
-rw-r--r--sql/opt_range.cc188
-rw-r--r--sql/opt_range.h17
-rw-r--r--sql/opt_sum.cc10
-rw-r--r--sql/partition_element.h3
-rw-r--r--sql/protocol.cc157
-rw-r--r--sql/protocol.h6
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/rpl_rli.cc4
-rw-r--r--sql/set_var.cc15
-rw-r--r--sql/share/errmsg.txt38
-rw-r--r--sql/slave.cc41
-rw-r--r--sql/sp.cc22
-rw-r--r--sql/sp_head.cc33
-rw-r--r--sql/sp_pcontext.cc3
-rw-r--r--sql/sp_pcontext.h2
-rw-r--r--sql/sp_rcontext.cc94
-rw-r--r--sql/sp_rcontext.h61
-rw-r--r--sql/sql_acl.cc26
-rw-r--r--sql/sql_base.cc30
-rw-r--r--sql/sql_cache.cc4
-rw-r--r--sql/sql_class.cc420
-rw-r--r--sql/sql_class.h369
-rw-r--r--sql/sql_connect.cc15
-rw-r--r--sql/sql_delete.cc19
-rw-r--r--sql/sql_derived.cc6
-rw-r--r--sql/sql_error.cc638
-rw-r--r--sql/sql_error.h514
-rw-r--r--sql/sql_insert.cc35
-rw-r--r--sql/sql_lex.h98
-rw-r--r--sql/sql_load.cc568
-rw-r--r--sql/sql_locale.cc619
-rw-r--r--sql/sql_parse.cc47
-rw-r--r--sql/sql_partition.cc36
-rw-r--r--sql/sql_prepare.cc46
-rw-r--r--sql/sql_repl.cc4
-rw-r--r--sql/sql_select.cc140
-rw-r--r--sql/sql_select.h7
-rw-r--r--sql/sql_servers.cc2
-rw-r--r--sql/sql_show.cc28
-rw-r--r--sql/sql_signal.cc510
-rw-r--r--sql/sql_signal.h152
-rw-r--r--sql/sql_string.cc68
-rw-r--r--sql/sql_table.cc46
-rw-r--r--sql/sql_tablespace.cc4
-rw-r--r--sql/sql_update.cc7
-rw-r--r--sql/sql_yacc.yy470
-rw-r--r--sql/table.cc24
-rw-r--r--sql/thr_malloc.cc7
-rw-r--r--sql/time.cc2
-rw-r--r--sql/tztime.cc2
-rw-r--r--sql/udf_example.c5
-rw-r--r--sql/unireg.cc21
-rw-r--r--storage/blackhole/CMakeLists.txt3
-rw-r--r--storage/csv/CMakeLists.txt2
-rw-r--r--storage/example/CMakeLists.txt2
-rwxr-xr-xstorage/heap/CMakeLists.txt2
-rw-r--r--storage/innobase/CMakeLists.txt6
-rw-r--r--storage/innobase/handler/ha_innodb.cc22
-rwxr-xr-xstorage/myisam/CMakeLists.txt10
-rw-r--r--storage/myisam/mi_locking.c8
-rwxr-xr-xstorage/myisammrg/CMakeLists.txt2
-rw-r--r--storage/myisammrg/ha_myisammrg.cc2
-rwxr-xr-xstrings/CMakeLists.txt3
-rw-r--r--strings/conf_to_src.c5
-rw-r--r--strings/ctype-extra.c72
-rw-r--r--strings/ctype-sjis.c4
-rw-r--r--strings/ctype-uca.c169
-rw-r--r--strings/ctype-ucs2.c4
-rw-r--r--strings/ctype-utf8.c2
-rw-r--r--strings/ctype.c20
-rw-r--r--support-files/mysql.server.sh178
-rw-r--r--support-files/mysql.spec.sh8
-rwxr-xr-xtests/CMakeLists.txt7
-rw-r--r--unittest/mysys/Makefile.am11
-rwxr-xr-xvio/CMakeLists.txt2
-rw-r--r--vio/viosocket.c4
371 files changed, 18593 insertions, 19814 deletions
diff --git a/.bzrignore b/.bzrignore
index 6c6a43dacab..0dd59e5cee8 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -3064,3 +3064,4 @@ sql/share/spanish
sql/share/swedish
sql/share/ukrainian
libmysqld/examples/mysqltest.cc
+libmysqld/sql_signal.cc
diff --git a/BUILD/build_mccge.sh b/BUILD/build_mccge.sh
index ad3e728453c..379ca1b2c68 100755
--- a/BUILD/build_mccge.sh
+++ b/BUILD/build_mccge.sh
@@ -556,7 +556,7 @@ parse_package()
package="pro"
;;
extended )
- package=""
+ package="extended"
;;
cge )
package="cge"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fba26ec1464..301855cf326 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -42,6 +42,13 @@ ADD_DEFINITIONS(-DSHAREDIR="share")
# Set debug options
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFORCE_INIT_OF_VARS")
+# Do not use SAFEMALLOC for Windows builds, as Debug CRT has the same functionality
+# Neither SAFE_MUTEX works on Windows and it has been explicitely undefined in
+# my_pthread.h
+IF(NOT WIN32)
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+ENDIF(NOT WIN32)
SET(localstatedir "C:\\mysql\\data")
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-huge.cnf.sh
@@ -55,9 +62,6 @@ CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-medium.cnf.sh
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-small.cnf.sh
${CMAKE_SOURCE_DIR}/support-files/my-small.ini @ONLY)
-
-ADD_DEFINITIONS(-D__NT__)
-
IF(CYBOZU)
ADD_DEFINITIONS(-DCYBOZU)
ENDIF(CYBOZU)
diff --git a/Makefile.am b/Makefile.am
index 0435489456b..53be49768de 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+# Copyright 2000-2008 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
@@ -24,7 +24,7 @@ EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \
SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
@readline_topdir@ sql-common scripts \
@pstack_dir@ \
- @sql_union_dirs@ unittest storage plugin \
+ @sql_union_dirs@ unittest \
@sql_server@ @man_dirs@ tests \
netware @libmysqld_dirs@ \
mysql-test support-files sql-bench \
@@ -137,46 +137,48 @@ test-force-full:
test-force-mem:
$(MAKE) force=--force mem=--mem test
+EXP = --experimental=collections/default.experimental
+
test-bt:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=normal --force --timer \
- --skip-ndbcluster --report-features
+ --skip-ndbcluster --report-features $(EXP)
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=ps --force --timer \
- --skip-ndbcluster --ps-protocol
+ --skip-ndbcluster --ps-protocol $(EXP)
-if [ -e bin/ndbd -o -e storage/ndb/src/kernel/ndbd ] ; then \
cd mysql-test ; \
MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=ndb+rpl_ndb+ps --force --timer \
- --ps-protocol --mysqld=--binlog-format=row --suite=ndb,rpl_ndb ; \
+ --ps-protocol --mysqld=--binlog-format=row --suite=ndb,rpl_ndb $(EXP) ; \
MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=ndb --force --timer \
- --with-ndbcluster-only ; \
+ --with-ndbcluster-only $(EXP) ; \
else \
echo "no program found for 'ndbcluster' tests - skipped testing" ; \
fi
-cd mysql-test ; MTR_BUILD_THREAD=auto \
- @PERL@ ./mysql-test-run.pl --force --comment=funcs1+ps --ps-protocol --reorder --suite=funcs_1
+ @PERL@ ./mysql-test-run.pl --force --comment=funcs1+ps --ps-protocol --reorder --suite=funcs_1 $(EXP)
-cd mysql-test ; MTR_BUILD_THREAD=auto \
- @PERL@ ./mysql-test-run.pl --force --comment=funcs2 --suite=funcs_2
+ @PERL@ ./mysql-test-run.pl --force --comment=funcs2 --suite=funcs_2 $(EXP)
-cd mysql-test ; MTR_BUILD_THREAD=auto \
- @PERL@ ./mysql-test-run.pl --force --comment=partitions --suite=parts
+ @PERL@ ./mysql-test-run.pl --force --comment=partitions --suite=parts $(EXP)
-cd mysql-test ; MTR_BUILD_THREAD=auto \
- @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress
+ @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress $(EXP)
-cd mysql-test ; MTR_BUILD_THREAD=auto \
- @PERL@ ./mysql-test-run.pl --force --comment=jp --suite=jp
+ @PERL@ ./mysql-test-run.pl --force --comment=jp --suite=jp $(EXP)
-if [ -d mysql-test/suite/nist ] ; then \
cd mysql-test ; MTR_BUILD_THREAD=auto \
- @PERL@ ./mysql-test-run.pl --comment=nist --force --suite=nist ; \
+ @PERL@ ./mysql-test-run.pl --comment=nist --force --suite=nist $(EXP) ; \
fi
-if [ -d mysql-test/suite/nist ] ; then \
cd mysql-test ; MTR_BUILD_THREAD=auto \
- @PERL@ ./mysql-test-run.pl --comment=nist+ps --force --suite=nist --ps-protocol ; \
+ @PERL@ ./mysql-test-run.pl --comment=nist+ps --force --suite=nist --ps-protocol $(EXP) ; \
fi
-if [ -e bin/mysqltest_embedded -o -e libmysqld/examples/mysqltest_embedded ] ; then \
cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=embedded --force --timer \
- --embedded-server --skip-rpl --skip-ndbcluster ; \
+ --embedded-server --skip-rpl --skip-ndbcluster $(EXP) ; \
else \
echo "no program found for 'embedded' tests - skipped testing" ; \
fi
@@ -184,22 +186,22 @@ test-bt:
test-bt-fast:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=ps --force --timer \
- --skip-ndbcluster --ps-protocol --report-features
+ --skip-ndbcluster --ps-protocol --report-features $(EXP)
-if [ -e bin/ndbd -o -e storage/ndb/src/kernel/ndbd ] ; then \
cd mysql-test ; \
MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=ndb --force --timer \
- --with-ndbcluster-only ; \
+ --with-ndbcluster-only $(EXP) ; \
else \
echo "no program found for 'ndbcluster' tests - skipped testing" ; \
fi
-cd mysql-test ; MTR_BUILD_THREAD=auto \
- @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress
+ @PERL@ ./mysql-test-run.pl --force --comment=stress --suite=stress $(EXP)
test-bt-debug:
-cd mysql-test ; MTR_BUILD_THREAD=auto \
@PERL@ ./mysql-test-run.pl --comment=debug --force --timer \
- --skip-ndbcluster --skip-rpl --report-features
+ --skip-ndbcluster --skip-rpl --report-features $(EXP)
test-bt-debug-fast:
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index e96437d40d0..28e4c354a69 100755
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -14,13 +14,6 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
-# We use the "mysqlclient_notls" library here just as safety, in case
-# any of the clients here would go beyond the client API and access the
-# Thread Local Storage directly.
-
-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}/zlib
${CMAKE_SOURCE_DIR}/extra/yassl/include
@@ -30,27 +23,27 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/strings)
ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc ../mysys/my_conio.c)
-TARGET_LINK_LIBRARIES(mysql mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysql mysqlclient)
ADD_EXECUTABLE(mysqltest mysqltest.cc)
SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS")
-TARGET_LINK_LIBRARIES(mysqltest mysqlclient mysys regex wsock32 dbug)
+TARGET_LINK_LIBRARIES(mysqltest mysqlclient mysys regex dbug)
ADD_EXECUTABLE(mysqlcheck mysqlcheck.c)
-TARGET_LINK_LIBRARIES(mysqlcheck mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysqlcheck mysqlclient)
ADD_EXECUTABLE(mysqldump mysqldump.c ../sql-common/my_user.c ../mysys/mf_getdate.c)
-TARGET_LINK_LIBRARIES(mysqldump mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysqldump mysqlclient)
ADD_EXECUTABLE(mysqlimport mysqlimport.c)
-TARGET_LINK_LIBRARIES(mysqlimport mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysqlimport mysqlclient)
ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c ../mysys/my_getpagesize.c)
-TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient)
ADD_DEPENDENCIES(mysql_upgrade GenFixPrivs)
ADD_EXECUTABLE(mysqlshow mysqlshow.c)
-TARGET_LINK_LIBRARIES(mysqlshow mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysqlshow mysqlclient)
ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc
../mysys/mf_tempdir.c
@@ -59,14 +52,14 @@ ADD_EXECUTABLE(mysqlbinlog mysqlbinlog.cc
../mysys/my_bitmap.c
../mysys/my_vle.c
../mysys/base64.c)
-TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysqlbinlog mysqlclient)
ADD_EXECUTABLE(mysqladmin mysqladmin.cc)
-TARGET_LINK_LIBRARIES(mysqladmin mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysqladmin mysqlclient)
ADD_EXECUTABLE(mysqlslap mysqlslap.c)
SET_SOURCE_FILES_PROPERTIES(mysqlslap.c PROPERTIES COMPILE_FLAGS "-DTHREADS")
-TARGET_LINK_LIBRARIES(mysqlslap mysqlclient mysys zlib wsock32 dbug)
+TARGET_LINK_LIBRARIES(mysqlslap mysqlclient mysys zlib dbug)
ADD_EXECUTABLE(echo echo.c)
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 82af7ca65f6..a01918caad4 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1909,7 +1909,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
return ERROR_STOP;
}
#endif
- if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
+ if (init_io_cache(file, my_fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
{
error("Failed to init IO cache.");
diff --git a/client/mysqldump.c b/client/mysqldump.c
index e9e3124b9cb..22d3f376e3e 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -3316,7 +3316,7 @@ static void dump_table(char *table, char *db)
{
if (length)
{
- if (!IS_NUM_FIELD(field))
+ if (!(field->flags & NUM_FLAG))
{
/*
"length * 2 + 2" is OK for both HEX and non-HEX modes:
@@ -3384,7 +3384,7 @@ static void dump_table(char *table, char *db)
}
if (row[i])
{
- if (!IS_NUM_FIELD(field))
+ if (!(field->flags & NUM_FLAG))
{
if (opt_xml)
{
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 92e9702aea0..ef38d760e5d 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2006 MySQL AB
+/* Copyright (C) 2000-2006 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
@@ -583,7 +583,7 @@ error:
counter--;
pthread_cond_signal(&count_threshhold);
pthread_mutex_unlock(&counter_mutex);
- my_thread_end();
+ mysql_thread_end();
return 0;
}
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index 70abfbb7136..0bbc15eb24e 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -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
@@ -1199,7 +1199,7 @@ get_options(int *argc,char ***argv)
if (opt_csv_str[0] == '-')
{
- csv_file= fileno(stdout);
+ csv_file= my_fileno(stdout);
}
else
{
@@ -1918,7 +1918,7 @@ end:
if (!opt_only_print)
mysql_close(mysql);
- my_thread_end();
+ mysql_thread_end();
pthread_mutex_lock(&counter_mutex);
thread_counter--;
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 81586c4ffc0..97fa15a1d5e 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1535,7 +1535,7 @@ void show_diff(DYNAMIC_STRING* ds,
else
diff_name = 0;
#else
- diff_name = "diff"; // Otherwise always assume it's called diff
+ diff_name = "diff"; /* Otherwise always assume it's called diff */
#endif
if (diff_name)
diff --git a/client/readline.cc b/client/readline.cc
index b32cb71b0de..73ce7c3b8c7 100644
--- a/client/readline.cc
+++ b/client/readline.cc
@@ -33,7 +33,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
if (!(line_buff=(LINE_BUFFER*)
my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
return 0;
- if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size))
+ if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size))
{
my_free(line_buff,MYF(0));
return 0;
diff --git a/configure.in b/configure.in
index 60a583fa25b..b5f3d46f3f4 100644
--- a/configure.in
+++ b/configure.in
@@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM
#
# When changing major version number please also check switch statement
# in client/mysqlbinlog.cc:check_master_version().
-AM_INIT_AUTOMAKE(mysql, 5.4.5-beta)
+AM_INIT_AUTOMAKE(mysql, 5.5.0-beta)
AM_CONFIG_HEADER([include/config.h:config.h.in])
PROTOCOL_VERSION=10
@@ -1665,13 +1665,14 @@ then
DEBUG_OPTIMIZE_CXX="-O"
OPTIMIZE_CXXFLAGS="$MAX_CXX_OPTIMIZE"
else
- DEBUG_CXXFLAGS="-g"
DEBUG_OPTIMIZE_CXX=""
case $SYSTEM_TYPE in
*solaris*)
+ DEBUG_CXXFLAGS="-g0"
OPTIMIZE_CXXFLAGS="-O1"
;;
*)
+ DEBUG_CXXFLAGS="-g"
OPTIMIZE_CXXFLAGS="-O"
;;
esac
@@ -2817,7 +2818,7 @@ server_scripts=
dnl This probably should be cleaned up more - for now the threaded
dnl client is just using plain-old libs.
-sql_client_dirs="strings regex mysys libmysql"
+sql_client_dirs="strings regex mysys dbug libmysql"
AM_CONDITIONAL(THREAD_SAFE_CLIENT, test "$THREAD_SAFE_CLIENT" != "no")
@@ -2845,15 +2846,20 @@ fi
AC_SUBST(netware_dir)
AM_CONDITIONAL(HAVE_NETWARE, test "$netware_dir" = "netware")
-if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
+if test "$with_server" != "no" -o "$THREAD_SAFE_CLIENT" != "no"
then
AC_DEFINE([THREAD], [1],
[Define if you want to have threaded code. This may be undef on client code])
# Avoid _PROGRAMS names
THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o"
AC_SUBST(THREAD_LOBJECTS)
+fi
+AM_CONDITIONAL(NEED_THREAD, test "$with_server" != "no" -o "$THREAD_SAFE_CLIENT" != "no")
+
+if test "$with_server" != "no"
+then
server_scripts="mysqld_safe mysql_install_db"
- sql_server_dirs="strings mysys dbug extra regex"
+ sql_server_dirs="strings mysys dbug extra regex storage plugin"
sql_server="vio sql"
fi
diff --git a/dbug/CMakeLists.txt b/dbug/CMakeLists.txt
index 8b27f79dcf4..fabb592dccc 100755
--- a/dbug/CMakeLists.txt
+++ b/dbug/CMakeLists.txt
@@ -18,7 +18,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/dbug)
SET(DBUG_SOURCES dbug.c factorial.c sanity.c)
IF(NOT SOURCE_SUBLIBS)
- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
ADD_LIBRARY(dbug ${DBUG_SOURCES})
ENDIF(NOT SOURCE_SUBLIBS)
diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt
index cec0db6a4ae..44c96ccbb86 100755
--- a/extra/CMakeLists.txt
+++ b/extra/CMakeLists.txt
@@ -14,13 +14,11 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
-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)
ADD_EXECUTABLE(comp_err comp_err.c)
-TARGET_LINK_LIBRARIES(comp_err debug dbug mysys strings zlib wsock32)
+TARGET_LINK_LIBRARIES(comp_err dbug mysys strings zlib)
GET_TARGET_PROPERTY(COMP_ERR_EXE comp_err LOCATION)
@@ -39,16 +37,16 @@ ADD_CUSTOM_TARGET(GenError
DEPENDS ${PROJECT_SOURCE_DIR}/include/mysqld_error.h)
ADD_EXECUTABLE(my_print_defaults my_print_defaults.c)
-TARGET_LINK_LIBRARIES(my_print_defaults strings mysys debug dbug taocrypt wsock32)
+TARGET_LINK_LIBRARIES(my_print_defaults strings mysys dbug taocrypt)
ADD_EXECUTABLE(perror perror.c)
-TARGET_LINK_LIBRARIES(perror strings mysys debug dbug wsock32)
+TARGET_LINK_LIBRARIES(perror strings mysys dbug)
ADD_EXECUTABLE(resolveip resolveip.c)
-TARGET_LINK_LIBRARIES(resolveip strings mysys debug dbug wsock32)
+TARGET_LINK_LIBRARIES(resolveip strings mysys dbug)
ADD_EXECUTABLE(replace replace.c)
-TARGET_LINK_LIBRARIES(replace strings mysys debug dbug wsock32)
+TARGET_LINK_LIBRARIES(replace strings mysys dbug)
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("myTest" "asInvoker")
diff --git a/include/config-win.h b/include/config-win.h
index af4915440b1..725b4fdf07b 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -27,6 +27,9 @@
#include <fcntl.h>
#include <io.h>
#include <malloc.h>
+#include <sys/stat.h>
+#include <process.h> /* getpid()*/
+
#define HAVE_SMEM 1
@@ -65,7 +68,6 @@
#endif
/* File and lock constants */
-#define O_SHARE 0x1000 /* Open file in sharing mode */
#ifdef __BORLANDC__
#define F_RDLCK LK_NBLCK /* read lock */
#define F_WRLCK LK_NBRLCK /* write lock */
@@ -175,7 +177,7 @@ typedef uint rf_SetTimer;
#define SIZEOF_CHARP 4
#endif
#define HAVE_BROKEN_NETINET_INCLUDES
-#ifdef __NT__
+#ifdef _WIN32
#define HAVE_NAMED_PIPE /* We can only create pipes on NT */
#endif
@@ -288,11 +290,6 @@ inline ulonglong double2ulonglong(double d)
#define strcasecmp stricmp
#define strncasecmp strnicmp
-#ifndef __NT__
-#undef FILE_SHARE_DELETE
-#define FILE_SHARE_DELETE 0 /* Not implemented on Win 98/ME */
-#endif
-
#ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */
#define _snprintf snprintf
@@ -336,13 +333,13 @@ inline ulonglong double2ulonglong(double d)
#define FN_DEVCHAR ':'
#define FN_NETWORK_DRIVES /* Uses \\ to indicate network drives */
#define FN_NO_CASE_SENCE /* Files are not case-sensitive */
-#define OS_FILE_LIMIT 2048
+#define OS_FILE_LIMIT UINT_MAX /* No limit*/
#define DO_NOT_REMOVE_THREAD_WRAPPERS
#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V))
#define thread_safe_decrement(V,L) InterlockedDecrement((long*) &(V))
/* The following is only used for statistics, so it should be good enough */
-#ifdef __NT__ /* This should also work on Win98 but .. */
+#ifdef _WIN32
#define thread_safe_add(V,C,L) InterlockedExchangeAdd((long*) &(V),(C))
#define thread_safe_sub(V,C,L) InterlockedExchangeAdd((long*) &(V),-(long) (C))
#endif
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 451c8db549b..f6503a54935 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -87,6 +87,7 @@ extern MY_UNI_CTYPE my_uni_ctype[256];
#define MY_CS_CSSORT 1024 /* if case sensitive sort order */
#define MY_CS_HIDDEN 2048 /* don't display in SHOW */
#define MY_CS_PUREASCII 4096 /* if a charset is pure ascii */
+#define MY_CS_NONASCII 8192 /* if not ASCII-compatible */
#define MY_CHARSET_UNDEFINED 0
/* Character repertoire flags */
@@ -474,6 +475,7 @@ my_bool my_charset_is_ascii_based(CHARSET_INFO *cs);
my_bool my_charset_is_8bit_pure_ascii(CHARSET_INFO *cs);
uint my_charset_repertoire(CHARSET_INFO *cs);
+my_bool my_charset_is_ascii_compatible(CHARSET_INFO *cs);
#define _MY_U 01 /* Upper case */
#define _MY_L 02 /* Lower case */
diff --git a/include/my_dir.h b/include/my_dir.h
index 06509a3af19..90d708ac811 100644
--- a/include/my_dir.h
+++ b/include/my_dir.h
@@ -69,7 +69,11 @@ typedef struct my_stat
#else
+#if(_MSC_VER)
+#define MY_STAT struct _stati64 /* 64 bit file size */
+#else
#define MY_STAT struct stat /* Orginal struct have what we need */
+#endif
#endif /* USE_MY_STAT_STRUCT */
diff --git a/include/my_global.h b/include/my_global.h
index e7d0026ac53..0c02dd6dcac 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -755,7 +755,41 @@ typedef SOCKET_SIZE_TYPE size_socket;
#define FN_LIBCHAR '/'
#define FN_ROOTDIR "/"
#endif
-#define MY_NFILE 64 /* This is only used to save filenames */
+
+/*
+ MY_FILE_MIN is Windows speciality and is used to quickly detect
+ the mismatch of CRT and mysys file IO usage on Windows at runtime.
+ CRT file descriptors can be in the range 0-2047, whereas descriptors returned
+ by my_open() will start with 2048. If a file descriptor with value less then
+ MY_FILE_MIN is passed to mysys IO function, chances are it stemms from
+ open()/fileno() and not my_open()/my_fileno.
+
+ For Posix, mysys functions are light wrappers around libc, and MY_FILE_MIN
+ is logically 0.
+*/
+
+#ifdef _WIN32
+#define MY_FILE_MIN 2048
+#else
+#define MY_FILE_MIN 0
+#endif
+
+/*
+ MY_NFILE is the default size of my_file_info array.
+
+ It is larger on Windows, because it all file handles are stored in my_file_info
+ Default size is 16384 and this should be enough for most cases.If it is not
+ enough, --max-open-files with larger value can be used.
+
+ For Posix , my_file_info array is only used to store filenames for
+ error reporting and its size is not a limitation for number of open files.
+*/
+#ifdef _WIN32
+#define MY_NFILE (16384 + MY_FILE_MIN)
+#else
+#define MY_NFILE 64
+#endif
+
#ifndef OS_FILE_LIMIT
#define OS_FILE_LIMIT 65535
#endif
@@ -792,9 +826,8 @@ typedef SOCKET_SIZE_TYPE size_socket;
/* Some things that this system doesn't have */
#define NO_HASH /* Not needed anymore */
-#ifdef __WIN__
-#define NO_DIR_LIBRARY /* Not standar dir-library */
-#define USE_MY_STAT_STRUCT /* For my_lib */
+#ifdef _WIN32
+#define NO_DIR_LIBRARY /* Not standard dir-library */
#endif
/* Some defines of functions for portability */
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 9e2c2111b8e..b4fe1203d2b 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -31,7 +31,7 @@ extern "C" {
#if defined(__WIN__)
typedef CRITICAL_SECTION pthread_mutex_t;
-typedef HANDLE pthread_t;
+typedef DWORD pthread_t;
typedef struct thread_attr {
DWORD dwStackSize ;
DWORD dwCreatingFlag ;
@@ -64,8 +64,7 @@ typedef struct {
typedef int pthread_mutexattr_t;
-#define win_pthread_self my_thread_var->pthread_self
-#define pthread_self() win_pthread_self
+#define pthread_self() GetCurrentThreadId()
#define pthread_handler_t EXTERNC void * __cdecl
typedef void * (__cdecl *pthread_handler)(void *);
@@ -99,8 +98,7 @@ struct timespec {
(ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \
}
-void win_pthread_init(void);
-int win_pthread_setspecific(void *A,void *B,uint length);
+
int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *);
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
@@ -117,42 +115,25 @@ int pthread_attr_destroy(pthread_attr_t *connect_att);
struct tm *localtime_r(const time_t *timep,struct tm *tmp);
struct tm *gmtime_r(const time_t *timep,struct tm *tmp);
+void pthread_exit(void *a);
+int pthread_join(pthread_t thread, void **value_ptr);
-void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#define ETIMEDOUT 145 /* Win32 doesn't have this */
-#define getpid() GetCurrentThreadId()
#define HAVE_LOCALTIME_R 1
#define _REENTRANT 1
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
-/*
- Windows has two ways to use thread local storage. The most efficient
- is using __declspec(thread), but that does not work properly when
- used in a .dll that is loaded at runtime, after program load. So for
- libmysql.dll and libmysqld.dll we define USE_TLS in order to use the
- TlsXxx() API instead, which works in all cases.
-*/
-#ifdef USE_TLS /* For LIBMYSQL.DLL */
+
#undef SAFE_MUTEX /* This will cause conflicts */
#define pthread_key(T,V) DWORD V
#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
#define pthread_key_delete(A) TlsFree(A)
+#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V)))
+#define pthread_setspecific(A,B) (!TlsSetValue((A),(B)))
#define pthread_getspecific(A) (TlsGetValue(A))
#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V))
-#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V)))
-#define pthread_setspecific(A,B) (!TlsSetValue((A),(B)))
-#else
-#define pthread_key(T,V) __declspec(thread) T V
-#define pthread_key_create(A,B) pthread_dummy(0)
-#define pthread_key_delete(A) pthread_dummy(0)
-#define pthread_getspecific(A) (&(A))
-#define my_pthread_getspecific(T,A) (&(A))
-#define my_pthread_getspecific_ptr(T,V) (V)
-#define my_pthread_setspecific_ptr(T,V) ((T)=(V),0)
-#define pthread_setspecific(A,B) win_pthread_setspecific(&(A),(B),sizeof(A))
-#endif /* USE_TLS */
#define pthread_equal(A,B) ((A) == (B))
#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0)
@@ -163,7 +144,6 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B))
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
-#define pthread_join(A,B) (WaitForSingleObject((A), INFINITE) != WAIT_OBJECT_0)
/* Dummy defines for easier code */
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
diff --git a/include/my_sys.h b/include/my_sys.h
index cb9a24bbd7f..4b93dc0e364 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -39,6 +39,17 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MYSYS_PROGRAM_DONT_USE_CURSES() { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;}
#define MY_INIT(name); { my_progname= name; my_init(); }
+/**
+ Max length of an error message generated by mysys utilities.
+ Some mysys functions produce error messages. These mostly go
+ to stderr.
+ This constant defines the size of the buffer used to format
+ the message. It should be kept in sync with MYSQL_ERRMSG_SIZE,
+ since sometimes mysys errors are stored in the server diagnostics
+ area, and we would like to avoid unexpected truncation.
+*/
+#define MYSYS_ERRMSG_SIZE (512)
+
#define MY_FILE_ERROR ((size_t) -1)
/* General bitmaps for my_func's */
@@ -90,8 +101,6 @@ extern int NEAR my_errno; /* Last error in mysys */
#define ME_COLOUR2 ((2 << ME_HIGHBYTE))
#define ME_COLOUR3 ((3 << ME_HIGHBYTE))
#define ME_FATALERROR 1024 /* Fatal statement error */
-#define ME_NO_WARNING_FOR_ERROR 2048 /* Don't push a warning for error */
-#define ME_NO_SP_HANDLER 4096 /* Don't call stored routine error handlers */
/* Bits in last argument to fn_format */
#define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */
@@ -210,8 +219,8 @@ extern int errno; /* declare errno */
extern char *home_dir; /* Home directory for user */
extern const char *my_progname; /* program-name (printed in errors) */
extern char NEAR curr_dir[]; /* Current directory for user */
-extern int (*error_handler_hook)(uint my_err, const char *str,myf MyFlags);
-extern int (*fatal_error_handler_hook)(uint my_err, const char *str,
+extern void (*error_handler_hook)(uint my_err, const char *str,myf MyFlags);
+extern void (*fatal_error_handler_hook)(uint my_err, const char *str,
myf MyFlags);
extern uint my_file_limit;
extern ulong my_thread_stack_size;
@@ -311,9 +320,13 @@ enum file_type
struct st_my_file_info
{
- char * name;
- enum file_type type;
-#if defined(THREAD) && !defined(HAVE_PREAD)
+ char *name;
+#ifdef _WIN32
+ HANDLE fhandle; /* win32 file handle */
+ int oflag; /* open flags, e.g O_APPEND */
+#endif
+ enum file_type type;
+#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32)
pthread_mutex_t mutex;
#endif
};
@@ -618,22 +631,29 @@ extern void *my_memmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen);
-#ifdef __WIN__
-extern int my_access(const char *path, int amode);
-extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
+#ifdef _WIN32
+extern int my_access(const char *path, int amode);
#else
#define my_access access
#endif
+
extern int check_if_legal_filename(const char *path);
extern int check_if_legal_tablename(const char *path);
-#if defined(__WIN__) && defined(__NT__)
+#ifdef _WIN32
extern int nt_share_delete(const char *name,myf MyFlags);
#define my_delete_allow_opened(fname,flags) nt_share_delete((fname),(flags))
#else
#define my_delete_allow_opened(fname,flags) my_delete((fname),(flags))
#endif
+#ifdef _WIN32
+/* Windows-only functions (CRT equivalents)*/
+extern File my_sopen(const char *path, int oflag, int shflag, int pmode);
+extern HANDLE my_get_osfhandle(File fd);
+extern void my_osmaperr(unsigned long last_error);
+#endif
+
#ifndef TERMINATE
extern void TERMINATE(FILE *file, uint flag);
#endif
@@ -642,19 +662,20 @@ extern void wait_for_free_space(const char *filename, int errors);
extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags);
extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags);
extern int my_fclose(FILE *fd,myf MyFlags);
+extern File my_fileno(FILE *fd);
extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags);
extern int my_sync(File fd, myf my_flags);
extern int my_sync_dir(const char *dir_name, myf my_flags);
extern int my_sync_dir_by_file(const char *file_name, myf my_flags);
-extern int my_error _VARARGS((int nr,myf MyFlags, ...));
-extern int my_printf_error _VARARGS((uint my_err, const char *format,
- myf MyFlags, ...))
- ATTRIBUTE_FORMAT(printf, 2, 4);
+extern void my_error _VARARGS((int nr,myf MyFlags, ...));
+extern void my_printf_error _VARARGS((uint my_err, const char *format,
+ myf MyFlags, ...))
+ ATTRIBUTE_FORMAT(printf, 2, 4);
extern int my_error_register(const char **errmsgs, int first, int last);
extern const char **my_error_unregister(int first, int last);
-extern int my_message(uint my_err, const char *str,myf MyFlags);
-extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags);
-extern int my_message_curses(uint my_err, const char *str,myf MyFlags);
+extern void my_message(uint my_err, const char *str,myf MyFlags);
+extern void my_message_no_curses(uint my_err, const char *str,myf MyFlags);
+extern void my_message_curses(uint my_err, const char *str,myf MyFlags);
extern my_bool my_init(void);
extern void my_end(int infoflag);
extern int my_redel(const char *from, const char *to, int MyFlags);
diff --git a/include/mysql.h b/include/mysql.h
index d114afb6c93..70faf3cb2c1 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -86,9 +86,11 @@ extern char *mysql_unix_port;
#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
#define IS_BLOB(n) ((n) & BLOB_FLAG)
-#define IS_NUM(t) ((t) <= MYSQL_TYPE_INT24 || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL)
-#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG)
-#define INTERNAL_NUM_FIELD(f) (((f)->type <= MYSQL_TYPE_INT24 && ((f)->type != MYSQL_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == MYSQL_TYPE_YEAR)
+/**
+ Returns true if the value is a number which does not need quotes for
+ the sql_lex.cc parser to parse correctly.
+*/
+#define IS_NUM(t) (((t) <= MYSQL_TYPE_INT24 && (t) != MYSQL_TYPE_TIMESTAMP) || (t) == MYSQL_TYPE_YEAR || (t) == MYSQL_TYPE_NEWDECIMAL)
#define IS_LONGDATA(t) ((t) >= MYSQL_TYPE_TINY_BLOB && (t) <= MYSQL_TYPE_STRING)
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
index 55138e4aa06..805551b7ee3 100755
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
@@ -14,8 +14,6 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
-SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
-SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
# Note that we don't link with the libraries "strings" or "mysys"
# here, instead we recompile the files needed and include them
@@ -98,33 +96,17 @@ 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})
-
-# Need to set USE_TLS for building the DLL, since __declspec(thread)
-# approach to thread local storage does not work properly in DLLs.
-#
-# The static library might be used to form another DLL, as is the case
-# with the ODBC driver, so it has to be compiled with USE_TLS as well.
-#
-# We create a third library without USE_TLS for internal use. We can't
-# be sure that some client application part of this build doesn't go
-# beond the documented API, and try access the Thread Local Storage.
-# The "_notls" means no Tls*() functions used, i.e. "static" TLS.
+ ../mysys/my_getsystime.c ../mysys/my_sync.c ../mysys/my_winerr.c ../mysys/my_winfile.c ${LIB_SOURCES})
+
+
ADD_LIBRARY(mysqlclient STATIC ${CLIENT_SOURCES})
ADD_DEPENDENCIES(mysqlclient GenError)
TARGET_LINK_LIBRARIES(mysqlclient)
-ADD_LIBRARY(mysqlclient_notls STATIC ${CLIENT_SOURCES})
-ADD_DEPENDENCIES(mysqlclient_notls GenError)
-TARGET_LINK_LIBRARIES(mysqlclient_notls)
-
ADD_LIBRARY(libmysql SHARED ${CLIENT_SOURCES} dll.c libmysql.def)
-IF(WIN32)
- SET_TARGET_PROPERTIES(libmysql mysqlclient PROPERTIES COMPILE_FLAGS "-DUSE_TLS")
-ENDIF(WIN32)
ADD_DEPENDENCIES(libmysql GenError)
-TARGET_LINK_LIBRARIES(libmysql wsock32)
+TARGET_LINK_LIBRARIES(libmysql)
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("myTest" "asInvoker")
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 8500d73863a..bce14b38338 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -13,15 +13,6 @@
# 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")
-
-# Need to set USE_TLS, since __declspec(thread) approach to thread local
-# storage does not work properly in DLLs.
-IF(WIN32)
- ADD_DEFINITIONS(-DUSE_TLS)
-ENDIF(WIN32)
-
ADD_DEFINITIONS(-DMYSQL_SERVER -DEMBEDDED_LIBRARY -DHAVE_DLOPEN)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
@@ -139,6 +130,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.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/sql_signal.cc
${GEN_SOURCES}
${LIB_SOURCES})
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index 171009c34f6..80a7c74a266 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -77,7 +77,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
sql_tablespace.cc \
rpl_injector.cc my_user.c partition_info.cc \
- sql_servers.cc event_parse_data.cc
+ sql_servers.cc event_parse_data.cc sql_signal.cc
libmysqld_int_a_SOURCES= $(libmysqld_sources)
nodist_libmysqld_int_a_SOURCES= $(libmysqlsources) $(sqlsources)
diff --git a/libmysqld/emb_qcache.cc b/libmysqld/emb_qcache.cc
index b4eddf39c1f..5cbced8a8ff 100644
--- a/libmysqld/emb_qcache.cc
+++ b/libmysqld/emb_qcache.cc
@@ -483,7 +483,8 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src)
*prev_row= NULL;
data->embedded_info->prev_ptr= prev_row;
return_ok:
- net_send_eof(thd, thd->server_status, thd->total_warn_count);
+ net_send_eof(thd, thd->server_status,
+ thd->warning_info->statement_warn_count());
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
diff --git a/libmysqld/examples/CMakeLists.txt b/libmysqld/examples/CMakeLists.txt
index 5194836a728..e4b6533f8a2 100644
--- a/libmysqld/examples/CMakeLists.txt
+++ b/libmysqld/examples/CMakeLists.txt
@@ -20,9 +20,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/extra/yassl/include)
# Currently does not work with DBUG, there are missing symbols reported.
-IF(WIN32)
- ADD_DEFINITIONS(-DUSE_TLS)
-ENDIF(WIN32)
ADD_DEFINITIONS(-DEMBEDDED_LIBRARY)
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index d4a200c07b2..f01a6b3f3df 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -112,7 +112,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
/* Clear result variables */
thd->clear_error();
- thd->main_da.reset_diagnostics_area();
+ thd->stmt_da->reset_diagnostics_area();
mysql->affected_rows= ~(my_ulonglong) 0;
mysql->field_count= 0;
net_clear_error(net);
@@ -217,7 +217,7 @@ static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
stmt->stmt_id= thd->client_stmt_id;
stmt->param_count= thd->client_param_count;
stmt->field_count= 0;
- mysql->warning_count= thd->total_warn_count;
+ mysql->warning_count= thd->warning_info->statement_warn_count();
if (thd->first_data)
{
@@ -402,7 +402,7 @@ static void emb_free_embedded_thd(MYSQL *mysql)
static const char * emb_read_statistics(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
- return thd->is_error() ? thd->main_da.message() : "";
+ return thd->is_error() ? thd->stmt_da->message() : "";
}
@@ -703,9 +703,10 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
err:
{
NET *net= &mysql->net;
- strmake(net->last_error, thd->main_da.message(), sizeof(net->last_error)-1);
+ strmake(net->last_error, thd->stmt_da->message(),
+ sizeof(net->last_error)-1);
memcpy(net->sqlstate,
- mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
+ mysql_errno_to_sqlstate(thd->stmt_da->sql_errno()),
sizeof(net->sqlstate)-1);
}
return result;
@@ -729,8 +730,8 @@ void THD::clear_data_list()
void THD::clear_error()
{
- if (main_da.is_error())
- main_da.reset_diagnostics_area();
+ if (stmt_da->is_error())
+ stmt_da->reset_diagnostics_area();
}
static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
@@ -804,7 +805,7 @@ MYSQL_DATA *THD::alloc_new_dataset()
static
bool
-write_eof_packet(THD *thd, uint server_status, uint total_warn_count)
+write_eof_packet(THD *thd, uint server_status, uint statement_warn_count)
{
if (!thd->mysql) // bootstrap file handling
return FALSE;
@@ -821,7 +822,7 @@ write_eof_packet(THD *thd, uint server_status, uint total_warn_count)
is cleared between substatements, and mysqltest gets confused
*/
thd->cur_data->embedded_info->warning_count=
- (thd->spcont ? 0 : min(total_warn_count, 65535));
+ (thd->spcont ? 0 : min(statement_warn_count, 65535));
return FALSE;
}
@@ -951,7 +952,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
client_field->catalog= dup_str_aux(field_alloc, "def", 3, cs, thd_cs);
client_field->catalog_length= 3;
- if (INTERNAL_NUM_FIELD(client_field))
+ if (IS_NUM(client_field->type))
client_field->flags|= NUM_FLAG;
if (flags & (int) Protocol::SEND_DEFAULTS)
@@ -978,7 +979,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
}
if (flags & SEND_EOF)
- write_eof_packet(thd, thd->server_status, thd->total_warn_count);
+ write_eof_packet(thd, thd->server_status,
+ thd->warning_info->statement_warn_count());
DBUG_RETURN(prepare_for_send(list));
err:
@@ -1040,25 +1042,24 @@ bool Protocol_binary::write()
bool
net_send_ok(THD *thd,
- uint server_status, uint total_warn_count,
- ha_rows affected_rows, ulonglong id, const char *message)
+ uint server_status, uint statement_warn_count,
+ ulonglong affected_rows, ulonglong id, const char *message)
{
DBUG_ENTER("emb_net_send_ok");
MYSQL_DATA *data;
- bool error;
MYSQL *mysql= thd->mysql;
if (!mysql) // bootstrap file handling
DBUG_RETURN(FALSE);
if (!(data= thd->alloc_new_dataset()))
- return TRUE;
+ DBUG_RETURN(TRUE);
data->embedded_info->affected_rows= affected_rows;
data->embedded_info->insert_id= id;
if (message)
strmake(data->embedded_info->info, message,
sizeof(data->embedded_info->info)-1);
- error= write_eof_packet(thd, server_status, total_warn_count);
+ bool error= write_eof_packet(thd, server_status, statement_warn_count);
thd->cur_data= 0;
DBUG_RETURN(error);
}
@@ -1075,15 +1076,16 @@ net_send_ok(THD *thd,
*/
bool
-net_send_eof(THD *thd, uint server_status, uint total_warn_count)
+net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
{
- bool error= write_eof_packet(thd, server_status, total_warn_count);
+ bool error= write_eof_packet(thd, server_status, statement_warn_count);
thd->cur_data= 0;
return error;
}
-bool net_send_error_packet(THD *thd, uint sql_errno, const char *err)
+bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
+ const char *sqlstate)
{
MYSQL_DATA *data= thd->cur_data;
struct embedded_query_result *ei;
@@ -1100,7 +1102,7 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err)
ei= data->embedded_info;
ei->last_errno= sql_errno;
strmake(ei->info, err, sizeof(ei->info)-1);
- strmov(ei->sqlstate, mysql_errno_to_sqlstate(sql_errno));
+ strmov(ei->sqlstate, sqlstate);
ei->server_status= thd->server_status;
thd->cur_data= 0;
return FALSE;
@@ -1173,3 +1175,27 @@ int vprint_msg_to_log(enum loglevel level __attribute__((unused)),
mysql_server_last_errno= CR_UNKNOWN_ERROR;
return 0;
}
+
+
+bool Protocol::net_store_data(const uchar *from, size_t length,
+ CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
+{
+ uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
+ uint dummy_error;
+ char *field_buf;
+ if (!thd->mysql) // bootstrap file handling
+ return false;
+
+ if (!(field_buf= (char*) alloc_root(alloc, conv_length + sizeof(uint) + 1)))
+ return true;
+ *next_field= field_buf + sizeof(uint);
+ length= copy_and_convert(*next_field, conv_length, to_cs,
+ (const char*) from, length, from_cs, &dummy_error);
+ *(uint *) field_buf= length;
+ (*next_field)[length]= 0;
+ if (next_mysql_field->max_length < length)
+ next_mysql_field->max_length= length;
+ ++next_field;
+ ++next_mysql_field;
+ return false;
+}
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index aff9391e015..31ad8844650 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -99,7 +99,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
char name_buff[USERNAME_LENGTH];
DBUG_ENTER("mysql_real_connect");
- DBUG_PRINT("enter",("host: %s db: %s user: %s",
+ DBUG_PRINT("enter",("host: %s db: %s user: %s (libmysqld)",
host ? host : "(Null)",
db ? db : "(Null)",
user ? user : "(Null)"));
diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental
index 85c14c6f67a..6d5655ba499 100644
--- a/mysql-test/collections/default.experimental
+++ b/mysql-test/collections/default.experimental
@@ -2,18 +2,79 @@
# in alphabetical order. This also helps with merge conflict resolution.
binlog.binlog_tmp_table* # Bug#45578:2009-07-10 alik Test binlog_tmp_table fails ramdonly on PB2: Unknown table 't2'
+
funcs_1.charset_collation_1 # depends on compile-time decisions
+
innodb.innodb_information_schema # Bug#47449 2009-09-19 alik main.information_schema and innodb.innodb_information_schema fail sporadically
+
main.ctype_gbk_binlog @solaris # Bug#46010: main.ctype_gbk_binlog fails sporadically : Table 't2' already exists
main.information_schema # Bug#47449 2009-09-19 alik main.information_schema and innodb.innodb_information_schema fail sporadically
+main.innodb-autoinc # Bug#44030 2009-09-24 alik Marking innodb-autoinc experimental while waiting for the patch to be merged
main.lock_multi_bug38499 # Bug#47448 2009-09-19 alik main.lock_multi_bug38499 times out sporadically
-main.plugin* @solaris # Bug#47146 Linking problem with example plugin when dtrace enabled
-main.plugin_load @solaris # Bug#47146
+main.lock_multi_bug38691 @solaris # Bug#47792 2009-10-02 alik main.lock_multi_bug38691 times out sporadically on Solaris 10
+main.log_tables # Bug#47924 2009-10-08 alik main.log_tables times out sporadically
+main.plugin # Bug#47146 Linking problem with example plugin when dtrace enabled
+main.plugin_load # Bug#47146
+
rpl.rpl_get_master_version_and_clock* # Bug#46931 2009-08-26 alik rpl.rpl_get_master_version_and_clock fails on hpux11.31
rpl.rpl_innodb_bug28430* @solaris # Bug#46029
+rpl.rpl_innodb_bug30888* @solaris # Bug#47646 2009-09-25 alik rpl.rpl_innodb_bug30888 fails sporadically on Solaris
rpl.rpl_plugin_load* @solaris # Bug#47146
rpl.rpl_row_create_table* # Bug#45576: rpl_row_create_table fails on PB2
-rpl_ndb.rpl_ndb_log # Bug#38998
+rpl.rpl_log_pos* # Bug#47743 2009-10-02 alik rpl.rpl_log_pos fails sporadically
+rpl.rpl_trigger* # Bug#46656 2009-09-25 alik InnoDB plugin: memory leaks (Valgrind)
+
+# Declare all NDB-tests in ndb and rpl_ndb test suites experimental.
+# Usually the test cases from ndb and rpl_ndb test suites are not run in PB,
+# but they run by gcov.
+#
+
+ndb.*
+rpl_ndb.*
+
+# Declare all NDB-tests in other test suites experimental.
+
+stress.ddl_ndb
+
+sys_vars.ndb_log_update_as_write_basic
+sys_vars.have_ndbcluster_basic
+sys_vars.ndb_log_updated_only_basic
+
+funcs_1.ndb_storedproc_10
+funcs_1.ndb_bitdata
+funcs_1.ndb_trig_03
+funcs_1.ndb_trig_0102
+funcs_1.is_tables_ndb
+funcs_1.is_columns_ndb
+funcs_1.ndb_trig_0407
+funcs_1.ndb_trig_1011ext
+funcs_1.ndb_storedproc_06
+funcs_1.ndb_views
+funcs_1.is_cml_ndb
+funcs_1.ndb_storedproc_02
+funcs_1.ndb_storedproc_03
+funcs_1.ndb_trig_03e
+funcs_1.is_engines_ndb
+funcs_1.ndb_trig_08
+funcs_1.ndb_storedproc_07
+funcs_1.ndb_storedproc_08
+funcs_1.ndb_func_view
+funcs_1.ndb_trig_09
+funcs_1.ndb_cursors
+
+funcs_2.ndb_charset
-ndb.n* # Consider all NDB tests experimental.
-rpl_ndb.r* # Consider all NDB tests experimental.
+parts.partition_engine_ndb
+parts.ndb_dd_backuprestore
+parts.partition_value_ndb
+parts.partition_mgm_lc2_ndb
+parts.partition_alter1_2_ndb
+parts.partition_alter1_1_ndb
+parts.part_supported_sql_func_ndb
+parts.partition_int_ndb
+parts.partition_mgm_lc1_ndb
+parts.partition_auto_increment_ndb
+parts.partition_syntax_ndb
+parts.partition_alter1_1_2_ndb
+parts.partition_basic_ndb
+parts.partition_mgm_lc0_ndb
diff --git a/mysql-test/collections/mysql-next-mr.push b/mysql-test/collections/mysql-next-mr.push
new file mode 100644
index 00000000000..99ff6f21673
--- /dev/null
+++ b/mysql-test/collections/mysql-next-mr.push
@@ -0,0 +1,5 @@
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=n_mix --mysqld=--binlog-format=mixed --suite=main,binlog,innodb,federated,rpl
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --ps-protocol --mysqld=--binlog-format=row --suite=main,binlog,innodb,federated,rpl
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=embedded --embedded --suite=main,binlog,innodb,federated,rpl
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=funcs_1 --suite=funcs_1
diff --git a/mysql-test/collections/mysql-trunk.push b/mysql-test/collections/mysql-trunk.push
new file mode 100644
index 00000000000..99ff6f21673
--- /dev/null
+++ b/mysql-test/collections/mysql-trunk.push
@@ -0,0 +1,5 @@
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=n_mix --mysqld=--binlog-format=mixed --suite=main,binlog,innodb,federated,rpl
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=ps_row --ps-protocol --mysqld=--binlog-format=row --suite=main,binlog,innodb,federated,rpl
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=embedded --embedded --suite=main,binlog,innodb,federated,rpl
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=rpl_binlog_row --mysqld=--binlog-format=row --suite=rpl,binlog
+perl mysql-test-run.pl --timer --force --parallel=auto --experimental=collections/default.experimental --comment=funcs_1 --suite=funcs_1
diff --git a/mysql-test/include/wait_for_slave_param.inc b/mysql-test/include/wait_for_slave_param.inc
index 82e57922913..1e690bdfe9c 100644
--- a/mysql-test/include/wait_for_slave_param.inc
+++ b/mysql-test/include/wait_for_slave_param.inc
@@ -49,6 +49,8 @@ if (!$_slave_timeout_counter)
{
let $_slave_timeout_counter= 3000;
}
+# Save resulting counter for later use.
+let $slave_tcnt= $_slave_timeout_counter;
let $_slave_param_comparison= $slave_param_comparison;
if (`SELECT '$_slave_param_comparison' = ''`)
@@ -70,7 +72,7 @@ while (`SELECT NOT('$_show_slave_status_value' $_slave_param_comparison '$slave_
# This has to be outside the loop until BUG#41913 has been fixed
if (!$_slave_timeout_counter)
{
- --echo **** ERROR: timeout after $slave_timeout seconds while waiting for slave parameter $slave_param $_slave_param_comparison $slave_param_value ****
+ --echo **** ERROR: timeout after $slave_tcnt deci-seconds while waiting for slave parameter $slave_param $_slave_param_comparison $slave_param_value ****
if (`SELECT '$slave_error_message' != ''`)
{
--echo Message: $slave_error_message
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index c30fb8ce2de..5b58d2e6733 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -818,7 +818,6 @@ sub command_line_setup {
'combination=s' => \@opt_combinations,
'skip-combinations' => \&collect_option,
'experimental=s' => \$opt_experimental,
- 'skip-im' => \&ignore_option,
# Specify ports
'build-thread|mtr-build-thread=i' => \$opt_build_thread,
diff --git a/mysql-test/r/bench_count_distinct.result b/mysql-test/r/bench_count_distinct.result
index 79e12afd237..8b67e4be38a 100644
--- a/mysql-test/r/bench_count_distinct.result
+++ b/mysql-test/r/bench_count_distinct.result
@@ -5,7 +5,7 @@ count(distinct n)
100
explain extended select count(distinct n) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 index NULL n 4 NULL 200 100.00 Using index
+1 SIMPLE t1 range NULL n 4 NULL 10 100.00 Using index for group-by
Warnings:
Note 1003 select count(distinct `test`.`t1`.`n`) AS `count(distinct n)` from `test`.`t1`
drop table t1;
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index 4a5b8fcf4aa..6b0954655e9 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -362,12 +362,12 @@ select cast(19999999999999999999 as signed);
cast(19999999999999999999 as signed)
9223372036854775807
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select cast(-19999999999999999999 as signed);
cast(-19999999999999999999 as signed)
-9223372036854775808
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select -9223372036854775808;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def -9223372036854775808 8 20 20 N 32897 0 63
@@ -385,7 +385,7 @@ def -((9223372036854775808)) 8 20 20 N 32897 0 63
-9223372036854775808
select -(-(9223372036854775808));
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def -(-(9223372036854775808)) 246 21 19 N 129 0 63
+def -(-(9223372036854775808)) 246 21 19 N 32897 0 63
-(-(9223372036854775808))
9223372036854775808
select --9223372036854775808, ---9223372036854775808, ----9223372036854775808;
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index dd61396e485..c53de220b60 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -380,7 +380,7 @@ select cast(s1 as decimal(7,2)) from t1;
cast(s1 as decimal(7,2))
99999.99
Warnings:
-Error 1264 Out of range value for column 'cast(s1 as decimal(7,2))' at row 1
+Warning 1264 Out of range value for column 'cast(s1 as decimal(7,2))' at row 1
drop table t1;
CREATE TABLE t1 (v varchar(10), tt tinytext, t text,
mt mediumtext, lt longtext);
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 6f4ae965ca0..393625f5192 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -1631,27 +1631,27 @@ select char(0xff,0x8f using utf8);
char(0xff,0x8f using utf8)
NULL
Warnings:
-Error 1300 Invalid utf8 character string: 'FF8F'
+Warning 1300 Invalid utf8 character string: 'FF8F'
select char(195 using utf8);
char(195 using utf8)
NULL
Warnings:
-Error 1300 Invalid utf8 character string: 'C3'
+Warning 1300 Invalid utf8 character string: 'C3'
select char(196 using utf8);
char(196 using utf8)
NULL
Warnings:
-Error 1300 Invalid utf8 character string: 'C4'
+Warning 1300 Invalid utf8 character string: 'C4'
select char(2557 using utf8);
char(2557 using utf8)
NULL
Warnings:
-Error 1300 Invalid utf8 character string: 'FD'
+Warning 1300 Invalid utf8 character string: 'FD'
select convert(char(0xff,0x8f) using utf8);
convert(char(0xff,0x8f) using utf8)
NULL
Warnings:
-Error 1300 Invalid utf8 character string: 'FF8F'
+Warning 1300 Invalid utf8 character string: 'FF8F'
select hex(convert(char(2557 using latin1) using utf8));
hex(convert(char(2557 using latin1) using utf8))
09C3BD
@@ -1815,12 +1815,12 @@ select hex(char(0xFF using utf8));
hex(char(0xFF using utf8))
NULL
Warnings:
-Error 1300 Invalid utf8 character string: 'FF'
+Warning 1300 Invalid utf8 character string: 'FF'
select hex(convert(0xFF using utf8));
hex(convert(0xFF using utf8))
NULL
Warnings:
-Error 1300 Invalid utf8 character string: 'FF'
+Warning 1300 Invalid utf8 character string: 'FF'
select hex(_utf8 0x616263FF);
ERROR HY000: Invalid utf8 character string: 'FF'
select hex(_utf8 X'616263FF');
@@ -1880,3 +1880,115 @@ CONVERT(a, CHAR) CONVERT(b, CHAR)
70000 1092
DROP TABLE t1;
End of 5.0 tests
+Start of 5.4 tests
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+predicted_order int NOT NULL,
+utf8_encoding VARCHAR(10) NOT NULL
+) CHARACTER SET utf8;
+INSERT INTO t1 VALUES (19, x'E0B696'), (30, x'E0B69AE0B798'), (61, x'E0B6AF'), (93, x'E0B799'), (52, x'E0B6A6'), (73, x'E0B6BBE0B78AE2808D'), (3, x'E0B686'), (56, x'E0B6AA'), (55, x'E0B6A9'), (70, x'E0B6B9'), (94, x'E0B79A'), (80, x'E0B785'), (25, x'E0B69AE0B791'), (48, x'E0B6A2'), (13, x'E0B690'), (86, x'E0B793'), (91, x'E0B79F'), (81, x'E0B786'), (79, x'E0B784'), (14, x'E0B691'), (99, x'E0B78A'), (8, x'E0B68B'), (68, x'E0B6B7'), (22, x'E0B69A'), (16, x'E0B693'), (33, x'E0B69AE0B7B3'), (38, x'E0B69AE0B79D'), (21, x'E0B683'), (11, x'E0B68E'), (77, x'E0B782'), (40, x'E0B69AE0B78A'), (101, x'E0B78AE2808DE0B6BB'), (35, x'E0B69AE0B79A'), (1, x'E0B7B4'), (9, x'E0B68C'), (96, x'E0B79C'), (6, x'E0B689'), (95, x'E0B79B'), (88, x'E0B796'), (64, x'E0B6B3'), (26, x'E0B69AE0B792'), (82, x'E0B78F'), (28, x'E0B69AE0B794'), (39, x'E0B69AE0B79E'), (97, x'E0B79D'), (2, x'E0B685'), (75, x'E0B780'), (34, x'E0B69AE0B799'), (69, x'E0B6B8'), (83, x'E0B790'), (18, x'E0B695'), (90, x'E0B7B2'), (17, x'E0B694'), (72, x'E0B6BB'), (66, x'E0B6B5'), (59, x'E0B6AD'), (44, x'E0B69E'), (15, x'E0B692'), (23, x'E0B69AE0B78F'), (65, x'E0B6B4'), (42, x'E0B69C'), (63, x'E0B6B1'), (85, x'E0B792'), (47, x'E0B6A1'), (49, x'E0B6A3'), (92, x'E0B7B3'), (78, x'E0B783'), (36, x'E0B69AE0B79B'), (4, x'E0B687'), (24, x'E0B69AE0B790'), (87, x'E0B794'), (37, x'E0B69AE0B79C'), (32, x'E0B69AE0B79F'), (29, x'E0B69AE0B796'), (43, x'E0B69D'), (62, x'E0B6B0'), (100, x'E0B78AE2808DE0B6BA'), (60, x'E0B6AE'), (45, x'E0B69F'), (12, x'E0B68F'), (46, x'E0B6A0'), (50, x'E0B6A5'), (51, x'E0B6A4'), (5, x'E0B688'), (76, x'E0B781'), (89, x'E0B798'), (74, x'E0B6BD'), (10, x'E0B68D'), (57, x'E0B6AB'), (71, x'E0B6BA'), (58, x'E0B6AC'), (27, x'E0B69AE0B793'), (54, x'E0B6A8'), (84, x'E0B791'), (31, x'E0B69AE0B7B2'), (98, x'E0B79E'), (53, x'E0B6A7'), (41, x'E0B69B'), (67, x'E0B6B6'), (7, x'E0B68A'), (20, x'E0B682');
+SELECT predicted_order, hex(utf8_encoding) FROM t1 ORDER BY utf8_encoding COLLATE utf8_sinhala_ci;
+predicted_order hex(utf8_encoding)
+1 E0B7B4
+2 E0B685
+3 E0B686
+4 E0B687
+5 E0B688
+6 E0B689
+7 E0B68A
+8 E0B68B
+9 E0B68C
+10 E0B68D
+11 E0B68E
+12 E0B68F
+13 E0B690
+14 E0B691
+15 E0B692
+16 E0B693
+17 E0B694
+18 E0B695
+19 E0B696
+20 E0B682
+21 E0B683
+22 E0B69A
+23 E0B69AE0B78F
+24 E0B69AE0B790
+25 E0B69AE0B791
+26 E0B69AE0B792
+27 E0B69AE0B793
+28 E0B69AE0B794
+29 E0B69AE0B796
+30 E0B69AE0B798
+31 E0B69AE0B7B2
+32 E0B69AE0B79F
+33 E0B69AE0B7B3
+34 E0B69AE0B799
+35 E0B69AE0B79A
+36 E0B69AE0B79B
+37 E0B69AE0B79C
+38 E0B69AE0B79D
+39 E0B69AE0B79E
+40 E0B69AE0B78A
+41 E0B69B
+42 E0B69C
+43 E0B69D
+44 E0B69E
+45 E0B69F
+46 E0B6A0
+47 E0B6A1
+48 E0B6A2
+49 E0B6A3
+50 E0B6A5
+51 E0B6A4
+52 E0B6A6
+53 E0B6A7
+54 E0B6A8
+55 E0B6A9
+56 E0B6AA
+57 E0B6AB
+58 E0B6AC
+59 E0B6AD
+60 E0B6AE
+61 E0B6AF
+62 E0B6B0
+63 E0B6B1
+64 E0B6B3
+65 E0B6B4
+66 E0B6B5
+67 E0B6B6
+68 E0B6B7
+69 E0B6B8
+70 E0B6B9
+71 E0B6BA
+72 E0B6BB
+73 E0B6BBE0B78AE2808D
+74 E0B6BD
+75 E0B780
+76 E0B781
+77 E0B782
+78 E0B783
+79 E0B784
+80 E0B785
+81 E0B786
+82 E0B78F
+83 E0B790
+84 E0B791
+85 E0B792
+86 E0B793
+87 E0B794
+88 E0B796
+89 E0B798
+90 E0B7B2
+91 E0B79F
+92 E0B7B3
+93 E0B799
+94 E0B79A
+95 E0B79B
+96 E0B79C
+97 E0B79D
+98 E0B79E
+99 E0B78A
+100 E0B78AE2808DE0B6BA
+101 E0B78AE2808DE0B6BB
+DROP TABLE t1;
+End of 5.4 tests
diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result
index 7e185daa668..b0b8316fe33 100644
--- a/mysql-test/r/date_formats.result
+++ b/mysql-test/r/date_formats.result
@@ -89,7 +89,7 @@ select STR_TO_DATE('2004.12.12 22.30.61','%Y.%m.%d %T');
STR_TO_DATE('2004.12.12 22.30.61','%Y.%m.%d %T')
NULL
Warnings:
-Error 1411 Incorrect time value: '22.30.61' for function str_to_date
+Warning 1411 Incorrect time value: '22.30.61' for function str_to_date
create table t1 (date char(30), format char(30) not null);
insert into t1 values
('2003-01-02 10:11:12', '%Y-%m-%d %H:%i:%S'),
@@ -361,21 +361,21 @@ Tuesday 52 2001 %W %u %x NULL
7 53 1998 %w %u %Y NULL
NULL %m.%d.%Y NULL
Warnings:
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_date
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12.123456' for function str_to_date
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12AM' for function str_to_date
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12AN' for function str_to_date
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_date
-Error 1411 Incorrect datetime value: '10:20:10AM' for function str_to_date
-Error 1411 Incorrect datetime value: '15 Septembei 2001' for function str_to_date
-Error 1411 Incorrect datetime value: '15 Ju 2001' for function str_to_date
-Error 1411 Incorrect datetime value: 'Sund 15 MA' for function str_to_date
-Error 1411 Incorrect datetime value: 'Thursdai 12 1998' for function str_to_date
-Error 1411 Incorrect datetime value: 'Sunday 01 2001' for function str_to_date
-Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
-Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
-Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
-Error 1411 Incorrect datetime value: '7 53 1998' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12.123456' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12AM' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12AN' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_date
+Warning 1411 Incorrect datetime value: '10:20:10AM' for function str_to_date
+Warning 1411 Incorrect datetime value: '15 Septembei 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: '15 Ju 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Sund 15 MA' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Thursdai 12 1998' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Sunday 01 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: '7 53 1998' for function str_to_date
select date,format,concat(str_to_date(date, format),'') as con from t1;
date format con
2003-01-02 10:11:12 PM %Y-%m-%d %H:%i:%S %p NULL
@@ -395,21 +395,21 @@ Tuesday 52 2001 %W %u %x NULL
7 53 1998 %w %u %Y NULL
NULL %m.%d.%Y NULL
Warnings:
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_date
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12.123456' for function str_to_date
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12AM' for function str_to_date
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12AN' for function str_to_date
-Error 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_date
-Error 1411 Incorrect datetime value: '10:20:10AM' for function str_to_date
-Error 1411 Incorrect datetime value: '15 Septembei 2001' for function str_to_date
-Error 1411 Incorrect datetime value: '15 Ju 2001' for function str_to_date
-Error 1411 Incorrect datetime value: 'Sund 15 MA' for function str_to_date
-Error 1411 Incorrect datetime value: 'Thursdai 12 1998' for function str_to_date
-Error 1411 Incorrect datetime value: 'Sunday 01 2001' for function str_to_date
-Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
-Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
-Error 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
-Error 1411 Incorrect datetime value: '7 53 1998' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12.123456' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12AM' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12AN' for function str_to_date
+Warning 1411 Incorrect datetime value: '2003-01-02 10:11:12 PM' for function str_to_date
+Warning 1411 Incorrect datetime value: '10:20:10AM' for function str_to_date
+Warning 1411 Incorrect datetime value: '15 Septembei 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: '15 Ju 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Sund 15 MA' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Thursdai 12 1998' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Sunday 01 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: 'Tuesday 52 2001' for function str_to_date
+Warning 1411 Incorrect datetime value: '7 53 1998' for function str_to_date
truncate table t1;
insert into t1 values
('10:20:10AM', '%h:%i:%s'),
@@ -449,7 +449,7 @@ select str_to_date('15-01-2001 12:59:59', GET_FORMAT(DATE,'USA'));
str_to_date('15-01-2001 12:59:59', GET_FORMAT(DATE,'USA'))
NULL
Warnings:
-Error 1411 Incorrect datetime value: '15-01-2001 12:59:59' for function str_to_date
+Warning 1411 Incorrect datetime value: '15-01-2001 12:59:59' for function str_to_date
explain extended select makedate(1997,1), addtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002"),subtime("31.12.97 11.59.59.999999 PM", "1 1.1.1.000002"),timediff("01.01.97 11:59:59.000001 PM","31.12.95 11:59:59.000002 PM"),cast(str_to_date("15-01-2001 12:59:59", "%d-%m-%Y %H:%i:%S") as TIME), maketime(23,11,12),microsecond("1997-12-31 23:59:59.000001");
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result
index b4e61d0e4fc..650cc9c2c70 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -65,8 +65,8 @@ NULL
50000
NULL
Warnings:
-Error 1259 ZLIB: Input data corrupted
-Error 1256 Uncompressed data size too large; the maximum size is 1048576 (probably, length of uncompressed data was corrupted)
+Warning 1259 ZLIB: Input data corrupted
+Warning 1256 Uncompressed data size too large; the maximum size is 1048576 (probably, length of uncompressed data was corrupted)
drop table t1;
set @@global.max_allowed_packet=1048576*100;
select compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null;
@@ -96,12 +96,12 @@ explain select * from t1 where uncompress(a) is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
Warnings:
-Error 1259 ZLIB: Input data corrupted
+Warning 1259 ZLIB: Input data corrupted
select * from t1 where uncompress(a) is null;
a
foo
Warnings:
-Error 1259 ZLIB: Input data corrupted
+Warning 1259 ZLIB: Input data corrupted
explain select *, uncompress(a) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
@@ -109,13 +109,13 @@ select *, uncompress(a) from t1;
a uncompress(a)
foo NULL
Warnings:
-Error 1259 ZLIB: Input data corrupted
+Warning 1259 ZLIB: Input data corrupted
select *, uncompress(a), uncompress(a) is null from t1;
a uncompress(a) uncompress(a) is null
foo NULL 1
Warnings:
-Error 1259 ZLIB: Input data corrupted
-Error 1259 ZLIB: Input data corrupted
+Warning 1259 ZLIB: Input data corrupted
+Warning 1259 ZLIB: Input data corrupted
drop table t1;
CREATE TABLE t1 (c1 INT);
INSERT INTO t1 VALUES (1), (1111), (11111);
diff --git a/mysql-test/r/func_encrypt.result b/mysql-test/r/func_encrypt.result
index 8fbf36b45b9..91ff4e218fb 100644
--- a/mysql-test/r/func_encrypt.result
+++ b/mysql-test/r/func_encrypt.result
@@ -124,7 +124,7 @@ select des_encrypt("hello",10);
des_encrypt("hello",10)
NULL
Warnings:
-Error 1108 Incorrect parameters to procedure 'des_encrypt'
+Warning 1108 Incorrect parameters to procedure 'des_encrypt'
select des_encrypt(NULL);
des_encrypt(NULL)
NULL
@@ -138,12 +138,12 @@ select des_encrypt(10, NULL);
des_encrypt(10, NULL)
NULL
Warnings:
-Error 1108 Incorrect parameters to procedure 'des_encrypt'
+Warning 1108 Incorrect parameters to procedure 'des_encrypt'
select des_encrypt("hello", NULL);
des_encrypt("hello", NULL)
NULL
Warnings:
-Error 1108 Incorrect parameters to procedure 'des_encrypt'
+Warning 1108 Incorrect parameters to procedure 'des_encrypt'
select des_decrypt("hello",10);
des_decrypt("hello",10)
hello
@@ -177,7 +177,7 @@ select hex(des_decrypt(des_encrypt("hello","hidden")));
hex(des_decrypt(des_encrypt("hello","hidden")))
NULL
Warnings:
-Error 1108 Incorrect parameters to procedure 'des_decrypt'
+Warning 1108 Incorrect parameters to procedure 'des_decrypt'
explain extended select des_decrypt(des_encrypt("hello",4),'password2'), des_decrypt(des_encrypt("hello","hidden"));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
diff --git a/mysql-test/r/func_encrypt_nossl.result b/mysql-test/r/func_encrypt_nossl.result
index d0df2335afa..fc003eec226 100644
--- a/mysql-test/r/func_encrypt_nossl.result
+++ b/mysql-test/r/func_encrypt_nossl.result
@@ -2,83 +2,83 @@ select des_encrypt("test", 'akeystr');
des_encrypt("test", 'akeystr')
NULL
Warnings:
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_encrypt("test", 1);
des_encrypt("test", 1)
NULL
Warnings:
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_encrypt("test", 9);
des_encrypt("test", 9)
NULL
Warnings:
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_encrypt("test", 100);
des_encrypt("test", 100)
NULL
Warnings:
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_encrypt("test", NULL);
des_encrypt("test", NULL)
NULL
Warnings:
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_encrypt(NULL, NULL);
des_encrypt(NULL, NULL)
NULL
Warnings:
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_decrypt("test", 'anotherkeystr');
des_decrypt("test", 'anotherkeystr')
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_decrypt(1, 1);
des_decrypt(1, 1)
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_decrypt(des_encrypt("test", 'thekey'));
des_decrypt(des_encrypt("test", 'thekey'))
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select hex(des_encrypt("hello")),des_decrypt(des_encrypt("hello"));
hex(des_encrypt("hello")) des_decrypt(des_encrypt("hello"))
NULL NULL
Warnings:
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_decrypt(des_encrypt("hello",4));
des_decrypt(des_encrypt("hello",4))
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_decrypt(des_encrypt("hello",'test'),'test');
des_decrypt(des_encrypt("hello",'test'),'test')
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select hex(des_encrypt("hello")),hex(des_encrypt("hello",5)),hex(des_encrypt("hello",'default_password'));
hex(des_encrypt("hello")) hex(des_encrypt("hello",5)) hex(des_encrypt("hello",'default_password'))
NULL NULL NULL
Warnings:
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
-Error 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_encrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_decrypt(des_encrypt("hello"),'default_password');
des_decrypt(des_encrypt("hello"),'default_password')
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select des_decrypt(des_encrypt("hello",4),'password4');
des_decrypt(des_encrypt("hello",4),'password4')
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
SET @a=des_decrypt(des_encrypt("hello"));
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
flush des_key_file;
select @a = des_decrypt(des_encrypt("hello"));
@a = des_decrypt(des_encrypt("hello"))
@@ -90,9 +90,9 @@ select hex(des_decrypt(des_encrypt("hello",4),'password2'));
hex(des_decrypt(des_encrypt("hello",4),'password2'))
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
select hex(des_decrypt(des_encrypt("hello","hidden")));
hex(des_decrypt(des_encrypt("hello","hidden")))
NULL
Warnings:
-Error 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
+Warning 1289 The 'des_decrypt' feature is disabled; you need MySQL built with '--with-openssl' to have it working
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 3b78851a1b9..ebec186591d 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -153,10 +153,10 @@ grp group_concat(c)
4
5 NULL
Warnings:
-Warning 1260 1 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 4 was cut by GROUP_CONCAT()
show warnings;
Level Code Message
-Warning 1260 1 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 4 was cut by GROUP_CONCAT()
set group_concat_max_len = 1024;
select group_concat(sum(c)) from t1 group by grp;
ERROR HY000: Invalid use of group function
@@ -380,25 +380,29 @@ group_concat(b)
bb,c
BB,C
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
+Warning 1260 Row 4 was cut by GROUP_CONCAT()
select group_concat(distinct b) from t1 group by a;
group_concat(distinct b)
bb,c
BB,C
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
+Warning 1260 Row 4 was cut by GROUP_CONCAT()
select group_concat(b order by b) from t1 group by a;
group_concat(b order by b)
a,bb
A,BB
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 3 was cut by GROUP_CONCAT()
+Warning 1260 Row 6 was cut by GROUP_CONCAT()
select group_concat(distinct b order by b) from t1 group by a;
group_concat(distinct b order by b)
a,bb
A,BB
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 3 was cut by GROUP_CONCAT()
+Warning 1260 Row 6 was cut by GROUP_CONCAT()
insert into t1 values (1, concat(repeat('1', 300), '2')),
(1, concat(repeat('1', 300), '2')), (1, concat(repeat('0', 300), '1')),
(2, concat(repeat('1', 300), '2')), (2, concat(repeat('1', 300), '2')),
@@ -426,25 +430,29 @@ group_concat(b)
bb,ccc,a,bb,ccc,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,1111111111111111111111111111111111111111111111111111111111111111111111111111111111
BB,CCC,A,BB,CCC,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,1111111111111111111111111111111111111111111111111111111111111111111111111111111111
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 7 was cut by GROUP_CONCAT()
+Warning 1260 Row 14 was cut by GROUP_CONCAT()
select group_concat(distinct b) from t1 group by a;
group_concat(distinct b)
bb,ccc,a,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
BB,CCC,A,1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 5 was cut by GROUP_CONCAT()
+Warning 1260 Row 10 was cut by GROUP_CONCAT()
select group_concat(b order by b) from t1 group by a;
group_concat(b order by b)
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
+Warning 1260 Row 4 was cut by GROUP_CONCAT()
select group_concat(distinct b order by b) from t1 group by a;
group_concat(distinct b order by b)
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
+Warning 1260 Row 4 was cut by GROUP_CONCAT()
drop table t1;
create table t1 (a varchar(255) character set cp1250 collate cp1250_general_ci,
b varchar(255) character set koi8r);
@@ -751,22 +759,22 @@ SELECT GROUP_CONCAT( a ) FROM t1;
GROUP_CONCAT( a )
aaaaaaaaaa,bbbbbbbbb
Warnings:
-Warning 1260 1 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
SELECT GROUP_CONCAT( DISTINCT a ) FROM t1;
GROUP_CONCAT( DISTINCT a )
aaaaaaaaaa,bbbbbbbbb
Warnings:
-Warning 1260 1 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
SELECT GROUP_CONCAT( a ORDER BY b ) FROM t1;
GROUP_CONCAT( a ORDER BY b )
aaaaaaaaaa,bbbbbbbbb
Warnings:
-Warning 1260 1 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
SELECT GROUP_CONCAT( DISTINCT a ORDER BY b ) FROM t1;
GROUP_CONCAT( DISTINCT a ORDER BY b )
aaaaaaaaaa,bbbbbbbbb
Warnings:
-Warning 1260 1 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
SET group_concat_max_len = DEFAULT;
DROP TABLE t1;
SET group_concat_max_len= 65535;
@@ -979,3 +987,31 @@ GROUP BY t1.a
1
DROP TABLE t1, t2;
End of 5.0 tests
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (a VARCHAR(6), b INT);
+CREATE TABLE t2 (a VARCHAR(6), b INT);
+INSERT INTO t1 VALUES ('111111', 1);
+INSERT INTO t1 VALUES ('222222', 2);
+INSERT INTO t1 VALUES ('333333', 3);
+INSERT INTO t1 VALUES ('444444', 4);
+INSERT INTO t1 VALUES ('555555', 5);
+SET group_concat_max_len = 5;
+SET @old_sql_mode = @@sql_mode, @@sql_mode = 'traditional';
+SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b LIMIT 3;
+GROUP_CONCAT(a) b
+11111 1
+22222 2
+33333 3
+Warnings:
+Warning 1260 Row 1 was cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
+Warning 1260 Row 3 was cut by GROUP_CONCAT()
+INSERT INTO t2 SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b;
+ERROR HY000: Row 1 was cut by GROUP_CONCAT()
+UPDATE t1 SET a = '11111' WHERE b = 1;
+UPDATE t1 SET a = '22222' WHERE b = 2;
+INSERT INTO t2 SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b;
+ERROR HY000: Row 3 was cut by GROUP_CONCAT()
+SET group_concat_max_len = DEFAULT;
+SET @@sql_mode = @old_sql_mode;
+DROP TABLE t1, t2;
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index fd7ef72409e..d8b8a14afc6 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -225,27 +225,27 @@ select ln(-1);
ln(-1)
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
select log10(-1);
log10(-1)
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
select log2(-1);
log2(-1)
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
select log(2,-1);
log(2,-1)
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
select log(-2,1);
log(-2,1)
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
set sql_mode='';
select round(111,-10);
round(111,-10)
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 2a2fe50ad0f..39d11aa3e2c 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1433,7 +1433,7 @@ select benchmark(-1, 1);
benchmark(-1, 1)
NULL
Warnings:
-Error 1411 Incorrect count value: '-1' for function benchmark
+Warning 1411 Incorrect count value: '-1' for function benchmark
set @password="password";
set @my_data="clear text to encode";
select md5(encode(@my_data, "password"));
@@ -1533,7 +1533,7 @@ select locate('lo','hello',-18446744073709551615);
locate('lo','hello',-18446744073709551615)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select locate('lo','hello',18446744073709551615);
locate('lo','hello',18446744073709551615)
0
@@ -1541,22 +1541,22 @@ select locate('lo','hello',-18446744073709551616);
locate('lo','hello',-18446744073709551616)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select locate('lo','hello',18446744073709551616);
locate('lo','hello',18446744073709551616)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select locate('lo','hello',-18446744073709551617);
locate('lo','hello',-18446744073709551617)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select locate('lo','hello',18446744073709551617);
locate('lo','hello',18446744073709551617)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select left('hello', 10);
left('hello', 10)
hello
@@ -1588,8 +1588,8 @@ select left('hello', -18446744073709551615);
left('hello', -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select left('hello', 18446744073709551615);
left('hello', 18446744073709551615)
hello
@@ -1597,26 +1597,26 @@ select left('hello', -18446744073709551616);
left('hello', -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select left('hello', 18446744073709551616);
left('hello', 18446744073709551616)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select left('hello', -18446744073709551617);
left('hello', -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select left('hello', 18446744073709551617);
left('hello', 18446744073709551617)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select right('hello', 10);
right('hello', 10)
hello
@@ -1648,8 +1648,8 @@ select right('hello', -18446744073709551615);
right('hello', -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select right('hello', 18446744073709551615);
right('hello', 18446744073709551615)
hello
@@ -1657,26 +1657,26 @@ select right('hello', -18446744073709551616);
right('hello', -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select right('hello', 18446744073709551616);
right('hello', 18446744073709551616)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select right('hello', -18446744073709551617);
right('hello', -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select right('hello', 18446744073709551617);
right('hello', 18446744073709551617)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 2, -1);
substring('hello', 2, -1)
@@ -1708,8 +1708,8 @@ select substring('hello', -18446744073709551615, 1);
substring('hello', -18446744073709551615, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 18446744073709551615, 1);
substring('hello', 18446744073709551615, 1)
@@ -1717,26 +1717,26 @@ select substring('hello', -18446744073709551616, 1);
substring('hello', -18446744073709551616, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 18446744073709551616, 1);
substring('hello', 18446744073709551616, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', -18446744073709551617, 1);
substring('hello', -18446744073709551617, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 18446744073709551617, 1);
substring('hello', 18446744073709551617, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 1, -1);
substring('hello', 1, -1)
@@ -1762,8 +1762,8 @@ select substring('hello', 1, -18446744073709551615);
substring('hello', 1, -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 1, 18446744073709551615);
substring('hello', 1, 18446744073709551615)
hello
@@ -1771,26 +1771,26 @@ select substring('hello', 1, -18446744073709551616);
substring('hello', 1, -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 1, 18446744073709551616);
substring('hello', 1, 18446744073709551616)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 1, -18446744073709551617);
substring('hello', 1, -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 1, 18446744073709551617);
substring('hello', 1, 18446744073709551617)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', -1, -1);
substring('hello', -1, -1)
@@ -1816,10 +1816,10 @@ select substring('hello', -18446744073709551615, -18446744073709551615);
substring('hello', -18446744073709551615, -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 18446744073709551615, 18446744073709551615);
substring('hello', 18446744073709551615, 18446744073709551615)
@@ -1827,34 +1827,34 @@ select substring('hello', -18446744073709551616, -18446744073709551616);
substring('hello', -18446744073709551616, -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 18446744073709551616, 18446744073709551616);
substring('hello', 18446744073709551616, 18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', -18446744073709551617, -18446744073709551617);
substring('hello', -18446744073709551617, -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select substring('hello', 18446744073709551617, 18446744073709551617);
substring('hello', 18446744073709551617, 18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', -1, 1, 'hi');
insert('hello', -1, 1, 'hi')
hello
@@ -1880,7 +1880,7 @@ select insert('hello', -18446744073709551615, 1, 'hi');
insert('hello', -18446744073709551615, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 18446744073709551615, 1, 'hi');
insert('hello', 18446744073709551615, 1, 'hi')
hello
@@ -1888,22 +1888,22 @@ select insert('hello', -18446744073709551616, 1, 'hi');
insert('hello', -18446744073709551616, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 18446744073709551616, 1, 'hi');
insert('hello', 18446744073709551616, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', -18446744073709551617, 1, 'hi');
insert('hello', -18446744073709551617, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 18446744073709551617, 1, 'hi');
insert('hello', 18446744073709551617, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 1, -1, 'hi');
insert('hello', 1, -1, 'hi')
hi
@@ -1929,7 +1929,7 @@ select insert('hello', 1, -18446744073709551615, 'hi');
insert('hello', 1, -18446744073709551615, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 1, 18446744073709551615, 'hi');
insert('hello', 1, 18446744073709551615, 'hi')
hi
@@ -1937,22 +1937,22 @@ select insert('hello', 1, -18446744073709551616, 'hi');
insert('hello', 1, -18446744073709551616, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 1, 18446744073709551616, 'hi');
insert('hello', 1, 18446744073709551616, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 1, -18446744073709551617, 'hi');
insert('hello', 1, -18446744073709551617, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 1, 18446744073709551617, 'hi');
insert('hello', 1, 18446744073709551617, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', -1, -1, 'hi');
insert('hello', -1, -1, 'hi')
hello
@@ -1978,8 +1978,8 @@ select insert('hello', -18446744073709551615, -18446744073709551615, 'hi');
insert('hello', -18446744073709551615, -18446744073709551615, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 18446744073709551615, 18446744073709551615, 'hi');
insert('hello', 18446744073709551615, 18446744073709551615, 'hi')
hello
@@ -1987,26 +1987,26 @@ select insert('hello', -18446744073709551616, -18446744073709551616, 'hi');
insert('hello', -18446744073709551616, -18446744073709551616, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 18446744073709551616, 18446744073709551616, 'hi');
insert('hello', 18446744073709551616, 18446744073709551616, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', -18446744073709551617, -18446744073709551617, 'hi');
insert('hello', -18446744073709551617, -18446744073709551617, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select insert('hello', 18446744073709551617, 18446744073709551617, 'hi');
insert('hello', 18446744073709551617, 18446744073709551617, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select repeat('hello', -1);
repeat('hello', -1)
@@ -2038,8 +2038,8 @@ select repeat('hello', -18446744073709551615);
repeat('hello', -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select repeat('hello', 18446744073709551615);
repeat('hello', 18446744073709551615)
NULL
@@ -2049,27 +2049,27 @@ select repeat('hello', -18446744073709551616);
repeat('hello', -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select repeat('hello', 18446744073709551616);
repeat('hello', 18446744073709551616)
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
select repeat('hello', -18446744073709551617);
repeat('hello', -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select repeat('hello', 18446744073709551617);
repeat('hello', 18446744073709551617)
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
select space(-1);
space(-1)
@@ -2102,8 +2102,8 @@ select space(-18446744073709551615);
space(-18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select space(18446744073709551615);
space(18446744073709551615)
NULL
@@ -2113,27 +2113,27 @@ select space(-18446744073709551616);
space(-18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select space(18446744073709551616);
space(18446744073709551616)
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
select space(-18446744073709551617);
space(-18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select space(18446744073709551617);
space(18446744073709551617)
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
select rpad('hello', -1, '1');
rpad('hello', -1, '1')
@@ -2166,8 +2166,8 @@ select rpad('hello', -18446744073709551615, '1');
rpad('hello', -18446744073709551615, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select rpad('hello', 18446744073709551615, '1');
rpad('hello', 18446744073709551615, '1')
NULL
@@ -2177,27 +2177,27 @@ select rpad('hello', -18446744073709551616, '1');
rpad('hello', -18446744073709551616, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select rpad('hello', 18446744073709551616, '1');
rpad('hello', 18446744073709551616, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
select rpad('hello', -18446744073709551617, '1');
rpad('hello', -18446744073709551617, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select rpad('hello', 18446744073709551617, '1');
rpad('hello', 18446744073709551617, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
select lpad('hello', -1, '1');
lpad('hello', -1, '1')
@@ -2230,8 +2230,8 @@ select lpad('hello', -18446744073709551615, '1');
lpad('hello', -18446744073709551615, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select lpad('hello', 18446744073709551615, '1');
lpad('hello', 18446744073709551615, '1')
NULL
@@ -2241,27 +2241,27 @@ select lpad('hello', -18446744073709551616, '1');
lpad('hello', -18446744073709551616, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select lpad('hello', 18446744073709551616, '1');
lpad('hello', 18446744073709551616, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
select lpad('hello', -18446744073709551617, '1');
lpad('hello', -18446744073709551617, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select lpad('hello', 18446744073709551617, '1');
lpad('hello', 18446744073709551617, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
SET @orig_sql_mode = @@SQL_MODE;
SET SQL_MODE=traditional;
@@ -2269,12 +2269,12 @@ SELECT CHAR(0xff,0x8f USING utf8);
CHAR(0xff,0x8f USING utf8)
NULL
Warnings:
-Error 1300 Invalid utf8 character string: 'FF8F'
+Warning 1300 Invalid utf8 character string: 'FF8F'
SELECT CHAR(0xff,0x8f USING utf8) IS NULL;
CHAR(0xff,0x8f USING utf8) IS NULL
1
Warnings:
-Error 1300 Invalid utf8 character string: 'FF8F'
+Warning 1300 Invalid utf8 character string: 'FF8F'
SET SQL_MODE=@orig_sql_mode;
select substring('abc', cast(2 as unsigned int));
substring('abc', cast(2 as unsigned int))
@@ -2558,3 +2558,133 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 Using join buffer
2 DERIVED t1 ALL NULL NULL NULL NULL 2
drop table t1;
+Start of 5.4 tests
+SELECT format(12345678901234567890.123, 3);
+format(12345678901234567890.123, 3)
+12,345,678,901,234,567,890.123
+SELECT format(12345678901234567890.123, 3, NULL);
+format(12345678901234567890.123, 3, NULL)
+12,345,678,901,234,567,890.123
+Warnings:
+Warning 1647 Unknown locale: 'NULL'
+SELECT format(12345678901234567890.123, 3, 'ar_AE');
+format(12345678901234567890.123, 3, 'ar_AE')
+12,345,678,901,234,567,890.123
+SELECT format(12345678901234567890.123, 3, 'ar_SA');
+format(12345678901234567890.123, 3, 'ar_SA')
+12345678901234567890.123
+SELECT format(12345678901234567890.123, 3, 'be_BY');
+format(12345678901234567890.123, 3, 'be_BY')
+12.345.678.901.234.567.890,123
+SELECT format(12345678901234567890.123, 3, 'de_DE');
+format(12345678901234567890.123, 3, 'de_DE')
+12.345.678.901.234.567.890,123
+SELECT format(12345678901234567890.123, 3, 'en_IN');
+format(12345678901234567890.123, 3, 'en_IN')
+1,23,45,67,89,01,23,45,67,890.123
+SELECT format(12345678901234567890.123, 3, 'en_US');
+format(12345678901234567890.123, 3, 'en_US')
+12,345,678,901,234,567,890.123
+SELECT format(12345678901234567890.123, 3, 'it_CH');
+format(12345678901234567890.123, 3, 'it_CH')
+12'345'678'901'234'567'890,123
+SELECT format(12345678901234567890.123, 3, 'ru_RU');
+format(12345678901234567890.123, 3, 'ru_RU')
+12 345 678 901 234 567 890,123
+SELECT format(12345678901234567890.123, 3, 'ta_IN');
+format(12345678901234567890.123, 3, 'ta_IN')
+1,23,45,67,89,01,23,45,67,890.123
+CREATE TABLE t1 (fmt CHAR(5) NOT NULL);
+INSERT INTO t1 VALUES ('ar_AE');
+INSERT INTO t1 VALUES ('ar_SA');
+INSERT INTO t1 VALUES ('be_BY');
+INSERT INTO t1 VALUES ('de_DE');
+INSERT INTO t1 VALUES ('en_IN');
+INSERT INTO t1 VALUES ('en_US');
+INSERT INTO t1 VALUES ('it_CH');
+INSERT INTO t1 VALUES ('ru_RU');
+INSERT INTO t1 VALUES ('ta_IN');
+SELECT fmt, format(12345678901234567890.123, 3, fmt) FROM t1 ORDER BY fmt;
+fmt format(12345678901234567890.123, 3, fmt)
+ar_AE 12,345,678,901,234,567,890.123
+ar_SA 12345678901234567890.123
+be_BY 12.345.678.901.234.567.890,123
+de_DE 12.345.678.901.234.567.890,123
+en_IN 1,23,45,67,89,01,23,45,67,890.123
+en_US 12,345,678,901,234,567,890.123
+it_CH 12'345'678'901'234'567'890,123
+ru_RU 12 345 678 901 234 567 890,123
+ta_IN 1,23,45,67,89,01,23,45,67,890.123
+SELECT fmt, format(12345678901234567890.123, 0, fmt) FROM t1 ORDER BY fmt;
+fmt format(12345678901234567890.123, 0, fmt)
+ar_AE 12,345,678,901,234,567,890
+ar_SA 12345678901234567890
+be_BY 12.345.678.901.234.567.890
+de_DE 12.345.678.901.234.567.890
+en_IN 1,23,45,67,89,01,23,45,67,890
+en_US 12,345,678,901,234,567,890
+it_CH 12'345'678'901'234'567'890
+ru_RU 12 345 678 901 234 567 890
+ta_IN 1,23,45,67,89,01,23,45,67,890
+SELECT fmt, format(12345678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+fmt format(12345678901234567890, 3, fmt)
+ar_AE 12,345,678,901,234,567,890.000
+ar_SA 12345678901234567890.000
+be_BY 12.345.678.901.234.567.890,000
+de_DE 12.345.678.901.234.567.890,000
+en_IN 1,23,45,67,89,01,23,45,67,890.000
+en_US 12,345,678,901,234,567,890.000
+it_CH 12'345'678'901'234'567'890,000
+ru_RU 12 345 678 901 234 567 890,000
+ta_IN 1,23,45,67,89,01,23,45,67,890.000
+SELECT fmt, format(-12345678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+fmt format(-12345678901234567890, 3, fmt)
+ar_AE -12,345,678,901,234,567,890.000
+ar_SA -12345678901234567890.000
+be_BY -12.345.678.901.234.567.890,000
+de_DE -12.345.678.901.234.567.890,000
+en_IN -1,23,45,67,89,01,23,45,67,890.000
+en_US -12,345,678,901,234,567,890.000
+it_CH -12'345'678'901'234'567'890,000
+ru_RU -12 345 678 901 234 567 890,000
+ta_IN -1,23,45,67,89,01,23,45,67,890.000
+SELECT fmt, format(-02345678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+fmt format(-02345678901234567890, 3, fmt)
+ar_AE -2,345,678,901,234,567,890.000
+ar_SA -2345678901234567890.000
+be_BY -2.345.678.901.234.567.890,000
+de_DE -2.345.678.901.234.567.890,000
+en_IN -23,45,67,89,01,23,45,67,890.000
+en_US -2,345,678,901,234,567,890.000
+it_CH -2'345'678'901'234'567'890,000
+ru_RU -2 345 678 901 234 567 890,000
+ta_IN -23,45,67,89,01,23,45,67,890.000
+SELECT fmt, format(-00345678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+fmt format(-00345678901234567890, 3, fmt)
+ar_AE -345,678,901,234,567,890.000
+ar_SA -345678901234567890.000
+be_BY -345.678.901.234.567.890,000
+de_DE -345.678.901.234.567.890,000
+en_IN -3,45,67,89,01,23,45,67,890.000
+en_US -345,678,901,234,567,890.000
+it_CH -345'678'901'234'567'890,000
+ru_RU -345 678 901 234 567 890,000
+ta_IN -3,45,67,89,01,23,45,67,890.000
+SELECT fmt, format(-00045678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+fmt format(-00045678901234567890, 3, fmt)
+ar_AE -45,678,901,234,567,890.000
+ar_SA -45678901234567890.000
+be_BY -45.678.901.234.567.890,000
+de_DE -45.678.901.234.567.890,000
+en_IN -45,67,89,01,23,45,67,890.000
+en_US -45,678,901,234,567,890.000
+it_CH -45'678'901'234'567'890,000
+ru_RU -45 678 901 234 567 890,000
+ta_IN -45,67,89,01,23,45,67,890.000
+DROP TABLE t1;
+SELECT format(123, 1, 'Non-existent-locale');
+format(123, 1, 'Non-existent-locale')
+123.0
+Warnings:
+Warning 1647 Unknown locale: 'Non-existent-locale'
+End of 5.4 tests
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index ac9a53ca238..c4841ee57a0 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -1800,23 +1800,23 @@ b
a
explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 65 Using where; Using index for group-by (scanning)
explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 128 75.00 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 100.00 Using where; Using index for group-by
Warnings:
Note 1003 select count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`) AS `count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`b` = 'c') and (`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
-explain extended select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
+explain extended select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 128 75.00 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 14 100.00 Using where; Using index for group-by
Warnings:
-Note 1003 select (ord(`test`.`t1`.`a1`) + count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`)) AS `ord(a1) + count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
+Note 1003 select (98 + count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`)) AS `98 + count(distinct a1,a2,b)` from `test`.`t1` where ((`test`.`t1`.`a1` > 'a') and (`test`.`t1`.`a2` > 'a'))
select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
count(distinct a1,a2,b)
4
@@ -1829,8 +1829,8 @@ count(distinct a1,a2,b)
select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
count(distinct b)
1
-select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
-ord(a1) + count(distinct a1,a2,b)
+select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
+98 + count(distinct a1,a2,b)
104
explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
@@ -2514,3 +2514,257 @@ a MAX(b)
2 1
DROP TABLE t;
End of 5.1 tests
+#
+# WL#3220 (Loose index scan for COUNT DISTINCT)
+#
+CREATE TABLE t1 (a INT, b INT, c INT, KEY (a,b));
+INSERT INTO t1 VALUES (1,1,1), (1,2,1), (1,3,1), (1,4,1);
+INSERT INTO t1 SELECT a, b + 4, 1 FROM t1;
+INSERT INTO t1 SELECT a + 1, b, 1 FROM t1;
+CREATE TABLE t2 (a INT, b INT, c INT, d INT, e INT, f INT, KEY (a,b,c));
+INSERT INTO t2 VALUES (1,1,1,1,1,1), (1,2,1,1,1,1), (1,3,1,1,1,1),
+(1,4,1,1,1,1);
+INSERT INTO t2 SELECT a, b + 4, c,d,e,f FROM t2;
+INSERT INTO t2 SELECT a + 1, b, c,d,e,f FROM t2;
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT a) FROM t1;
+COUNT(DISTINCT a)
+2
+EXPLAIN SELECT COUNT(DISTINCT a,b) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT a,b) FROM t1;
+COUNT(DISTINCT a,b)
+16
+EXPLAIN SELECT COUNT(DISTINCT b,a) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT b,a) FROM t1;
+COUNT(DISTINCT b,a)
+16
+EXPLAIN SELECT COUNT(DISTINCT b) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index
+SELECT COUNT(DISTINCT b) FROM t1;
+COUNT(DISTINCT b)
+8
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
+COUNT(DISTINCT a)
+1
+1
+EXPLAIN SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
+COUNT(DISTINCT b)
+8
+8
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index; Using filesort
+SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
+COUNT(DISTINCT a)
+2
+2
+2
+2
+2
+2
+2
+2
+EXPLAIN SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index
+SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
+COUNT(DISTINCT a)
+2
+EXPLAIN SELECT COUNT(DISTINCT a, b + 0) FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index
+SELECT COUNT(DISTINCT a, b + 0) FROM t1;
+COUNT(DISTINCT a, b + 0)
+16
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
+COUNT(DISTINCT a)
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 16
+SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
+COUNT(DISTINCT a)
+2
+EXPLAIN SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by
+SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
+1
+1
+EXPLAIN SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 10 NULL 9 Using index for group-by
+SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
+1
+1
+1
+EXPLAIN SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1_1 index NULL a 10 NULL 16 Using index; Using temporary; Using filesort
+1 SIMPLE t1_2 index NULL a 10 NULL 16 Using index; Using join buffer
+SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
+COUNT(DISTINCT t1_1.a)
+1
+1
+EXPLAIN SELECT COUNT(DISTINCT a), 12 FROM t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 5 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT a), 12 FROM t1;
+COUNT(DISTINCT a) 12
+2 12
+EXPLAIN SELECT COUNT(DISTINCT a, b, c) FROM t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 15 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT a, b, c) FROM t2;
+COUNT(DISTINCT a, b, c)
+16
+EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 5 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
+COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT a)
+2 3 1.5000
+EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 16
+SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
+COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT f)
+2 3 1.0000
+EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 10 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
+COUNT(DISTINCT a, b) COUNT(DISTINCT b, a)
+16 16
+EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 16
+SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
+COUNT(DISTINCT a, b) COUNT(DISTINCT b, f)
+16 8
+EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 16
+SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
+COUNT(DISTINCT a, b) COUNT(DISTINCT b, d)
+16 8
+EXPLAIN SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 15 NULL 9 Using index for group-by
+SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
+a c COUNT(DISTINCT c, a, b)
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+1 1 1
+2 1 1
+2 1 1
+2 1 1
+2 1 1
+2 1 1
+2 1 1
+2 1 1
+2 1 1
+2 1 1
+EXPLAIN SELECT COUNT(DISTINCT c, a, b) FROM t2
+WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range a a 15 NULL 1 Using where; Using index for group-by
+SELECT COUNT(DISTINCT c, a, b) FROM t2
+WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
+COUNT(DISTINCT c, a, b)
+EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
+GROUP BY b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref a a 5 const 1 Using where; Using index
+SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
+GROUP BY b;
+COUNT(DISTINCT b) SUM(DISTINCT b)
+EXPLAIN SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 10 NULL 9 Using index for group-by
+SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
+a COUNT(DISTINCT b) SUM(DISTINCT b)
+2 8 36
+2 8 36
+EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 10 NULL 9 Using index for group-by
+SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
+COUNT(DISTINCT b) SUM(DISTINCT b)
+8 36
+8 36
+EXPLAIN SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 16 Using where
+SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
+COUNT(DISTINCT a, b)
+0
+EXPLAIN SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
+WHERE b = 13 AND c = 42 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 15 NULL 9 Using where; Using index for group-by
+SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
+WHERE b = 13 AND c = 42 GROUP BY a;
+a COUNT(DISTINCT a) SUM(DISTINCT a)
+EXPLAIN SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 10 NULL 9 Using where; Using index for group-by
+SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
+COUNT(DISTINCT a, b) SUM(DISTINCT a)
+0 NULL
+EXPLAIN SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 5 NULL 9 Using index for group-by
+SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
+SUM(DISTINCT a) MAX(b)
+1 8
+2 8
+EXPLAIN SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 15 NULL 9 Using index for group-by
+SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
+42 * (a + c + COUNT(DISTINCT c, a, b))
+126
+126
+126
+126
+126
+126
+126
+168
+168
+168
+168
+168
+168
+168
+168
+168
+EXPLAIN SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NULL a 5 NULL 9 Using index for group-by
+SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
+(SUM(DISTINCT a) + MAX(b))
+9
+10
+DROP TABLE t1,t2;
+# end of WL#3220 tests
diff --git a/mysql-test/r/index_merge_innodb.result b/mysql-test/r/index_merge_innodb.result
index 71b81d6acd2..6d130a64e35 100644
--- a/mysql-test/r/index_merge_innodb.result
+++ b/mysql-test/r/index_merge_innodb.result
@@ -1,329 +1,3 @@
-#---------------- Index merge test 2 -------------------------------------------
-SET SESSION STORAGE_ENGINE = InnoDB;
-drop table if exists t1,t2;
-create table t1
-(
-key1 int not null,
-key2 int not null,
-INDEX i1(key1),
-INDEX i2(key2)
-);
-explain select * from t1 where key1 < 5 or key2 > 197;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
-select * from t1 where key1 < 5 or key2 > 197;
-key1 key2
-0 200
-1 199
-2 198
-3 197
-4 196
-explain select * from t1 where key1 < 3 or key2 > 195;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
-select * from t1 where key1 < 3 or key2 > 195;
-key1 key2
-0 200
-1 199
-2 198
-3 197
-4 196
-alter table t1 add str1 char (255) not null,
-add zeroval int not null default 0,
-add str2 char (255) not null,
-add str3 char (255) not null;
-update t1 set str1='aaa', str2='bbb', str3=concat(key2, '-', key1 div 2, '_' ,if(key1 mod 2 = 0, 'a', 'A'));
-alter table t1 add primary key (str1, zeroval, str2, str3);
-explain select * from t1 where key1 < 5 or key2 > 197;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
-select * from t1 where key1 < 5 or key2 > 197;
-key1 key2 str1 zeroval str2 str3
-4 196 aaa 0 bbb 196-2_a
-3 197 aaa 0 bbb 197-1_A
-2 198 aaa 0 bbb 198-1_a
-1 199 aaa 0 bbb 199-0_A
-0 200 aaa 0 bbb 200-0_a
-explain select * from t1 where key1 < 3 or key2 > 195;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
-select * from t1 where key1 < 3 or key2 > 195;
-key1 key2 str1 zeroval str2 str3
-4 196 aaa 0 bbb 196-2_a
-3 197 aaa 0 bbb 197-1_A
-2 198 aaa 0 bbb 198-1_a
-1 199 aaa 0 bbb 199-0_A
-0 200 aaa 0 bbb 200-0_a
-drop table t1;
-create table t1 (
-pk integer not null auto_increment primary key,
-key1 integer,
-key2 integer not null,
-filler char (200),
-index (key1),
-index (key2)
-);
-show warnings;
-Level Code Message
-explain select pk from t1 where key1 = 1 and key2 = 1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge key1,key2 key1,key2 5,4 NULL 1 Using intersect(key1,key2); Using where; Using index
-select pk from t1 where key2 = 1 and key1 = 1;
-pk
-26
-27
-select pk from t1 ignore index(key1,key2) where key2 = 1 and key1 = 1;
-pk
-26
-27
-drop table t1;
-create table t1 (
-pk int primary key auto_increment,
-key1a int,
-key2a int,
-key1b int,
-key2b int,
-dummy1 int,
-dummy2 int,
-dummy3 int,
-dummy4 int,
-key3a int,
-key3b int,
-filler1 char (200),
-index i1(key1a, key1b),
-index i2(key2a, key2b),
-index i3(key3a, key3b)
-);
-create table t2 (a int);
-insert into t2 values (0),(1),(2),(3),(4),(NULL);
-insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
-select A.a, B.a, C.a, D.a, C.a, D.a from t2 A,t2 B,t2 C, t2 D;
-insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
-select key1a, key1b, key2a, key2b, key3a, key3b from t1;
-insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
-select key1a, key1b, key2a, key2b, key3a, key3b from t1;
-analyze table t1;
-Table Op Msg_type Msg_text
-test.t1 analyze status OK
-select count(*) from t1;
-count(*)
-5184
-explain select count(*) from t1 where
-key1a = 2 and key1b is null and key2a = 2 and key2b is null;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL # Using intersect(i1,i2); Using where; Using index
-select count(*) from t1 where
-key1a = 2 and key1b is null and key2a = 2 and key2b is null;
-count(*)
-4
-explain select count(*) from t1 where
-key1a = 2 and key1b is null and key3a = 2 and key3b is null;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL # Using intersect(i1,i3); Using where; Using index
-select count(*) from t1 where
-key1a = 2 and key1b is null and key3a = 2 and key3b is null;
-count(*)
-4
-drop table t1,t2;
-create table t1 (
-id1 int,
-id2 date ,
-index idx2 (id1,id2),
-index idx1 (id2)
-);
-insert into t1 values(1,'20040101'), (2,'20040102');
-select * from t1 where id1 = 1 and id2= '20040101';
-id1 id2
-1 2004-01-01
-drop table t1;
-drop view if exists v1;
-CREATE TABLE t1 (
-`oid` int(11) unsigned NOT NULL auto_increment,
-`fk_bbk_niederlassung` int(11) unsigned NOT NULL,
-`fk_wochentag` int(11) unsigned NOT NULL,
-`uhrzeit_von` time NOT NULL COMMENT 'HH:MM',
-`uhrzeit_bis` time NOT NULL COMMENT 'HH:MM',
-`geloescht` tinyint(4) NOT NULL,
-`version` int(5) NOT NULL,
-PRIMARY KEY (`oid`),
-KEY `fk_bbk_niederlassung` (`fk_bbk_niederlassung`),
-KEY `fk_wochentag` (`fk_wochentag`),
-KEY `ix_version` (`version`)
-) DEFAULT CHARSET=latin1;
-insert into t1 values
-(1, 38, 1, '08:00:00', '13:00:00', 0, 1),
-(2, 38, 2, '08:00:00', '13:00:00', 0, 1),
-(3, 38, 3, '08:00:00', '13:00:00', 0, 1),
-(4, 38, 4, '08:00:00', '13:00:00', 0, 1),
-(5, 38, 5, '08:00:00', '13:00:00', 0, 1),
-(6, 38, 5, '08:00:00', '13:00:00', 1, 2),
-(7, 38, 3, '08:00:00', '13:00:00', 1, 2),
-(8, 38, 1, '08:00:00', '13:00:00', 1, 2),
-(9, 38, 2, '08:00:00', '13:00:00', 1, 2),
-(10, 38, 4, '08:00:00', '13:00:00', 1, 2),
-(11, 38, 1, '08:00:00', '13:00:00', 0, 3),
-(12, 38, 2, '08:00:00', '13:00:00', 0, 3),
-(13, 38, 3, '08:00:00', '13:00:00', 0, 3),
-(14, 38, 4, '08:00:00', '13:00:00', 0, 3),
-(15, 38, 5, '08:00:00', '13:00:00', 0, 3),
-(16, 38, 4, '08:00:00', '13:00:00', 0, 4),
-(17, 38, 5, '08:00:00', '13:00:00', 0, 4),
-(18, 38, 1, '08:00:00', '13:00:00', 0, 4),
-(19, 38, 2, '08:00:00', '13:00:00', 0, 4),
-(20, 38, 3, '08:00:00', '13:00:00', 0, 4),
-(21, 7, 1, '08:00:00', '13:00:00', 0, 1),
-(22, 7, 2, '08:00:00', '13:00:00', 0, 1),
-(23, 7, 3, '08:00:00', '13:00:00', 0, 1),
-(24, 7, 4, '08:00:00', '13:00:00', 0, 1),
-(25, 7, 5, '08:00:00', '13:00:00', 0, 1);
-create view v1 as
-select
-zeit1.oid AS oid,
-zeit1.fk_bbk_niederlassung AS fk_bbk_niederlassung,
-zeit1.fk_wochentag AS fk_wochentag,
-zeit1.uhrzeit_von AS uhrzeit_von,
-zeit1.uhrzeit_bis AS uhrzeit_bis,
-zeit1.geloescht AS geloescht,
-zeit1.version AS version
-from
-t1 zeit1
-where
-(zeit1.version =
-(select max(zeit2.version) AS `max(version)`
- from t1 zeit2
-where
-((zeit1.fk_bbk_niederlassung = zeit2.fk_bbk_niederlassung) and
-(zeit1.fk_wochentag = zeit2.fk_wochentag) and
-(zeit1.uhrzeit_von = zeit2.uhrzeit_von) and
-(zeit1.uhrzeit_bis = zeit2.uhrzeit_bis)
-)
-)
-)
-and (zeit1.geloescht = 0);
-select * from v1 where oid = 21;
-oid fk_bbk_niederlassung fk_wochentag uhrzeit_von uhrzeit_bis geloescht version
-21 7 1 08:00:00 13:00:00 0 1
-drop view v1;
-drop table t1;
-CREATE TABLE t1(
-t_cpac varchar(2) NOT NULL,
-t_vers varchar(4) NOT NULL,
-t_rele varchar(2) NOT NULL,
-t_cust varchar(4) NOT NULL,
-filler1 char(250) default NULL,
-filler2 char(250) default NULL,
-PRIMARY KEY (t_cpac,t_vers,t_rele,t_cust),
-UNIQUE KEY IX_4 (t_cust,t_cpac,t_vers,t_rele),
-KEY IX_5 (t_vers,t_rele,t_cust)
-);
-insert into t1 values
-('tm','2.5 ','a ',' ','',''), ('tm','2.5U','a ','stnd','',''),
-('da','3.3 ','b ',' ','',''), ('da','3.3U','b ','stnd','',''),
-('tl','7.6 ','a ',' ','',''), ('tt','7.6 ','a ',' ','',''),
-('bc','B61 ','a ',' ','',''), ('bp','B61 ','a ',' ','',''),
-('ca','B61 ','a ',' ','',''), ('ci','B61 ','a ',' ','',''),
-('cp','B61 ','a ',' ','',''), ('dm','B61 ','a ',' ','',''),
-('ec','B61 ','a ',' ','',''), ('ed','B61 ','a ',' ','',''),
-('fm','B61 ','a ',' ','',''), ('nt','B61 ','a ',' ','',''),
-('qm','B61 ','a ',' ','',''), ('tc','B61 ','a ',' ','',''),
-('td','B61 ','a ',' ','',''), ('tf','B61 ','a ',' ','',''),
-('tg','B61 ','a ',' ','',''), ('ti','B61 ','a ',' ','',''),
-('tp','B61 ','a ',' ','',''), ('ts','B61 ','a ',' ','',''),
-('wh','B61 ','a ',' ','',''), ('bc','B61U','a ','stnd','',''),
-('bp','B61U','a ','stnd','',''), ('ca','B61U','a ','stnd','',''),
-('ci','B61U','a ','stnd','',''), ('cp','B61U','a ','stnd','',''),
-('dm','B61U','a ','stnd','',''), ('ec','B61U','a ','stnd','',''),
-('fm','B61U','a ','stnd','',''), ('nt','B61U','a ','stnd','',''),
-('qm','B61U','a ','stnd','',''), ('tc','B61U','a ','stnd','',''),
-('td','B61U','a ','stnd','',''), ('tf','B61U','a ','stnd','',''),
-('tg','B61U','a ','stnd','',''), ('ti','B61U','a ','stnd','',''),
-('tp','B61U','a ','stnd','',''), ('ts','B61U','a ','stnd','',''),
-('wh','B61U','a ','stnd','','');
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `t_cpac` varchar(2) NOT NULL,
- `t_vers` varchar(4) NOT NULL,
- `t_rele` varchar(2) NOT NULL,
- `t_cust` varchar(4) NOT NULL,
- `filler1` char(250) DEFAULT NULL,
- `filler2` char(250) DEFAULT NULL,
- PRIMARY KEY (`t_cpac`,`t_vers`,`t_rele`,`t_cust`),
- UNIQUE KEY `IX_4` (`t_cust`,`t_cpac`,`t_vers`,`t_rele`),
- KEY `IX_5` (`t_vers`,`t_rele`,`t_cust`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1
-select t_vers,t_rele,t_cust,filler1 from t1 where t_vers = '7.6';
-t_vers t_rele t_cust filler1
-7.6 a
-7.6 a
-select t_vers,t_rele,t_cust,filler1 from t1 where t_vers = '7.6'
- and t_rele='a' and t_cust = ' ';
-t_vers t_rele t_cust filler1
-7.6 a
-7.6 a
-drop table t1;
-create table t1 (
-pk int(11) not null auto_increment,
-a int(11) not null default '0',
-b int(11) not null default '0',
-c int(11) not null default '0',
-filler1 datetime, filler2 varchar(15),
-filler3 longtext,
-kp1 varchar(4), kp2 varchar(7),
-kp3 varchar(2), kp4 varchar(4),
-kp5 varchar(7),
-filler4 char(1),
-primary key (pk),
-key idx1(a,b,c),
-key idx2(c),
-key idx3(kp1,kp2,kp3,kp4,kp5)
-) default charset=latin1;
-set @fill=NULL;
-SELECT COUNT(*) FROM t1 WHERE b = 0 AND a = 0 AND c = 13286427 AND
-kp1='279' AND kp2='ELM0678' AND kp3='6' AND kp4='10' AND kp5 = 'R ';
-COUNT(*)
-1
-drop table t1;
-create table t1
-(
-key1 int not null,
-key2 int not null default 0,
-key3 int not null default 0
-);
-insert into t1(key1) values (1),(2),(3),(4),(5),(6),(7),(8);
-set @d=8;
-insert into t1 (key1) select key1+@d from t1;
-set @d=@d*2;
-insert into t1 (key1) select key1+@d from t1;
-set @d=@d*2;
-insert into t1 (key1) select key1+@d from t1;
-set @d=@d*2;
-insert into t1 (key1) select key1+@d from t1;
-set @d=@d*2;
-insert into t1 (key1) select key1+@d from t1;
-set @d=@d*2;
-insert into t1 (key1) select key1+@d from t1;
-set @d=@d*2;
-insert into t1 (key1) select key1+@d from t1;
-set @d=@d*2;
-alter table t1 add index i2(key2);
-alter table t1 add index i3(key3);
-update t1 set key2=key1,key3=key1;
-explain select * from t1 where (key3 > 30 and key3<35) or (key2 >32 and key2 < 40);
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge i2,i3 i3,i2 4,4 NULL 9 Using sort_union(i3,i2); Using where
-select * from t1 where (key3 > 30 and key3<35) or (key2 >32 and key2 < 40);
-key1 key2 key3
-31 31 31
-32 32 32
-33 33 33
-34 34 34
-35 35 35
-36 36 36
-37 37 37
-38 38 38
-39 39 39
-drop table t1;
#---------------- 2-sweeps read Index merge test 2 -------------------------------
SET SESSION STORAGE_ENGINE = InnoDB;
drop table if exists t1;
diff --git a/mysql-test/r/information_schema-big.result b/mysql-test/r/information_schema-big.result
new file mode 100644
index 00000000000..248b8d606dc
--- /dev/null
+++ b/mysql-test/r/information_schema-big.result
@@ -0,0 +1,93 @@
+DROP TABLE IF EXISTS t0,t1,t2,t3,t4,t5;
+DROP VIEW IF EXISTS v1;
+#
+# Bug#18925: subqueries with MIN/MAX functions on INFORMARTION_SCHEMA
+#
+SELECT t.table_name, c1.column_name
+FROM information_schema.tables t
+INNER JOIN
+information_schema.columns c1
+ON t.table_schema = c1.table_schema AND
+t.table_name = c1.table_name
+WHERE t.table_schema = 'information_schema' AND
+c1.ordinal_position =
+( SELECT COALESCE(MIN(c2.ordinal_position),1)
+FROM information_schema.columns c2
+WHERE c2.table_schema = t.table_schema AND
+c2.table_name = t.table_name AND
+c2.column_name LIKE '%SCHEMA%'
+ )
+AND t.table_name NOT LIKE 'innodb%';
+table_name column_name
+CHARACTER_SETS CHARACTER_SET_NAME
+COLLATIONS COLLATION_NAME
+COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME
+COLUMNS TABLE_SCHEMA
+COLUMN_PRIVILEGES TABLE_SCHEMA
+ENGINES ENGINE
+EVENTS EVENT_SCHEMA
+FILES TABLE_SCHEMA
+GLOBAL_STATUS VARIABLE_NAME
+GLOBAL_VARIABLES VARIABLE_NAME
+KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
+PARTITIONS TABLE_SCHEMA
+PLUGINS PLUGIN_NAME
+PROCESSLIST ID
+PROFILING QUERY_ID
+REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA
+ROUTINES ROUTINE_SCHEMA
+SCHEMATA SCHEMA_NAME
+SCHEMA_PRIVILEGES TABLE_SCHEMA
+SESSION_STATUS VARIABLE_NAME
+SESSION_VARIABLES VARIABLE_NAME
+STATISTICS TABLE_SCHEMA
+TABLES TABLE_SCHEMA
+TABLE_CONSTRAINTS CONSTRAINT_SCHEMA
+TABLE_PRIVILEGES TABLE_SCHEMA
+TRIGGERS TRIGGER_SCHEMA
+USER_PRIVILEGES GRANTEE
+VIEWS TABLE_SCHEMA
+SELECT t.table_name, c1.column_name
+FROM information_schema.tables t
+INNER JOIN
+information_schema.columns c1
+ON t.table_schema = c1.table_schema AND
+t.table_name = c1.table_name
+WHERE t.table_schema = 'information_schema' AND
+c1.ordinal_position =
+( SELECT COALESCE(MIN(c2.ordinal_position),1)
+FROM information_schema.columns c2
+WHERE c2.table_schema = 'information_schema' AND
+c2.table_name = t.table_name AND
+c2.column_name LIKE '%SCHEMA%'
+ )
+AND t.table_name NOT LIKE 'innodb%';
+table_name column_name
+CHARACTER_SETS CHARACTER_SET_NAME
+COLLATIONS COLLATION_NAME
+COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME
+COLUMNS TABLE_SCHEMA
+COLUMN_PRIVILEGES TABLE_SCHEMA
+ENGINES ENGINE
+EVENTS EVENT_SCHEMA
+FILES TABLE_SCHEMA
+GLOBAL_STATUS VARIABLE_NAME
+GLOBAL_VARIABLES VARIABLE_NAME
+KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
+PARTITIONS TABLE_SCHEMA
+PLUGINS PLUGIN_NAME
+PROCESSLIST ID
+PROFILING QUERY_ID
+REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA
+ROUTINES ROUTINE_SCHEMA
+SCHEMATA SCHEMA_NAME
+SCHEMA_PRIVILEGES TABLE_SCHEMA
+SESSION_STATUS VARIABLE_NAME
+SESSION_VARIABLES VARIABLE_NAME
+STATISTICS TABLE_SCHEMA
+TABLES TABLE_SCHEMA
+TABLE_CONSTRAINTS CONSTRAINT_SCHEMA
+TABLE_PRIVILEGES TABLE_SCHEMA
+TRIGGERS TRIGGER_SCHEMA
+USER_PRIVILEGES GRANTEE
+VIEWS TABLE_SCHEMA
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index ffa9b596d2f..9a66c809226 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -1226,94 +1226,6 @@ f1()
DROP FUNCTION f1;
DROP PROCEDURE p1;
DROP USER mysql_bug20230@localhost;
-SELECT t.table_name, c1.column_name
-FROM information_schema.tables t
-INNER JOIN
-information_schema.columns c1
-ON t.table_schema = c1.table_schema AND
-t.table_name = c1.table_name
-WHERE t.table_schema = 'information_schema' AND
-c1.ordinal_position =
-( SELECT COALESCE(MIN(c2.ordinal_position),1)
-FROM information_schema.columns c2
-WHERE c2.table_schema = t.table_schema AND
-c2.table_name = t.table_name AND
-c2.column_name LIKE '%SCHEMA%'
- )
-AND t.table_name not like 'innodb_%';
-table_name column_name
-CHARACTER_SETS CHARACTER_SET_NAME
-COLLATIONS COLLATION_NAME
-COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME
-COLUMNS TABLE_SCHEMA
-COLUMN_PRIVILEGES TABLE_SCHEMA
-ENGINES ENGINE
-EVENTS EVENT_SCHEMA
-FILES TABLE_SCHEMA
-GLOBAL_STATUS VARIABLE_NAME
-GLOBAL_VARIABLES VARIABLE_NAME
-KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
-PARTITIONS TABLE_SCHEMA
-PLUGINS PLUGIN_NAME
-PROCESSLIST ID
-PROFILING QUERY_ID
-REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA
-ROUTINES ROUTINE_SCHEMA
-SCHEMATA SCHEMA_NAME
-SCHEMA_PRIVILEGES TABLE_SCHEMA
-SESSION_STATUS VARIABLE_NAME
-SESSION_VARIABLES VARIABLE_NAME
-STATISTICS TABLE_SCHEMA
-TABLES TABLE_SCHEMA
-TABLE_CONSTRAINTS CONSTRAINT_SCHEMA
-TABLE_PRIVILEGES TABLE_SCHEMA
-TRIGGERS TRIGGER_SCHEMA
-USER_PRIVILEGES GRANTEE
-VIEWS TABLE_SCHEMA
-SELECT t.table_name, c1.column_name
-FROM information_schema.tables t
-INNER JOIN
-information_schema.columns c1
-ON t.table_schema = c1.table_schema AND
-t.table_name = c1.table_name
-WHERE t.table_schema = 'information_schema' AND
-c1.ordinal_position =
-( SELECT COALESCE(MIN(c2.ordinal_position),1)
-FROM information_schema.columns c2
-WHERE c2.table_schema = 'information_schema' AND
-c2.table_name = t.table_name AND
-c2.column_name LIKE '%SCHEMA%'
- )
-AND t.table_name not like 'innodb_%';
-table_name column_name
-CHARACTER_SETS CHARACTER_SET_NAME
-COLLATIONS COLLATION_NAME
-COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME
-COLUMNS TABLE_SCHEMA
-COLUMN_PRIVILEGES TABLE_SCHEMA
-ENGINES ENGINE
-EVENTS EVENT_SCHEMA
-FILES TABLE_SCHEMA
-GLOBAL_STATUS VARIABLE_NAME
-GLOBAL_VARIABLES VARIABLE_NAME
-KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
-PARTITIONS TABLE_SCHEMA
-PLUGINS PLUGIN_NAME
-PROCESSLIST ID
-PROFILING QUERY_ID
-REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA
-ROUTINES ROUTINE_SCHEMA
-SCHEMATA SCHEMA_NAME
-SCHEMA_PRIVILEGES TABLE_SCHEMA
-SESSION_STATUS VARIABLE_NAME
-SESSION_VARIABLES VARIABLE_NAME
-STATISTICS TABLE_SCHEMA
-TABLES TABLE_SCHEMA
-TABLE_CONSTRAINTS CONSTRAINT_SCHEMA
-TABLE_PRIVILEGES TABLE_SCHEMA
-TRIGGERS TRIGGER_SCHEMA
-USER_PRIVILEGES GRANTEE
-VIEWS TABLE_SCHEMA
SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test');
MAX(table_name)
VIEWS
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 1e4fc91b8bd..bc77072f67a 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -942,25 +942,29 @@ group_concat(t1.b,t2.c)
aaaaa
bbbbb
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 1 was cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a;
group_concat(t1.b,t2.c)
aaaaa
bbbbb
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 1 was cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by a;
group_concat(t1.b,t2.c)
aaaaa
bbbbb
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 1 was cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by a;
group_concat(t1.b,t2.c)
aaaaa
bbbbb
Warnings:
-Warning 1260 2 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 1 was cut by GROUP_CONCAT()
+Warning 1260 Row 2 was cut by GROUP_CONCAT()
drop table t1, t2;
set group_concat_max_len=default;
create table t1 (gid smallint(5) unsigned not null, x int(11) not null, y int(11) not null, art int(11) not null, primary key (gid,x,y));
diff --git a/mysql-test/r/loadxml.result b/mysql-test/r/loadxml.result
new file mode 100644
index 00000000000..d7967a105f8
--- /dev/null
+++ b/mysql-test/r/loadxml.result
@@ -0,0 +1,79 @@
+drop table if exists t1, t2;
+create table t1 (a int, b varchar(64));
+-- Load a static XML file
+load xml infile '../../std_data/loadxml.dat' into table t1
+rows identified by '<row>';
+select * from t1 order by a;
+a b
+1 b1
+2 b2
+3 b3
+11 b11
+111 b111
+112 b112 & < > " ' &unknown; -- check entities
+212 b212
+213 b213
+214 b214
+215 b215
+216 &bb b;
+delete from t1;
+-- Load a static XML file with 'IGNORE num ROWS'
+load xml infile '../../std_data/loadxml.dat' into table t1
+rows identified by '<row>' ignore 4 rows;
+select * from t1 order by a;
+a b
+111 b111
+112 b112 & < > " ' &unknown; -- check entities
+212 b212
+213 b213
+214 b214
+215 b215
+216 &bb b;
+-- Check 'mysqldump --xml' + 'LOAD XML' round trip
+delete from t1;
+load xml infile 'MYSQLTEST_VARDIR/tmp/loadxml-dump.xml' into table t1 rows identified by '<row>';;
+select * from t1 order by a;
+a b
+111 b111
+112 b112 & < > " ' &unknown; -- check entities
+212 b212
+213 b213
+214 b214
+215 b215
+216 &bb b;
+--Check that default row tag is '<row>
+delete from t1;
+load xml infile 'MYSQLTEST_VARDIR/tmp/loadxml-dump.xml' into table t1;;
+select * from t1 order by a;
+a b
+111 b111
+112 b112 & < > " ' &unknown; -- check entities
+212 b212
+213 b213
+214 b214
+215 b215
+216 &bb b;
+-- Check that 'xml' is not a keyword
+select 1 as xml;
+xml
+1
+create table t2(fl text);
+LOAD XML LOCAL INFILE "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" INTO TABLE t2 ROWS IDENTIFIED BY '<person>';;
+show processlist;
+Id User Host db Command Time State Info
+# root localhost test Query # NULL show processlist
+# root localhost test Query # Reading from net LOAD XML LOCAL INFILE "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" INTO TABLE t2 ROWS IDENTIFIED BY '<p
+drop table t1;
+drop table t2;
+create table t1 (
+id int(11) not null,
+text text,
+primary key (id)
+) engine=MyISAM default charset=latin1;
+load xml infile '../../std_data/loadxml2.dat' into table t1;
+select * from t1;
+id text
+1 line1
+line2
+line3
+drop table t1;
diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result
new file mode 100644
index 00000000000..467eb97b639
--- /dev/null
+++ b/mysql-test/r/locale.result
@@ -0,0 +1,49 @@
+DROP TABLE IF EXISTS t1;
+Start of 5.4 tests
+#
+# WL#4642 Greek locale for DAYNAME, MONTHNAME, DATE_FORMAT
+#
+SET NAMES utf8;
+SET @@lc_time_names=109;
+SELECT @@lc_time_names;
+@@lc_time_names
+el_GR
+CREATE TABLE t1 (a DATE);
+INSERT INTO t1 VALUES
+('2006-01-01'),('2006-01-02'),('2006-01-03'),
+('2006-01-04'),('2006-01-05'),('2006-01-06'),('2006-01-07');
+SELECT a, date_format(a,'%a') as abday, dayname(a) as day FROM t1 ORDER BY a;
+a abday day
+2006-01-01 ÎšÏ…Ï ÎšÏ…Ïιακή
+2006-01-02 Δευ ΔευτέÏα
+2006-01-03 ΤÏί ΤÏίτη
+2006-01-04 Τετ ΤετάÏτη
+2006-01-05 Πέμ Πέμπτη
+2006-01-06 Î Î±Ï Î Î±Ïασκευή
+2006-01-07 Σάβ Σάββατο
+DROP TABLE t1;
+CREATE TABLE t1 (a DATE);
+INSERT INTO t1 VALUES
+('2006-01-01'),('2006-02-01'),('2006-03-01'),
+('2006-04-01'),('2006-05-01'),('2006-06-01'),
+('2006-07-01'),('2006-08-01'),('2006-09-01'),
+('2006-10-01'),('2006-11-01'),('2006-12-01');
+SELECT a, date_format(a,'%b') as abmon, monthname(a) as mon FROM t1 ORDER BY a;
+a abmon mon
+2006-01-01 Ιαν ΙανουάÏιος
+2006-02-01 Φεβ ΦεβÏουάÏιος
+2006-03-01 ÎœÎ¬Ï ÎœÎ¬Ïτιος
+2006-04-01 Î‘Ï€Ï Î‘Ï€Ïίλιος
+2006-05-01 Μάι Μάιος
+2006-06-01 ΙοÏν ΙοÏνιος
+2006-07-01 ΙοÏλ ΙοÏλιος
+2006-08-01 ΑÏγ ΑÏγουστος
+2006-09-01 Σεπ ΣεπτέμβÏιος
+2006-10-01 Οκτ ΟκτώβÏιος
+2006-11-01 Îοέ ÎοέμβÏιος
+2006-12-01 Δεκ ΔεκέμβÏιος
+SELECT format(123456.789, 3, 'el_GR');
+format(123456.789, 3, 'el_GR')
+123456.789
+DROP TABLE t1;
+End of 5.4 tests
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 893ea5acf88..a2248d3d878 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -914,7 +914,7 @@ SELECT * FROM tm1;
ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
CHECK TABLE tm1;
Table Op Msg_type Msg_text
-test.tm1 check Error Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist
+test.tm1 check Warning Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist
test.tm1 check Error Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
test.tm1 check error Corrupt
ALTER TABLE t2 MODIFY a INT;
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index 6b498e55d85..58dd97ee9f3 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -2,7 +2,7 @@ drop table if exists t1,t2;
select 1, 1.0, -1, "hello", NULL;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def 1 8 1 1 N 32897 0 63
-def 1.0 246 4 3 N 129 1 63
+def 1.0 246 4 3 N 32897 1 63
def -1 8 2 2 N 32897 0 63
def hello 253 5 5 N 1 31 8
def NULL 6 0 0 Y 32896 0 63
@@ -18,7 +18,7 @@ def test t1 t1 d d 3 11 0 Y 32768 0 63
def test t1 t1 e e 8 20 0 Y 32768 0 63
def test t1 t1 f f 4 3 0 Y 32768 2 63
def test t1 t1 g g 5 4 0 Y 32768 3 63
-def test t1 t1 h h 246 7 0 Y 0 4 63
+def test t1 t1 h h 246 7 0 Y 32768 4 63
def test t1 t1 i i 13 4 0 Y 32864 0 63
def test t1 t1 j j 10 10 0 Y 128 0 63
def test t1 t1 k k 7 19 0 N 9441 0 63
@@ -199,3 +199,95 @@ def IFNULL(d, d) IFNULL(d, d) 10 10 10 Y 128 0 63
def LEAST(d, d) LEAST(d, d) 10 10 10 Y 128 0 63
DROP TABLE t1;
End of 5.0 tests
+create table t1(
+# numeric types
+bool_col bool,
+boolean_col boolean,
+bit_col bit(5),
+tiny tinyint,
+tiny_uns tinyint unsigned,
+small smallint,
+small_uns smallint unsigned,
+medium mediumint,
+medium_uns mediumint unsigned,
+int_col int,
+int_col_uns int unsigned,
+big bigint,
+big_uns bigint unsigned,
+decimal_col decimal(10,5),
+# synonyms of DECIMAL
+numeric_col numeric(10),
+fixed_col fixed(10),
+dec_col dec(10),
+decimal_col_uns decimal(10,5) unsigned,
+fcol float,
+fcol_uns float unsigned,
+dcol double,
+double_precision_col double precision,
+dcol_uns double unsigned,
+# date/time types
+date_col date,
+time_col time,
+timestamp_col timestamp,
+year_col year,
+datetime_col datetime,
+# string types
+char_col char(5),
+varchar_col varchar(10),
+binary_col binary(10),
+varbinary_col varbinary(10),
+tinyblob_col tinyblob,
+blob_col blob,
+mediumblob_col mediumblob,
+longblob_col longblob,
+text_col text,
+mediumtext_col mediumtext,
+longtext_col longtext,
+enum_col enum("A","B","C"),
+set_col set("F","E","D")
+);
+select * from t1;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 t1 bool_col bool_col 1 1 0 Y 32768 0 63
+def test t1 t1 boolean_col boolean_col 1 1 0 Y 32768 0 63
+def test t1 t1 bit_col bit_col 16 5 0 Y 32 0 63
+def test t1 t1 tiny tiny 1 4 0 Y 32768 0 63
+def test t1 t1 tiny_uns tiny_uns 1 3 0 Y 32800 0 63
+def test t1 t1 small small 2 6 0 Y 32768 0 63
+def test t1 t1 small_uns small_uns 2 5 0 Y 32800 0 63
+def test t1 t1 medium medium 9 9 0 Y 32768 0 63
+def test t1 t1 medium_uns medium_uns 9 8 0 Y 32800 0 63
+def test t1 t1 int_col int_col 3 11 0 Y 32768 0 63
+def test t1 t1 int_col_uns int_col_uns 3 10 0 Y 32800 0 63
+def test t1 t1 big big 8 20 0 Y 32768 0 63
+def test t1 t1 big_uns big_uns 8 20 0 Y 32800 0 63
+def test t1 t1 decimal_col decimal_col 246 12 0 Y 32768 5 63
+def test t1 t1 numeric_col numeric_col 246 11 0 Y 32768 0 63
+def test t1 t1 fixed_col fixed_col 246 11 0 Y 32768 0 63
+def test t1 t1 dec_col dec_col 246 11 0 Y 32768 0 63
+def test t1 t1 decimal_col_uns decimal_col_uns 246 11 0 Y 32800 5 63
+def test t1 t1 fcol fcol 4 12 0 Y 32768 31 63
+def test t1 t1 fcol_uns fcol_uns 4 12 0 Y 32800 31 63
+def test t1 t1 dcol dcol 5 22 0 Y 32768 31 63
+def test t1 t1 double_precision_col double_precision_col 5 22 0 Y 32768 31 63
+def test t1 t1 dcol_uns dcol_uns 5 22 0 Y 32800 31 63
+def test t1 t1 date_col date_col 10 10 0 Y 128 0 63
+def test t1 t1 time_col time_col 11 8 0 Y 128 0 63
+def test t1 t1 timestamp_col timestamp_col 7 19 0 N 9441 0 63
+def test t1 t1 year_col year_col 13 4 0 Y 32864 0 63
+def test t1 t1 datetime_col datetime_col 12 19 0 Y 128 0 63
+def test t1 t1 char_col char_col 254 5 0 Y 0 0 8
+def test t1 t1 varchar_col varchar_col 253 10 0 Y 0 0 8
+def test t1 t1 binary_col binary_col 254 10 0 Y 128 0 63
+def test t1 t1 varbinary_col varbinary_col 253 10 0 Y 128 0 63
+def test t1 t1 tinyblob_col tinyblob_col 252 255 0 Y 144 0 63
+def test t1 t1 blob_col blob_col 252 65535 0 Y 144 0 63
+def test t1 t1 mediumblob_col mediumblob_col 252 16777215 0 Y 144 0 63
+def test t1 t1 longblob_col longblob_col 252 4294967295 0 Y 144 0 63
+def test t1 t1 text_col text_col 252 65535 0 Y 16 0 8
+def test t1 t1 mediumtext_col mediumtext_col 252 16777215 0 Y 16 0 8
+def test t1 t1 longtext_col longtext_col 252 4294967295 0 Y 16 0 8
+def test t1 t1 enum_col enum_col 254 1 0 Y 256 0 8
+def test t1 t1 set_col set_col 254 5 0 Y 2048 0 8
+bool_col boolean_col bit_col tiny tiny_uns small small_uns medium medium_uns int_col int_col_uns big big_uns decimal_col numeric_col fixed_col dec_col decimal_col_uns fcol fcol_uns dcol double_precision_col dcol_uns date_col time_col timestamp_col year_col datetime_col char_col varchar_col binary_col varbinary_col tinyblob_col blob_col mediumblob_col longblob_col text_col mediumtext_col longtext_col enum_col set_col
+drop table t1;
diff --git a/mysql-test/r/myisam-system.result b/mysql-test/r/myisam-system.result
index e0629d955ae..b3ba8066f5c 100644
--- a/mysql-test/r/myisam-system.result
+++ b/mysql-test/r/myisam-system.result
@@ -2,7 +2,7 @@ drop table if exists t1,t2;
create table t1 (a int) engine=myisam;
drop table if exists t1;
Warnings:
-Error 2 Can't find file: 't1' (errno: 2)
+Warning 2 Can't find file: 't1' (errno: 2)
create table t1 (a int) engine=myisam;
drop table t1;
Got one of the listed errors
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index 8162e1aca05..e4889b86987 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -40,7 +40,7 @@ CREATE TABLE `t1` (
`a` decimal(64,20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
-INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000');
+INSERT INTO `t1` VALUES (1234567890123456789012345678901234567890.00000000000000000000),(987654321098765432109876543210987654321.00000000000000000000);
DROP TABLE t1;
#
# Bug#2055 mysqldump should replace "-inf" numeric field values with "NULL"
@@ -77,7 +77,7 @@ CREATE TABLE `t1` (
`b` float DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
-INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456);
+INSERT INTO `t1` VALUES (1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456);
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `t1` (
@@ -85,7 +85,7 @@ CREATE TABLE `t1` (
`b` float DEFAULT NULL
);
/*!40101 SET character_set_client = @saved_cs_client */;
-INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456);
+INSERT INTO `t1` VALUES (1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456);
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
@@ -108,7 +108,7 @@ CREATE TABLE `t1` (
LOCK TABLES `t1` WRITE;
/*!40000 ALTER TABLE `t1` DISABLE KEYS */;
-INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456);
+INSERT INTO `t1` VALUES (1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456);
/*!40000 ALTER TABLE `t1` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
@@ -135,7 +135,7 @@ CREATE TABLE `t1` (
);
/*!40101 SET character_set_client = @saved_cs_client */;
-INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456);
+INSERT INTO `t1` VALUES (1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456),(1.23450,2.3456);
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index 2d54a66fe11..a76cb2ba225 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -1226,7 +1226,6 @@ COMMIT;
END|
CALL test.p1(12);
Warnings:
-Note 1051 Unknown table 't1'
Warning 1196 Some non-transactional changed tables couldn't be rolled back
CALL test.p1(13);
Warnings:
diff --git a/mysql-test/r/partition_hash.result b/mysql-test/r/partition_hash.result
index 19da70db5a0..dcefd70ff43 100644
--- a/mysql-test/r/partition_hash.result
+++ b/mysql-test/r/partition_hash.result
@@ -93,7 +93,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where
explain partitions select * from t1 where a >= 1 and a <= 5;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where
+1 SIMPLE t1 p0,p1,p2 ALL NULL NULL NULL NULL 9 Using where
drop table t1;
CREATE TABLE t1 (
a int not null,
diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result
index 769d499fc0a..d8bff2cbe01 100644
--- a/mysql-test/r/partition_pruning.result
+++ b/mysql-test/r/partition_pruning.result
@@ -2229,3 +2229,22 @@ explain partitions select * from t1 where recdate < '2006-01-01 00:00:00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
drop table t1;
+#
+# BUG#33730 Full table scan instead selected partitions for query more than 10 partitions
+#
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (a int)
+partition by range(a+0) (
+partition p0 values less than (64),
+partition p1 values less than (128),
+partition p2 values less than (255)
+);
+insert into t1 select A.a + 10*B.a from t0 A, t0 B;
+explain partitions select * from t1 where a between 10 and 13;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 64 Using where
+explain partitions select * from t1 where a between 10 and 10+33;
+id select_type table partitions type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 p0,p1,p2 ALL NULL NULL NULL NULL 100 Using where
+drop table t0, t1;
diff --git a/mysql-test/r/partition_truncate.result b/mysql-test/r/partition_truncate.result
new file mode 100644
index 00000000000..8f594a319df
--- /dev/null
+++ b/mysql-test/r/partition_truncate.result
@@ -0,0 +1,18 @@
+drop table if exists t1, t2, t3, t4;
+create table t1 (a int)
+partition by list (a)
+(partition p1 values in (0));
+alter table t1 truncate partition p1,p1;
+ERROR HY000: Incorrect partition name
+alter table t1 truncate partition p0;
+ERROR HY000: Incorrect partition name
+drop table t1;
+create table t1 (a int)
+partition by list (a)
+subpartition by hash (a)
+subpartitions 1
+(partition p1 values in (1)
+(subpartition sp1));
+alter table t1 truncate partition sp1;
+ERROR HY000: Incorrect partition name
+drop table t1;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 1f8a077af40..06e6b8167fd 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -2748,17 +2748,21 @@ Warnings:
Note 1051 Unknown table 't1'
call proc_1();
Level Code Message
+Note 1051 Unknown table 't1'
drop table if exists t2;
Warnings:
Note 1051 Unknown table 't2'
call proc_1();
Level Code Message
+Note 1051 Unknown table 't2'
drop table if exists t1, t2;
Warnings:
Note 1051 Unknown table 't1'
Note 1051 Unknown table 't2'
call proc_1();
Level Code Message
+Note 1051 Unknown table 't1'
+Note 1051 Unknown table 't2'
drop procedure proc_1;
create function func_1() returns int begin show warnings; return 1; end|
ERROR 0A000: Not allowed to return a result set from a function
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index a91d13d11a1..c51863b73f7 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -59,8 +59,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 9 6 Y 0 4 63
-def test t9 t9 c12 c12 246 10 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 246 10 6 Y 32768 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 9441 0 63
@@ -1807,8 +1807,8 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 3 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 4 3 N 1 1 63
-def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 32769 1 63
+def test t5 t5 param02 param02 246 67 32 Y 32768 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
@@ -1829,7 +1829,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 67 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 32768 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
@@ -1927,8 +1927,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -1974,8 +1974,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2024,8 +2024,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2064,8 +2064,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2112,8 +2112,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2156,8 +2156,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2202,8 +2202,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2240,8 +2240,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 50c94d6cc4e..2670451f24e 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -59,8 +59,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 9 6 Y 0 4 63
-def test t9 t9 c12 c12 246 10 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 246 10 6 Y 32768 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 9441 0 63
@@ -1790,8 +1790,8 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 3 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 4 3 N 1 1 63
-def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 32769 1 63
+def test t5 t5 param02 param02 246 67 32 Y 32768 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
@@ -1812,7 +1812,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 67 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 32768 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
@@ -1910,8 +1910,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -1957,8 +1957,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2007,8 +2007,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2047,8 +2047,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2095,8 +2095,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2139,8 +2139,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2185,8 +2185,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2223,8 +2223,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index a85809d3800..4372c470b2d 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -60,8 +60,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 9 6 Y 0 4 63
-def test t9 t9 c12 c12 246 10 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 246 10 6 Y 32768 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 9441 0 63
@@ -1791,8 +1791,8 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 3 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 4 3 N 1 1 63
-def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 32769 1 63
+def test t5 t5 param02 param02 246 67 32 Y 32768 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
@@ -1813,7 +1813,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 67 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 32768 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
@@ -1911,8 +1911,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -1958,8 +1958,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2008,8 +2008,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2048,8 +2048,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2096,8 +2096,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2140,8 +2140,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2186,8 +2186,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2224,8 +2224,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index fd1b69c0ffd..35a43f7c032 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -102,8 +102,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 9 6 Y 0 4 63
-def test t9 t9 c12 c12 246 10 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 246 10 6 Y 32768 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 9441 0 63
@@ -1727,8 +1727,8 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 3 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 4 3 N 1 1 63
-def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 32769 1 63
+def test t5 t5 param02 param02 246 67 32 Y 32768 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
@@ -1749,7 +1749,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 67 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 32768 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
@@ -1847,8 +1847,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -1894,8 +1894,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -1944,8 +1944,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -1984,8 +1984,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2032,8 +2032,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2076,8 +2076,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2122,8 +2122,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2160,8 +2160,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -3124,8 +3124,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 9 6 Y 0 4 63
-def test t9 t9 c12 c12 246 10 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 246 10 6 Y 32768 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 9441 0 63
@@ -4749,8 +4749,8 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 3 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 4 3 N 1 1 63
-def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 32769 1 63
+def test t5 t5 param02 param02 246 67 32 Y 32768 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
@@ -4771,7 +4771,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 67 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 32768 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
@@ -4869,8 +4869,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -4916,8 +4916,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -4966,8 +4966,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -5006,8 +5006,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -5054,8 +5054,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -5098,8 +5098,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -5144,8 +5144,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -5182,8 +5182,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 6cabc24d0eb..89057603c3d 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -889,7 +889,7 @@ select group_concat(a) FROM t1 group by b;
group_concat(a)
1234567890
Warnings:
-Warning 1260 1 line(s) were cut by GROUP_CONCAT()
+Warning 1260 Row 1 was cut by GROUP_CONCAT()
set group_concat_max_len=1024;
select group_concat(a) FROM t1 group by b;
group_concat(a)
@@ -992,19 +992,19 @@ COUNT(*)
0
Warnings:
Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
-Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 0
+Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid';
COUNT(*)
0
Warnings:
Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1
-Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 0
+Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1
SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid';
COUNT(*)
0
Warnings:
Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
-Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 0
+Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
diff --git a/mysql-test/r/signal.result b/mysql-test/r/signal.result
new file mode 100644
index 00000000000..56140733c33
--- /dev/null
+++ b/mysql-test/r/signal.result
@@ -0,0 +1,2362 @@
+#
+# PART 1: syntax
+#
+#
+# Test every new reserved and non reserved keywords
+#
+drop table if exists signal_non_reserved;
+create table signal_non_reserved (
+class_origin int,
+subclass_origin int,
+constraint_catalog int,
+constraint_schema int,
+constraint_name int,
+catalog_name int,
+schema_name int,
+table_name int,
+column_name int,
+cursor_name int,
+message_text int,
+sqlcode int
+);
+drop table signal_non_reserved;
+drop table if exists diag_non_reserved;
+create table diag_non_reserved (
+diagnostics int,
+current int,
+stacked int,
+exception int
+);
+drop table diag_non_reserved;
+drop table if exists diag_cond_non_reserved;
+create table diag_cond_non_reserved (
+condition_identifier int,
+condition_number int,
+condition_name int,
+connection_name int,
+message_length int,
+message_octet_length int,
+parameter_mode int,
+parameter_name int,
+parameter_ordinal_position int,
+returned_sqlstate int,
+routine_catalog int,
+routine_name int,
+routine_schema int,
+server_name int,
+specific_name int,
+trigger_catalog int,
+trigger_name int,
+trigger_schema int
+);
+drop table diag_cond_non_reserved;
+drop table if exists diag_stmt_non_reserved;
+create table diag_stmt_non_reserved (
+number int,
+more int,
+command_function int,
+command_function_code int,
+dynamic_function int,
+dynamic_function_code int,
+row_count int,
+transactions_committed int,
+transactions_rolled_back int,
+transaction_active int
+);
+drop table diag_stmt_non_reserved;
+drop table if exists test_reserved;
+create table test_reserved (signal int);
+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 'signal int)' at line 1
+create table test_reserved (resignal int);
+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 'resignal int)' at line 1
+create table test_reserved (condition int);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'condition int)' at line 1
+#
+# Test the SIGNAL syntax
+#
+drop procedure if exists test_invalid;
+drop procedure if exists test_signal_syntax;
+drop function if exists test_signal_func;
+create procedure test_invalid()
+begin
+SIGNAL;
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL foo;
+end $$
+ERROR 42000: Undefined CONDITION: foo
+create procedure test_invalid()
+begin
+DECLARE foo CONDITION FOR 1234;
+SIGNAL foo;
+end $$
+ERROR HY000: SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo;
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+SIGNAL SQLSTATE '23000';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+SIGNAL SQLSTATE VALUE '23000';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET CLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET SUBCLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET CONSTRAINT_CATALOG = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET CONSTRAINT_SCHEMA = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET CONSTRAINT_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET CATALOG_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET SCHEMA_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET TABLE_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET COLUMN_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET CURSOR_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MESSAGE_TEXT = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+create procedure test_invalid()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET CLASS_ORIGIN = 'foo', CLASS_ORIGIN = 'bar';
+end $$
+ERROR 42000: Duplicate condition information item 'CLASS_ORIGIN'
+create procedure test_invalid()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MESSAGE_TEXT = 'foo', MESSAGE_TEXT = 'bar';
+end $$
+ERROR 42000: Duplicate condition information item 'MESSAGE_TEXT'
+create procedure test_invalid()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 'foo', MYSQL_ERRNO = 'bar';
+end $$
+ERROR 42000: Duplicate condition information item 'MYSQL_ERRNO'
+create procedure test_signal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET
+CLASS_ORIGIN = 'foo',
+SUBCLASS_ORIGIN = 'foo',
+CONSTRAINT_CATALOG = 'foo',
+CONSTRAINT_SCHEMA = 'foo',
+CONSTRAINT_NAME = 'foo',
+CATALOG_NAME = 'foo',
+SCHEMA_NAME = 'foo',
+TABLE_NAME = 'foo',
+COLUMN_NAME = 'foo',
+CURSOR_NAME = 'foo',
+MESSAGE_TEXT = 'foo',
+MYSQL_ERRNO = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+SIGNAL SQLSTATE '00000' $$
+ERROR 42000: Bad SQLSTATE: '00000'
+SIGNAL SQLSTATE '00001' $$
+ERROR 42000: Bad SQLSTATE: '00001'
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '00000';
+end $$
+ERROR 42000: Bad SQLSTATE: '00000'
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '00001';
+end $$
+ERROR 42000: Bad SQLSTATE: '00001'
+#
+# Test conditions information that SIGNAL can not set
+#
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET bla_bla = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'bla_bla = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET CONDITION_IDENTIFIER = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CONDITION_IDENTIFIER = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET CONDITION_NUMBER = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CONDITION_NUMBER = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET CONNECTION_NAME = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CONNECTION_NAME = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET MESSAGE_LENGTH = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MESSAGE_LENGTH = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET MESSAGE_OCTET_LENGTH = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'MESSAGE_OCTET_LENGTH = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET PARAMETER_MODE = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARAMETER_MODE = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET PARAMETER_NAME = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARAMETER_NAME = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET PARAMETER_ORDINAL_POSITION = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARAMETER_ORDINAL_POSITION = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET RETURNED_SQLSTATE = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'RETURNED_SQLSTATE = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET ROUTINE_CATALOG = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ROUTINE_CATALOG = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET ROUTINE_NAME = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ROUTINE_NAME = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET ROUTINE_SCHEMA = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ROUTINE_SCHEMA = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET SERVER_NAME = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SERVER_NAME = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET SPECIFIC_NAME = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SPECIFIC_NAME = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET TRIGGER_CATALOG = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TRIGGER_CATALOG = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET TRIGGER_NAME = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TRIGGER_NAME = 'foo';
+end' at line 3
+create procedure test_invalid()
+begin
+SIGNAL SQLSTATE '12345' SET TRIGGER_SCHEMA = 'foo';
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TRIGGER_SCHEMA = 'foo';
+end' at line 3
+#
+# Test the RESIGNAL syntax
+#
+drop procedure if exists test_invalid;
+drop procedure if exists test_resignal_syntax;
+create procedure test_invalid()
+begin
+RESIGNAL foo;
+end $$
+ERROR 42000: Undefined CONDITION: foo
+create procedure test_resignal_syntax()
+begin
+RESIGNAL;
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_invalid()
+begin
+DECLARE foo CONDITION FOR 1234;
+RESIGNAL foo;
+end $$
+ERROR HY000: SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo;
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SQLSTATE '23000';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SQLSTATE VALUE '23000';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET CLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET CLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET SUBCLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET SUBCLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET CONSTRAINT_CATALOG = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET CONSTRAINT_CATALOG = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET CONSTRAINT_SCHEMA = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET CONSTRAINT_SCHEMA = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET CONSTRAINT_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET CONSTRAINT_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET CATALOG_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET CATALOG_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET SCHEMA_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET SCHEMA_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET TABLE_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET TABLE_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET COLUMN_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET COLUMN_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET CURSOR_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET CURSOR_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET MESSAGE_TEXT = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET MESSAGE_TEXT = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+RESIGNAL SET MYSQL_ERRNO = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET MYSQL_ERRNO = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_invalid()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET CLASS_ORIGIN = 'foo', CLASS_ORIGIN = 'bar';
+end $$
+ERROR 42000: Duplicate condition information item 'CLASS_ORIGIN'
+create procedure test_invalid()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET MESSAGE_TEXT = 'foo', MESSAGE_TEXT = 'bar';
+end $$
+ERROR 42000: Duplicate condition information item 'MESSAGE_TEXT'
+create procedure test_invalid()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET MYSQL_ERRNO = 'foo', MYSQL_ERRNO = 'bar';
+end $$
+ERROR 42000: Duplicate condition information item 'MYSQL_ERRNO'
+create procedure test_resignal_syntax()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+RESIGNAL foo SET
+CLASS_ORIGIN = 'foo',
+SUBCLASS_ORIGIN = 'foo',
+CONSTRAINT_CATALOG = 'foo',
+CONSTRAINT_SCHEMA = 'foo',
+CONSTRAINT_NAME = 'foo',
+CATALOG_NAME = 'foo',
+SCHEMA_NAME = 'foo',
+TABLE_NAME = 'foo',
+COLUMN_NAME = 'foo',
+CURSOR_NAME = 'foo',
+MESSAGE_TEXT = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+create procedure test_invalid()
+begin
+RESIGNAL SQLSTATE '00000';
+end $$
+ERROR 42000: Bad SQLSTATE: '00000'
+create procedure test_invalid()
+begin
+RESIGNAL SQLSTATE '00001';
+end $$
+ERROR 42000: Bad SQLSTATE: '00001'
+#
+# PART 2: non preparable statements
+#
+prepare stmt from 'SIGNAL SQLSTATE \'23000\'';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+prepare stmt from 'RESIGNAL SQLSTATE \'23000\'';
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+#
+# PART 3: runtime execution
+#
+drop procedure if exists test_signal;
+drop procedure if exists test_resignal;
+drop table if exists t_warn;
+drop table if exists t_cursor;
+create table t_warn(a integer(2));
+create table t_cursor(a integer);
+#
+# SIGNAL can also appear in a query
+#
+SIGNAL foo;
+ERROR 42000: Undefined CONDITION: foo
+SIGNAL SQLSTATE '01000';
+Warnings:
+Warning 1640 Unhandled user-defined warning condition
+SIGNAL SQLSTATE '02000';
+ERROR 02000: Unhandled user-defined not found condition
+SIGNAL SQLSTATE '23000';
+ERROR 23000: Unhandled user-defined exception condition
+SIGNAL SQLSTATE VALUE '23000';
+ERROR 23000: Unhandled user-defined exception condition
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 65536;
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of '65536'
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 99999;
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of '99999'
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 4294967295;
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of '4294967295'
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 0;
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of '0'
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = -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
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 65535;
+ERROR HY000: Unhandled user-defined exception condition
+#
+# RESIGNAL can also appear in a query
+#
+RESIGNAL;
+ERROR 0K000: RESIGNAL when handler not active
+RESIGNAL foo;
+ERROR 42000: Undefined CONDITION: foo
+RESIGNAL SQLSTATE '12345';
+ERROR 0K000: RESIGNAL when handler not active
+RESIGNAL SQLSTATE VALUE '12345';
+ERROR 0K000: RESIGNAL when handler not active
+#
+# Different kind of SIGNAL conditions
+#
+create procedure test_signal()
+begin
+# max range
+DECLARE foo CONDITION FOR SQLSTATE 'AABBB';
+SIGNAL foo SET MYSQL_ERRNO = 65535;
+end $$
+call test_signal() $$
+ERROR AABBB: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# max range
+DECLARE foo CONDITION FOR SQLSTATE 'AABBB';
+SIGNAL foo SET MYSQL_ERRNO = 65536;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of '65536'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Error
+DECLARE foo CONDITION FOR SQLSTATE '99999';
+SIGNAL foo SET MYSQL_ERRNO = 9999;
+end $$
+call test_signal() $$
+ERROR 99999: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# warning
+DECLARE too_few_records CONDITION FOR SQLSTATE '01000';
+SIGNAL too_few_records SET MYSQL_ERRNO = 1261;
+end $$
+call test_signal() $$
+Warnings:
+Warning 1261 Unhandled user-defined warning condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Not found
+DECLARE sp_fetch_no_data CONDITION FOR SQLSTATE '02000';
+SIGNAL sp_fetch_no_data SET MYSQL_ERRNO = 1329;
+end $$
+call test_signal() $$
+ERROR 02000: Unhandled user-defined not found condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Error
+DECLARE sp_cursor_already_open CONDITION FOR SQLSTATE '24000';
+SIGNAL sp_cursor_already_open SET MYSQL_ERRNO = 1325;
+end $$
+call test_signal() $$
+ERROR 24000: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Severe error
+DECLARE lock_deadlock CONDITION FOR SQLSTATE '40001';
+SIGNAL lock_deadlock SET MYSQL_ERRNO = 1213;
+end $$
+call test_signal() $$
+ERROR 40001: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Unknown -> error
+DECLARE foo CONDITION FOR SQLSTATE "99999";
+SIGNAL foo;
+end $$
+call test_signal() $$
+ERROR 99999: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# warning, no subclass
+DECLARE warn CONDITION FOR SQLSTATE "01000";
+SIGNAL warn;
+end $$
+call test_signal() $$
+Warnings:
+Warning 1640 Unhandled user-defined warning condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# warning, with subclass
+DECLARE warn CONDITION FOR SQLSTATE "01123";
+SIGNAL warn;
+end $$
+call test_signal() $$
+Warnings:
+Warning 1640 Unhandled user-defined warning condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Not found, no subclass
+DECLARE not_found CONDITION FOR SQLSTATE "02000";
+SIGNAL not_found;
+end $$
+call test_signal() $$
+ERROR 02000: Unhandled user-defined not found condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Not found, with subclass
+DECLARE not_found CONDITION FOR SQLSTATE "02XXX";
+SIGNAL not_found;
+end $$
+call test_signal() $$
+ERROR 02XXX: Unhandled user-defined not found condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Error, no subclass
+DECLARE error CONDITION FOR SQLSTATE "12000";
+SIGNAL error;
+end $$
+call test_signal() $$
+ERROR 12000: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Error, with subclass
+DECLARE error CONDITION FOR SQLSTATE "12ABC";
+SIGNAL error;
+end $$
+call test_signal() $$
+ERROR 12ABC: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Severe error, no subclass
+DECLARE error CONDITION FOR SQLSTATE "40000";
+SIGNAL error;
+end $$
+call test_signal() $$
+ERROR 40000: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+# Severe error, with subclass
+DECLARE error CONDITION FOR SQLSTATE "40001";
+SIGNAL error;
+end $$
+call test_signal() $$
+ERROR 40001: Unhandled user-defined exception condition
+drop procedure test_signal $$
+#
+# Test the scope of condition
+#
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '99999';
+begin
+DECLARE foo CONDITION FOR 8888;
+end;
+SIGNAL foo SET MYSQL_ERRNO=9999; /* outer */
+end $$
+call test_signal() $$
+ERROR 99999: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR 9999;
+begin
+DECLARE foo CONDITION FOR SQLSTATE '88888';
+SIGNAL foo SET MYSQL_ERRNO=8888; /* inner */
+end;
+end $$
+call test_signal() $$
+ERROR 88888: Unhandled user-defined exception condition
+drop procedure test_signal $$
+#
+# Test SET MYSQL_ERRNO
+#
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '99999';
+SIGNAL foo SET MYSQL_ERRNO = 1111;
+end $$
+call test_signal() $$
+ERROR 99999: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01000";
+SIGNAL warn SET MYSQL_ERRNO = 1111;
+end $$
+call test_signal() $$
+Warnings:
+Warning 1111 Unhandled user-defined warning condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02000";
+SIGNAL not_found SET MYSQL_ERRNO = 1111;
+end $$
+call test_signal() $$
+ERROR 02000: Unhandled user-defined not found condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "55000";
+SIGNAL error SET MYSQL_ERRNO = 1111;
+end $$
+call test_signal() $$
+ERROR 55000: Unhandled user-defined exception condition
+drop procedure test_signal $$
+#
+# Test SET MESSAGE_TEXT
+#
+SIGNAL SQLSTATE '77777' SET MESSAGE_TEXT='' $$
+ERROR 77777:
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '77777';
+SIGNAL foo SET
+MESSAGE_TEXT = "",
+MYSQL_ERRNO=5678;
+end $$
+call test_signal() $$
+ERROR 77777:
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '99999';
+SIGNAL foo SET
+MESSAGE_TEXT = "Something bad happened",
+MYSQL_ERRNO=9999;
+end $$
+call test_signal() $$
+ERROR 99999: Something bad happened
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01000";
+SIGNAL warn SET MESSAGE_TEXT = "Something bad happened";
+end $$
+call test_signal() $$
+Warnings:
+Warning 1640 Something bad happened
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02000";
+SIGNAL not_found SET MESSAGE_TEXT = "Something bad happened";
+end $$
+call test_signal() $$
+ERROR 02000: Something bad happened
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "55000";
+SIGNAL error SET MESSAGE_TEXT = "Something bad happened";
+end $$
+call test_signal() $$
+ERROR 55000: Something bad happened
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE something CONDITION FOR SQLSTATE "01000";
+SIGNAL something SET MESSAGE_TEXT = _utf8 "This is a UTF8 text";
+end $$
+call test_signal() $$
+Warnings:
+Warning 1640 This is a UTF8 text
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE something CONDITION FOR SQLSTATE "01000";
+SIGNAL something SET MESSAGE_TEXT = "";
+end $$
+call test_signal() $$
+Warnings:
+Warning 1640
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01111";
+SIGNAL warn SET MESSAGE_TEXT = "á a";
+end $$
+call test_signal() $$
+Warnings:
+Warning 1640 á a
+show warnings $$
+Level Code Message
+Warning 1640 á a
+drop procedure test_signal $$
+#
+# Test SET complex expressions
+#
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+MYSQL_ERRNO = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+CLASS_ORIGIN = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'CLASS_ORIGIN' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+SUBCLASS_ORIGIN = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'SUBCLASS_ORIGIN' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+CONSTRAINT_CATALOG = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'CONSTRAINT_CATALOG' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+CONSTRAINT_SCHEMA = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'CONSTRAINT_SCHEMA' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+CONSTRAINT_NAME = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'CONSTRAINT_NAME' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+CATALOG_NAME = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'CATALOG_NAME' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+SCHEMA_NAME = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'SCHEMA_NAME' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+TABLE_NAME = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'TABLE_NAME' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+COLUMN_NAME = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'COLUMN_NAME' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+CURSOR_NAME = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'CURSOR_NAME' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE '99999';
+SIGNAL error SET
+MESSAGE_TEXT = NULL;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'MESSAGE_TEXT' can't be set to the value of 'NULL'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE something CONDITION FOR SQLSTATE '99999';
+DECLARE message_text VARCHAR(64) DEFAULT "Local string variable";
+DECLARE sqlcode INTEGER DEFAULT 1234;
+SIGNAL something SET
+MESSAGE_TEXT = message_text,
+MYSQL_ERRNO = sqlcode;
+end $$
+call test_signal() $$
+ERROR 99999: Local string variable
+drop procedure test_signal $$
+create procedure test_signal(message_text VARCHAR(64), sqlcode INTEGER)
+begin
+DECLARE something CONDITION FOR SQLSTATE "12345";
+SIGNAL something SET
+MESSAGE_TEXT = message_text,
+MYSQL_ERRNO = sqlcode;
+end $$
+call test_signal("Parameter string", NULL) $$
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of 'NULL'
+call test_signal(NULL, 1234) $$
+ERROR 42000: Variable 'MESSAGE_TEXT' can't be set to the value of 'NULL'
+call test_signal("Parameter string", 5678) $$
+ERROR 12345: Parameter string
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE something CONDITION FOR SQLSTATE "AABBB";
+SIGNAL something SET
+MESSAGE_TEXT = @message_text,
+MYSQL_ERRNO = @sqlcode;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'MESSAGE_TEXT' can't be set to the value of 'NULL'
+set @sqlcode= 12 $$
+call test_signal() $$
+ERROR 42000: Variable 'MESSAGE_TEXT' can't be set to the value of 'NULL'
+set @message_text= "User variable" $$
+call test_signal() $$
+ERROR AABBB: User variable
+drop procedure test_signal $$
+create procedure test_invalid()
+begin
+DECLARE something CONDITION FOR SQLSTATE "AABBB";
+SIGNAL something SET
+MESSAGE_TEXT = @message_text := 'illegal',
+MYSQL_ERRNO = @sqlcode := 1234;
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '
+MYSQL_ERRNO = @sqlcode := 1234;
+end' at line 5
+create procedure test_signal()
+begin
+DECLARE aaa VARCHAR(64);
+DECLARE bbb VARCHAR(64);
+DECLARE ccc VARCHAR(64);
+DECLARE ddd VARCHAR(64);
+DECLARE eee VARCHAR(64);
+DECLARE fff VARCHAR(64);
+DECLARE ggg VARCHAR(64);
+DECLARE hhh VARCHAR(64);
+DECLARE iii VARCHAR(64);
+DECLARE jjj VARCHAR(64);
+DECLARE kkk VARCHAR(64);
+DECLARE warn CONDITION FOR SQLSTATE "01234";
+set aaa= repeat("A", 64);
+set bbb= repeat("B", 64);
+set ccc= repeat("C", 64);
+set ddd= repeat("D", 64);
+set eee= repeat("E", 64);
+set fff= repeat("F", 64);
+set ggg= repeat("G", 64);
+set hhh= repeat("H", 64);
+set iii= repeat("I", 64);
+set jjj= repeat("J", 64);
+set kkk= repeat("K", 64);
+SIGNAL warn SET
+CLASS_ORIGIN = aaa,
+SUBCLASS_ORIGIN = bbb,
+CONSTRAINT_CATALOG = ccc,
+CONSTRAINT_SCHEMA = ddd,
+CONSTRAINT_NAME = eee,
+CATALOG_NAME = fff,
+SCHEMA_NAME = ggg,
+TABLE_NAME = hhh,
+COLUMN_NAME = iii,
+CURSOR_NAME = jjj,
+MESSAGE_TEXT = kkk,
+MYSQL_ERRNO = 65535;
+end $$
+call test_signal() $$
+Warnings:
+Warning 65535 KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01234";
+SIGNAL warn SET
+MYSQL_ERRNO = 999999999999999999999999999999999999999999999999999;
+end $$
+call test_signal() $$
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of '999999999999999999999999999999999999999999999999999'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE aaax VARCHAR(65);
+DECLARE bbbx VARCHAR(65);
+DECLARE cccx VARCHAR(65);
+DECLARE dddx VARCHAR(65);
+DECLARE eeex VARCHAR(65);
+DECLARE fffx VARCHAR(65);
+DECLARE gggx VARCHAR(65);
+DECLARE hhhx VARCHAR(65);
+DECLARE iiix VARCHAR(65);
+DECLARE jjjx VARCHAR(65);
+DECLARE kkkx VARCHAR(65);
+DECLARE lllx VARCHAR(129);
+DECLARE warn CONDITION FOR SQLSTATE "01234";
+set aaax= concat(repeat("A", 64), "X");
+set bbbx= concat(repeat("B", 64), "X");
+set cccx= concat(repeat("C", 64), "X");
+set dddx= concat(repeat("D", 64), "X");
+set eeex= concat(repeat("E", 64), "X");
+set fffx= concat(repeat("F", 64), "X");
+set gggx= concat(repeat("G", 64), "X");
+set hhhx= concat(repeat("H", 64), "X");
+set iiix= concat(repeat("I", 64), "X");
+set jjjx= concat(repeat("J", 64), "X");
+set kkkx= concat(repeat("K", 64), "X");
+set lllx= concat(repeat("1", 100),
+repeat("2", 20),
+repeat("8", 8),
+"X");
+SIGNAL warn SET
+CLASS_ORIGIN = aaax,
+SUBCLASS_ORIGIN = bbbx,
+CONSTRAINT_CATALOG = cccx,
+CONSTRAINT_SCHEMA = dddx,
+CONSTRAINT_NAME = eeex,
+CATALOG_NAME = fffx,
+SCHEMA_NAME = gggx,
+TABLE_NAME = hhhx,
+COLUMN_NAME = iiix,
+CURSOR_NAME = jjjx,
+MESSAGE_TEXT = lllx,
+MYSQL_ERRNO = 10000;
+end $$
+call test_signal() $$
+Warnings:
+Warning 1645 Data truncated for condition item 'CLASS_ORIGIN'
+Warning 1645 Data truncated for condition item 'SUBCLASS_ORIGIN'
+Warning 1645 Data truncated for condition item 'CONSTRAINT_CATALOG'
+Warning 1645 Data truncated for condition item 'CONSTRAINT_SCHEMA'
+Warning 1645 Data truncated for condition item 'CONSTRAINT_NAME'
+Warning 1645 Data truncated for condition item 'CATALOG_NAME'
+Warning 1645 Data truncated for condition item 'SCHEMA_NAME'
+Warning 1645 Data truncated for condition item 'TABLE_NAME'
+Warning 1645 Data truncated for condition item 'COLUMN_NAME'
+Warning 1645 Data truncated for condition item 'CURSOR_NAME'
+Warning 1645 Data truncated for condition item 'MESSAGE_TEXT'
+Warning 10000 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112222222222222222222288888888
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01234";
+DECLARE CONTINUE HANDLER for SQLSTATE "01234"
+ begin
+select "Caught by SQLSTATE";
+end;
+SIGNAL warn SET
+MESSAGE_TEXT = "Raising a warning",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by SQLSTATE
+Caught by SQLSTATE
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01234";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "Caught by number";
+end;
+SIGNAL warn SET
+MESSAGE_TEXT = "Raising a warning",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by number
+Caught by number
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01234";
+DECLARE CONTINUE HANDLER for SQLWARNING
+begin
+select "Caught by SQLWARNING";
+end;
+SIGNAL warn SET
+MESSAGE_TEXT = "Raising a warning",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by SQLWARNING
+Caught by SQLWARNING
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+DECLARE CONTINUE HANDLER for SQLSTATE "02ABC"
+ begin
+select "Caught by SQLSTATE";
+end;
+SIGNAL not_found SET
+MESSAGE_TEXT = "Raising a not found",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by SQLSTATE
+Caught by SQLSTATE
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "Caught by number";
+end;
+SIGNAL not_found SET
+MESSAGE_TEXT = "Raising a not found",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by number
+Caught by number
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+DECLARE CONTINUE HANDLER for NOT FOUND
+begin
+select "Caught by NOT FOUND";
+end;
+SIGNAL not_found SET
+MESSAGE_TEXT = "Raising a not found",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by NOT FOUND
+Caught by NOT FOUND
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "55555";
+DECLARE CONTINUE HANDLER for SQLSTATE "55555"
+ begin
+select "Caught by SQLSTATE";
+end;
+SIGNAL error SET
+MESSAGE_TEXT = "Raising an error",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by SQLSTATE
+Caught by SQLSTATE
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "55555";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "Caught by number";
+end;
+SIGNAL error SET
+MESSAGE_TEXT = "Raising an error",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by number
+Caught by number
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "55555";
+DECLARE CONTINUE HANDLER for SQLEXCEPTION
+begin
+select "Caught by SQLEXCEPTION";
+end;
+SIGNAL error SET
+MESSAGE_TEXT = "Raising an error",
+MYSQL_ERRNO = 1012;
+end $$
+call test_signal() $$
+Caught by SQLEXCEPTION
+Caught by SQLEXCEPTION
+drop procedure test_signal $$
+#
+# Test where SIGNAL can be used
+#
+create function test_signal_func() returns integer
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01XXX";
+SIGNAL warn SET
+MESSAGE_TEXT = "This function SIGNAL a warning",
+MYSQL_ERRNO = 1012;
+return 5;
+end $$
+select test_signal_func() $$
+test_signal_func()
+5
+Warnings:
+Warning 1012 This function SIGNAL a warning
+drop function test_signal_func $$
+create function test_signal_func() returns integer
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02XXX";
+SIGNAL not_found SET
+MESSAGE_TEXT = "This function SIGNAL not found",
+MYSQL_ERRNO = 1012;
+return 5;
+end $$
+select test_signal_func() $$
+ERROR 02XXX: This function SIGNAL not found
+drop function test_signal_func $$
+create function test_signal_func() returns integer
+begin
+DECLARE error CONDITION FOR SQLSTATE "50000";
+SIGNAL error SET
+MESSAGE_TEXT = "This function SIGNAL an error",
+MYSQL_ERRNO = 1012;
+return 5;
+end $$
+select test_signal_func() $$
+ERROR 50000: This function SIGNAL an error
+drop function test_signal_func $$
+drop table if exists t1 $$
+create table t1 (a integer) $$
+create trigger t1_ai after insert on t1 for each row
+begin
+DECLARE msg VARCHAR(128);
+DECLARE warn CONDITION FOR SQLSTATE "01XXX";
+set msg= concat("This trigger SIGNAL a warning, a=", NEW.a);
+SIGNAL warn SET
+MESSAGE_TEXT = msg,
+MYSQL_ERRNO = 1012;
+end $$
+insert into t1 values (1), (2) $$
+Warnings:
+Warning 1012 This trigger SIGNAL a warning, a=1
+Warning 1012 This trigger SIGNAL a warning, a=2
+drop trigger t1_ai $$
+create trigger t1_ai after insert on t1 for each row
+begin
+DECLARE msg VARCHAR(128);
+DECLARE not_found CONDITION FOR SQLSTATE "02XXX";
+set msg= concat("This trigger SIGNAL a not found, a=", NEW.a);
+SIGNAL not_found SET
+MESSAGE_TEXT = msg,
+MYSQL_ERRNO = 1012;
+end $$
+insert into t1 values (3), (4) $$
+ERROR 02XXX: This trigger SIGNAL a not found, a=3
+drop trigger t1_ai $$
+create trigger t1_ai after insert on t1 for each row
+begin
+DECLARE msg VARCHAR(128);
+DECLARE error CONDITION FOR SQLSTATE "03XXX";
+set msg= concat("This trigger SIGNAL an error, a=", NEW.a);
+SIGNAL error SET
+MESSAGE_TEXT = msg,
+MYSQL_ERRNO = 1012;
+end $$
+insert into t1 values (5), (6) $$
+ERROR 03XXX: This trigger SIGNAL an error, a=5
+drop table t1 $$
+create table t1 (errno integer, msg varchar(128)) $$
+create trigger t1_ai after insert on t1 for each row
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01XXX";
+SIGNAL warn SET
+MESSAGE_TEXT = NEW.msg,
+MYSQL_ERRNO = NEW.errno;
+end $$
+insert into t1 set errno=1012, msg='Warning message 1 in trigger' $$
+Warnings:
+Warning 1012 Warning message 1 in trigger
+insert into t1 set errno=1013, msg='Warning message 2 in trigger' $$
+Warnings:
+Warning 1013 Warning message 2 in trigger
+drop table t1 $$
+drop table if exists t1 $$
+drop procedure if exists p1 $$
+drop function if exists f1 $$
+create table t1 (s1 int) $$
+insert into t1 values (1) $$
+create procedure p1()
+begin
+declare a int;
+declare c cursor for select f1() from t1;
+declare continue handler for sqlstate '03000'
+ select "caught 03000";
+declare continue handler for 1326
+select "caught cursor is not open";
+select "Before open";
+open c;
+select "Before fetch";
+fetch c into a;
+select "Before close";
+close c;
+end $$
+create function f1() returns int
+begin
+signal sqlstate '03000';
+return 5;
+end $$
+drop table t1 $$
+drop procedure p1 $$
+drop function f1 $$
+#
+# Test the RESIGNAL runtime
+#
+create procedure test_resignal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01234";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL;
+select "after RESIGNAL";
+end;
+SIGNAL warn SET
+MESSAGE_TEXT = "Raising a warning",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Warning 1012 Raising a warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02222";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL;
+select "after RESIGNAL";
+end;
+SIGNAL not_found SET
+MESSAGE_TEXT = "Raising a not found",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02222: Raising a not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "55555";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL;
+select "after RESIGNAL";
+end;
+SIGNAL error SET
+MESSAGE_TEXT = "Raising an error",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 55555: Raising an error
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlwarning
+begin
+select "before RESIGNAL";
+RESIGNAL;
+select "after RESIGNAL";
+end;
+insert into t_warn set a= 9999999999999999;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE x integer;
+DECLARE c cursor for select * from t_cursor;
+DECLARE CONTINUE HANDLER for not found
+begin
+select "before RESIGNAL";
+RESIGNAL;
+select "after RESIGNAL";
+end;
+open c;
+fetch c into x;
+close c;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02000: No data - zero rows fetched, selected, or processed
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlexception
+begin
+select "before RESIGNAL";
+RESIGNAL;
+select "after RESIGNAL";
+end;
+drop table no_such_table;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 42S02: Unknown table 'no_such_table'
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01234";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SET
+MESSAGE_TEXT = "RESIGNAL of a warning",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL warn SET
+MESSAGE_TEXT = "Raising a warning",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Warning 5555 RESIGNAL of a warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02111";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SET
+MESSAGE_TEXT = "RESIGNAL of a not found",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL not_found SET
+MESSAGE_TEXT = "Raising a not found",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02111: RESIGNAL of a not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "33333";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SET
+MESSAGE_TEXT = "RESIGNAL of an error",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL error SET
+MESSAGE_TEXT = "Raising an error",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 33333: RESIGNAL of an error
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlwarning
+begin
+select "before RESIGNAL";
+RESIGNAL SET
+MESSAGE_TEXT = "RESIGNAL of a warning",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+insert into t_warn set a= 9999999999999999;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Warning 5555 RESIGNAL of a warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE x integer;
+DECLARE c cursor for select * from t_cursor;
+DECLARE CONTINUE HANDLER for not found
+begin
+select "before RESIGNAL";
+RESIGNAL SET
+MESSAGE_TEXT = "RESIGNAL of not found",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+open c;
+fetch c into x;
+close c;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02000: RESIGNAL of not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlexception
+begin
+select "before RESIGNAL";
+RESIGNAL SET
+MESSAGE_TEXT = "RESIGNAL of an error",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+drop table no_such_table;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 42S02: RESIGNAL of an error
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01111";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "01222" SET
+MESSAGE_TEXT = "RESIGNAL to warning",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL warn SET
+MESSAGE_TEXT = "Raising a warning",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Warning 1012 Raising a warning
+Warning 5555 RESIGNAL to warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01111";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "02222" SET
+MESSAGE_TEXT = "RESIGNAL to not found",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL warn SET
+MESSAGE_TEXT = "Raising a warning",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02222: RESIGNAL to not found
+show warnings $$
+Level Code Message
+Warning 1012 Raising a warning
+Error 5555 RESIGNAL to not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE warn CONDITION FOR SQLSTATE "01111";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "33333" SET
+MESSAGE_TEXT = "RESIGNAL to error",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL warn SET
+MESSAGE_TEXT = "Raising a warning",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 33333: RESIGNAL to error
+show warnings $$
+Level Code Message
+Warning 1012 Raising a warning
+Error 5555 RESIGNAL to error
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "01222" SET
+MESSAGE_TEXT = "RESIGNAL to warning",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL not_found SET
+MESSAGE_TEXT = "Raising a not found",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Error 1012 Raising a not found
+Warning 5555 RESIGNAL to warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "02222" SET
+MESSAGE_TEXT = "RESIGNAL to not found",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL not_found SET
+MESSAGE_TEXT = "Raising a not found",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02222: RESIGNAL to not found
+show warnings $$
+Level Code Message
+Error 1012 Raising a not found
+Error 5555 RESIGNAL to not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "33333" SET
+MESSAGE_TEXT = "RESIGNAL to error",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL not_found SET
+MESSAGE_TEXT = "Raising a not found",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 33333: RESIGNAL to error
+show warnings $$
+Level Code Message
+Error 1012 Raising a not found
+Error 5555 RESIGNAL to error
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "AAAAA";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "01222" SET
+MESSAGE_TEXT = "RESIGNAL to warning",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL error SET
+MESSAGE_TEXT = "Raising an error",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Error 1012 Raising an error
+Warning 5555 RESIGNAL to warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "AAAAA";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "02222" SET
+MESSAGE_TEXT = "RESIGNAL to not found",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL error SET
+MESSAGE_TEXT = "Raising an error",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02222: RESIGNAL to not found
+show warnings $$
+Level Code Message
+Error 1012 Raising an error
+Error 5555 RESIGNAL to not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE error CONDITION FOR SQLSTATE "AAAAA";
+DECLARE CONTINUE HANDLER for 1012
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "33333" SET
+MESSAGE_TEXT = "RESIGNAL to error",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+SIGNAL error SET
+MESSAGE_TEXT = "Raising an error",
+MYSQL_ERRNO = 1012;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 33333: RESIGNAL to error
+show warnings $$
+Level Code Message
+Error 1012 Raising an error
+Error 5555 RESIGNAL to error
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlwarning
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "01111" SET
+MESSAGE_TEXT = "RESIGNAL to a warning",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+insert into t_warn set a= 9999999999999999;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Warning 1264 Out of range value for column 'a' at row 1
+Warning 5555 RESIGNAL to a warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlwarning
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "02444" SET
+MESSAGE_TEXT = "RESIGNAL to a not found",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+insert into t_warn set a= 9999999999999999;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02444: RESIGNAL to a not found
+show warnings $$
+Level Code Message
+Warning 1264 Out of range value for column 'a' at row 1
+Error 5555 RESIGNAL to a not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlwarning
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "44444" SET
+MESSAGE_TEXT = "RESIGNAL to an error",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+insert into t_warn set a= 9999999999999999;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 44444: RESIGNAL to an error
+show warnings $$
+Level Code Message
+Warning 1264 Out of range value for column 'a' at row 1
+Error 5555 RESIGNAL to an error
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE x integer;
+DECLARE c cursor for select * from t_cursor;
+DECLARE CONTINUE HANDLER for not found
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "01111" SET
+MESSAGE_TEXT = "RESIGNAL to a warning",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+open c;
+fetch c into x;
+close c;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Error 1329 No data - zero rows fetched, selected, or processed
+Warning 5555 RESIGNAL to a warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE x integer;
+DECLARE c cursor for select * from t_cursor;
+DECLARE CONTINUE HANDLER for not found
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "02444" SET
+MESSAGE_TEXT = "RESIGNAL to a not found",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+open c;
+fetch c into x;
+close c;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02444: RESIGNAL to a not found
+show warnings $$
+Level Code Message
+Error 1329 No data - zero rows fetched, selected, or processed
+Error 5555 RESIGNAL to a not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE x integer;
+DECLARE c cursor for select * from t_cursor;
+DECLARE CONTINUE HANDLER for not found
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "44444" SET
+MESSAGE_TEXT = "RESIGNAL to an error",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+open c;
+fetch c into x;
+close c;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 44444: RESIGNAL to an error
+show warnings $$
+Level Code Message
+Error 1329 No data - zero rows fetched, selected, or processed
+Error 5555 RESIGNAL to an error
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlexception
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "01111" SET
+MESSAGE_TEXT = "RESIGNAL to a warning",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+drop table no_such_table;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+after RESIGNAL
+after RESIGNAL
+Warnings:
+Error 1051 Unknown table 'no_such_table'
+Warning 5555 RESIGNAL to a warning
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlexception
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "02444" SET
+MESSAGE_TEXT = "RESIGNAL to a not found",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+drop table no_such_table;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 02444: RESIGNAL to a not found
+show warnings $$
+Level Code Message
+Error 1051 Unknown table 'no_such_table'
+Error 5555 RESIGNAL to a not found
+drop procedure test_resignal $$
+create procedure test_resignal()
+begin
+DECLARE CONTINUE HANDLER for sqlexception
+begin
+select "before RESIGNAL";
+RESIGNAL SQLSTATE "44444" SET
+MESSAGE_TEXT = "RESIGNAL to an error",
+MYSQL_ERRNO = 5555 ;
+select "after RESIGNAL";
+end;
+drop table no_such_table;
+end $$
+call test_resignal() $$
+before RESIGNAL
+before RESIGNAL
+ERROR 44444: RESIGNAL to an error
+show warnings $$
+Level Code Message
+Error 1051 Unknown table 'no_such_table'
+Error 5555 RESIGNAL to an error
+drop procedure test_resignal $$
+#
+# More complex cases
+#
+drop procedure if exists peter_p1 $$
+drop procedure if exists peter_p2 $$
+CREATE PROCEDURE peter_p1 ()
+BEGIN
+DECLARE x CONDITION FOR 1231;
+DECLARE EXIT HANDLER FOR x
+BEGIN
+SELECT '2';
+RESIGNAL SET MYSQL_ERRNO = 9999;
+END;
+BEGIN
+DECLARE EXIT HANDLER FOR x
+BEGIN
+SELECT '1';
+RESIGNAL SET SCHEMA_NAME = 'test';
+END;
+SET @@sql_mode=NULL;
+END;
+END
+$$
+CREATE PROCEDURE peter_p2 ()
+BEGIN
+DECLARE x CONDITION for 9999;
+DECLARE EXIT HANDLER FOR x
+BEGIN
+SELECT '3';
+RESIGNAL SET MESSAGE_TEXT = 'Hi, I am a useless error message';
+END;
+CALL peter_p1();
+END
+$$
+CALL peter_p2() $$
+1
+1
+2
+2
+3
+3
+ERROR 42000: Hi, I am a useless error message
+show warnings $$
+Level Code Message
+Error 9999 Hi, I am a useless error message
+drop procedure peter_p1 $$
+drop procedure peter_p2 $$
+CREATE PROCEDURE peter_p1 ()
+BEGIN
+DECLARE x CONDITION FOR SQLSTATE '42000';
+DECLARE EXIT HANDLER FOR x
+BEGIN
+SELECT '2';
+RESIGNAL x SET MYSQL_ERRNO = 9999;
+END;
+BEGIN
+DECLARE EXIT HANDLER FOR x
+BEGIN
+SELECT '1';
+RESIGNAL x SET
+SCHEMA_NAME = 'test',
+MYSQL_ERRNO= 1231;
+END;
+/* Raises ER_WRONG_VALUE_FOR_VAR : 1231, SQLSTATE 42000 */
+SET @@sql_mode=NULL;
+END;
+END
+$$
+CREATE PROCEDURE peter_p2 ()
+BEGIN
+DECLARE x CONDITION for SQLSTATE '42000';
+DECLARE EXIT HANDLER FOR x
+BEGIN
+SELECT '3';
+RESIGNAL x SET
+MESSAGE_TEXT = 'Hi, I am a useless error message',
+MYSQL_ERRNO = 9999;
+END;
+CALL peter_p1();
+END
+$$
+CALL peter_p2() $$
+1
+1
+2
+2
+3
+3
+ERROR 42000: Hi, I am a useless error message
+show warnings $$
+Level Code Message
+Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
+Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
+Error 9999 Variable 'sql_mode' can't be set to the value of 'NULL'
+Error 9999 Hi, I am a useless error message
+drop procedure peter_p1 $$
+drop procedure peter_p2 $$
+drop procedure if exists peter_p3 $$
+Warnings:
+Note 1305 PROCEDURE peter_p3 does not exist
+create procedure peter_p3()
+begin
+declare continue handler for sqlexception
+resignal sqlstate '99002' set mysql_errno = 2;
+signal sqlstate '99001' set mysql_errno = 1, message_text = "Original";
+end $$
+call peter_p3() $$
+ERROR 99002: Original
+show warnings $$
+Level Code Message
+Error 1 Original
+Error 2 Original
+drop procedure peter_p3 $$
+drop table t_warn;
+drop table t_cursor;
+#
+# Miscelaneous test cases
+#
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 0x12; /* 18 */
+end $$
+call test_signal $$
+ERROR 12345: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 0b00010010; /* 18 */
+end $$
+call test_signal $$
+ERROR 12345: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = '65'; /* 65 */
+end $$
+call test_signal $$
+ERROR 12345: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 'A'; /* illegal */
+end $$
+call test_signal $$
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of 'A'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = "65"; /* 65 */
+end $$
+call test_signal $$
+ERROR 12345: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = "A"; /* illegal */
+end $$
+call test_signal $$
+ERROR 42000: Variable 'MYSQL_ERRNO' can't be set to the value of 'A'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = `65`; /* illegal */
+end $$
+call test_signal $$
+ERROR 42S22: Unknown column '65' in 'field list'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = `A`; /* illegal */
+end $$
+call test_signal $$
+ERROR 42S22: Unknown column 'A' in 'field list'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 3.141592; /* 3 */
+end $$
+call test_signal $$
+ERROR 12345: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 1000,
+MESSAGE_TEXT= 0x41; /* A */
+end $$
+call test_signal $$
+ERROR 12345: A
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 1000,
+MESSAGE_TEXT= 0b01000001; /* A */
+end $$
+call test_signal $$
+ERROR 12345: A
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 1000,
+MESSAGE_TEXT = "Hello";
+end $$
+call test_signal $$
+ERROR 12345: Hello
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 1000,
+MESSAGE_TEXT = 'Hello';
+end $$
+call test_signal $$
+ERROR 12345: Hello
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 1000,
+MESSAGE_TEXT = `Hello`;
+end $$
+call test_signal $$
+ERROR 42S22: Unknown column 'Hello' in 'field list'
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo SET MYSQL_ERRNO = 1000,
+MESSAGE_TEXT = 65.4321;
+end $$
+call test_signal $$
+ERROR 12345: 65.4321
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+DECLARE céèçà foo CONDITION FOR SQLSTATE '12345';
+SIGNAL céèçà SET MYSQL_ERRNO = 1000;
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '©Ã¨Ã§Ã  foo CONDITION FOR SQLSTATE '12345';
+SIGNAL céèçà SET MYSQL_ERRNO = 1' at line 3
+create procedure test_signal()
+begin
+DECLARE "céèçà" CONDITION FOR SQLSTATE '12345';
+SIGNAL "céèçà" SET MYSQL_ERRNO = 1000;
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"céèçà" CONDITION FOR SQLSTATE '12345';
+SIGNAL "céèçà" SET MYSQL_ERRNO =' at line 3
+create procedure test_signal()
+begin
+DECLARE 'céèçà' CONDITION FOR SQLSTATE '12345';
+SIGNAL 'céèçà' SET MYSQL_ERRNO = 1000;
+end $$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''céèçà' CONDITION FOR SQLSTATE '12345';
+SIGNAL 'céèçà' SET MYSQL_ERRNO =' at line 3
+create procedure test_signal()
+begin
+DECLARE `céèçà` CONDITION FOR SQLSTATE '12345';
+SIGNAL `céèçà` SET MYSQL_ERRNO = 1000;
+end $$
+call test_signal $$
+ERROR 12345: Unhandled user-defined exception condition
+drop procedure test_signal $$
+create procedure test_signal()
+begin
+SIGNAL SQLSTATE '77777' SET MYSQL_ERRNO = 1000, MESSAGE_TEXT='ÃÂÃÅÄ';
+end $$
+drop procedure test_signal $$
diff --git a/mysql-test/r/signal_code.result b/mysql-test/r/signal_code.result
new file mode 100644
index 00000000000..63db6656636
--- /dev/null
+++ b/mysql-test/r/signal_code.result
@@ -0,0 +1,35 @@
+use test;
+drop procedure if exists signal_proc;
+drop function if exists signal_func;
+create procedure signal_proc()
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo;
+SIGNAL foo SET MESSAGE_TEXT = "This is an error message";
+RESIGNAL foo;
+RESIGNAL foo SET MESSAGE_TEXT = "This is an error message";
+end $$
+create function signal_func() returns int
+begin
+DECLARE foo CONDITION FOR SQLSTATE '12345';
+SIGNAL foo;
+SIGNAL foo SET MESSAGE_TEXT = "This is an error message";
+RESIGNAL foo;
+RESIGNAL foo SET MESSAGE_TEXT = "This is an error message";
+return 0;
+end $$
+show procedure code signal_proc;
+Pos Instruction
+0 stmt 136 "SIGNAL foo"
+1 stmt 136 "SIGNAL foo SET MESSAGE_TEXT = "This i..."
+2 stmt 137 "RESIGNAL foo"
+3 stmt 137 "RESIGNAL foo SET MESSAGE_TEXT = "This..."
+drop procedure signal_proc;
+show function code signal_func;
+Pos Instruction
+0 stmt 136 "SIGNAL foo"
+1 stmt 136 "SIGNAL foo SET MESSAGE_TEXT = "This i..."
+2 stmt 137 "RESIGNAL foo"
+3 stmt 137 "RESIGNAL foo SET MESSAGE_TEXT = "This..."
+4 freturn 3 0
+drop function signal_func;
diff --git a/mysql-test/r/signal_demo1.result b/mysql-test/r/signal_demo1.result
new file mode 100644
index 00000000000..752f23a48d6
--- /dev/null
+++ b/mysql-test/r/signal_demo1.result
@@ -0,0 +1,270 @@
+drop database if exists demo;
+create database demo;
+use demo;
+create table ab_physical_person (
+person_id integer,
+first_name VARCHAR(50),
+middle_initial CHAR,
+last_name VARCHAR(50),
+primary key (person_id));
+create table ab_moral_person (
+company_id integer,
+name VARCHAR(100),
+primary key (company_id));
+create table in_inventory (
+item_id integer,
+descr VARCHAR(50),
+stock integer,
+primary key (item_id));
+create table po_order (
+po_id integer auto_increment,
+cust_type char, /* arc relationship, see cust_id */
+cust_id integer, /* FK to ab_physical_person *OR* ab_moral_person */
+primary key (po_id));
+create table po_order_line (
+po_id integer, /* FK to po_order.po_id */
+line_no integer,
+item_id integer, /* FK to in_inventory.item_id */
+qty integer);
+#
+# Schema integrity enforcement
+#
+create procedure check_pk_person(in person_type char, in id integer)
+begin
+declare x integer;
+declare msg varchar(128);
+/*
+Test integrity constraints for an 'arc' relationship.
+Based on 'person_type', 'id' points to either a
+physical person, or a moral person.
+*/
+case person_type
+when 'P' then
+begin
+select count(person_id) from ab_physical_person
+where ab_physical_person.person_id = id
+into x;
+if (x != 1)
+then
+set msg= concat('No such physical person, PK:', id);
+SIGNAL SQLSTATE '45000' SET
+MESSAGE_TEXT = msg,
+MYSQL_ERRNO = 10000;
+end if;
+end;
+when 'M' then
+begin
+select count(company_id) from ab_moral_person
+where ab_moral_person.company_id = id
+into x;
+if (x != 1)
+then
+set msg= concat('No such moral person, PK:', id);
+SIGNAL SQLSTATE '45000' SET
+MESSAGE_TEXT = msg,
+MYSQL_ERRNO = 10000;
+end if;
+end;
+else
+begin
+set msg= concat('No such person type:', person_type);
+SIGNAL SQLSTATE '45000' SET
+MESSAGE_TEXT = msg,
+MYSQL_ERRNO = 20000;
+end;
+end case;
+end
+$$
+create procedure check_pk_inventory(in id integer)
+begin
+declare x integer;
+declare msg varchar(128);
+select count(item_id) from in_inventory
+where in_inventory.item_id = id
+into x;
+if (x != 1)
+then
+set msg= concat('Failed integrity constraint, table in_inventory, PK:',
+id);
+SIGNAL SQLSTATE '45000' SET
+MESSAGE_TEXT = msg,
+MYSQL_ERRNO = 10000;
+end if;
+end
+$$
+create procedure check_pk_order(in id integer)
+begin
+declare x integer;
+declare msg varchar(128);
+select count(po_id) from po_order
+where po_order.po_id = id
+into x;
+if (x != 1)
+then
+set msg= concat('Failed integrity constraint, table po_order, PK:', id);
+SIGNAL SQLSTATE '45000' SET
+MESSAGE_TEXT = msg,
+MYSQL_ERRNO = 10000;
+end if;
+end
+$$
+create trigger po_order_bi before insert on po_order
+for each row
+begin
+call check_pk_person(NEW.cust_type, NEW.cust_id);
+end
+$$
+create trigger po_order_bu before update on po_order
+for each row
+begin
+call check_pk_person(NEW.cust_type, NEW.cust_id);
+end
+$$
+create trigger po_order_line_bi before insert on po_order_line
+for each row
+begin
+call check_pk_order(NEW.po_id);
+call check_pk_inventory(NEW.item_id);
+end
+$$
+create trigger po_order_line_bu before update on po_order_line
+for each row
+begin
+call check_pk_order(NEW.po_id);
+call check_pk_inventory(NEW.item_id);
+end
+$$
+#
+# Application helpers
+#
+create procedure po_create_order(
+in p_cust_type char,
+in p_cust_id integer,
+out id integer)
+begin
+insert into po_order set cust_type = p_cust_type, cust_id = p_cust_id;
+set id = last_insert_id();
+end
+$$
+create procedure po_add_order_line(
+in po integer,
+in line integer,
+in item integer,
+in q integer)
+begin
+insert into po_order_line set
+po_id = po, line_no = line, item_id = item, qty = q;
+end
+$$
+#
+# Create sample data
+#
+insert into ab_physical_person values
+( 1, "John", "A", "Doe"),
+( 2, "Marry", "B", "Smith")
+;
+insert into ab_moral_person values
+( 3, "ACME real estate, INC"),
+( 4, "Local school")
+;
+insert into in_inventory values
+( 100, "Table, dinner", 5),
+( 101, "Chair", 20),
+( 200, "Table, coffee", 3),
+( 300, "School table", 25),
+( 301, "School chairs", 50)
+;
+select * from ab_physical_person order by person_id;
+person_id first_name middle_initial last_name
+1 John A Doe
+2 Marry B Smith
+select * from ab_moral_person order by company_id;
+company_id name
+3 ACME real estate, INC
+4 Local school
+select * from in_inventory order by item_id;
+item_id descr stock
+100 Table, dinner 5
+101 Chair 20
+200 Table, coffee 3
+300 School table 25
+301 School chairs 50
+#
+# Entering an order
+#
+set @my_po = 0;
+/* John Doe wants 1 table and 4 chairs */
+call po_create_order("P", 1, @my_po);
+call po_add_order_line (@my_po, 1, 100, 1);
+call po_add_order_line (@my_po, 2, 101, 4);
+/* Marry Smith wants a coffee table */
+call po_create_order("P", 2, @my_po);
+call po_add_order_line (@my_po, 1, 200, 1);
+#
+# Entering bad data in an order
+#
+call po_add_order_line (@my_po, 1, 999, 1);
+ERROR 45000: Failed integrity constraint, table in_inventory, PK:999
+#
+# Entering bad data in an unknown order
+#
+call po_add_order_line (99, 1, 100, 1);
+ERROR 45000: Failed integrity constraint, table po_order, PK:99
+#
+# Entering an order for an unknown company
+#
+call po_create_order("M", 7, @my_po);
+ERROR 45000: No such moral person, PK:7
+#
+# Entering an order for an unknown person type
+#
+call po_create_order("X", 1, @my_po);
+ERROR 45000: No such person type:X
+/* The local school wants 10 class tables and 20 chairs */
+call po_create_order("M", 4, @my_po);
+call po_add_order_line (@my_po, 1, 300, 10);
+call po_add_order_line (@my_po, 2, 301, 20);
+select * from po_order;
+po_id cust_type cust_id
+1 P 1
+2 P 2
+3 M 4
+select * from po_order_line;
+po_id line_no item_id qty
+1 1 100 1
+1 2 101 4
+2 1 200 1
+3 1 300 10
+3 2 301 20
+select po_id as "PO#",
+( case cust_type
+when "P" then concat (pp.first_name,
+" ",
+pp.middle_initial,
+" ",
+pp.last_name)
+when "M" then mp.name
+end ) as "Sold to"
+ from po_order po
+left join ab_physical_person pp on po.cust_id = pp.person_id
+left join ab_moral_person mp on po.cust_id = company_id
+;
+PO# Sold to
+1 John A Doe
+2 Marry B Smith
+3 Local school
+select po_id as "PO#",
+ol.line_no as "Line",
+ol.item_id as "Item",
+inv.descr as "Description",
+ol.qty as "Quantity"
+ from po_order_line ol, in_inventory inv
+where inv.item_id = ol.item_id
+order by ol.item_id, ol.line_no;
+PO# Line Item Description Quantity
+1 1 100 Table, dinner 1
+1 2 101 Chair 4
+2 1 200 Table, coffee 1
+3 1 300 School table 10
+3 2 301 School chairs 20
+drop database demo;
diff --git a/mysql-test/r/signal_demo2.result b/mysql-test/r/signal_demo2.result
new file mode 100644
index 00000000000..223030b0624
--- /dev/null
+++ b/mysql-test/r/signal_demo2.result
@@ -0,0 +1,197 @@
+drop database if exists demo;
+create database demo;
+use demo;
+create procedure proc_top_a(p1 integer)
+begin
+## DECLARE CONTINUE HANDLER for SQLEXCEPTION, NOT FOUND
+begin
+end;
+select "Starting ...";
+call proc_middle_a(p1);
+select "The end";
+end
+$$
+create procedure proc_middle_a(p1 integer)
+begin
+DECLARE l integer;
+# without RESIGNAL:
+# Should be: DECLARE EXIT HANDLER for SQLEXCEPTION, NOT FOUND
+DECLARE EXIT HANDLER for 1 /* not sure how to handle exceptions */
+begin
+select "Oops ... now what ?";
+end;
+select "In prod_middle()";
+create temporary table t1(a integer, b integer);
+select GET_LOCK("user_mutex", 10) into l;
+insert into t1 set a = p1, b = p1;
+call proc_bottom_a(p1);
+select RELEASE_LOCK("user_mutex") into l;
+drop temporary table t1;
+end
+$$
+create procedure proc_bottom_a(p1 integer)
+begin
+select "In proc_bottom()";
+if (p1 = 1) then
+begin
+select "Doing something that works ...";
+select * from t1;
+end;
+end if;
+if (p1 = 2) then
+begin
+select "Doing something that fail (simulate an error) ...";
+drop table no_such_table;
+end;
+end if;
+if (p1 = 3) then
+begin
+select "Doing something that *SHOULD* works ...";
+select * from t1;
+end;
+end if;
+end
+$$
+call proc_top_a(1);
+Starting ...
+Starting ...
+In prod_middle()
+In prod_middle()
+In proc_bottom()
+In proc_bottom()
+Doing something that works ...
+Doing something that works ...
+a b
+1 1
+The end
+The end
+call proc_top_a(2);
+Starting ...
+Starting ...
+In prod_middle()
+In prod_middle()
+In proc_bottom()
+In proc_bottom()
+Doing something that fail (simulate an error) ...
+Doing something that fail (simulate an error) ...
+ERROR 42S02: Unknown table 'no_such_table'
+call proc_top_a(3);
+Starting ...
+Starting ...
+In prod_middle()
+In prod_middle()
+ERROR 42S01: Table 't1' already exists
+call proc_top_a(1);
+Starting ...
+Starting ...
+In prod_middle()
+In prod_middle()
+ERROR 42S01: Table 't1' already exists
+drop temporary table if exists t1;
+create procedure proc_top_b(p1 integer)
+begin
+select "Starting ...";
+call proc_middle_b(p1);
+select "The end";
+end
+$$
+create procedure proc_middle_b(p1 integer)
+begin
+DECLARE l integer;
+DECLARE EXIT HANDLER for SQLEXCEPTION, NOT FOUND
+begin
+begin
+DECLARE CONTINUE HANDLER for SQLEXCEPTION, NOT FOUND
+begin
+/* Ignore errors from the cleanup code */
+end;
+select "Doing cleanup !";
+select RELEASE_LOCK("user_mutex") into l;
+drop temporary table t1;
+end;
+RESIGNAL;
+end;
+select "In prod_middle()";
+create temporary table t1(a integer, b integer);
+select GET_LOCK("user_mutex", 10) into l;
+insert into t1 set a = p1, b = p1;
+call proc_bottom_b(p1);
+select RELEASE_LOCK("user_mutex") into l;
+drop temporary table t1;
+end
+$$
+create procedure proc_bottom_b(p1 integer)
+begin
+select "In proc_bottom()";
+if (p1 = 1) then
+begin
+select "Doing something that works ...";
+select * from t1;
+end;
+end if;
+if (p1 = 2) then
+begin
+select "Doing something that fail (simulate an error) ...";
+drop table no_such_table;
+end;
+end if;
+if (p1 = 3) then
+begin
+select "Doing something that *SHOULD* works ...";
+select * from t1;
+end;
+end if;
+end
+$$
+call proc_top_b(1);
+Starting ...
+Starting ...
+In prod_middle()
+In prod_middle()
+In proc_bottom()
+In proc_bottom()
+Doing something that works ...
+Doing something that works ...
+a b
+1 1
+The end
+The end
+call proc_top_b(2);
+Starting ...
+Starting ...
+In prod_middle()
+In prod_middle()
+In proc_bottom()
+In proc_bottom()
+Doing something that fail (simulate an error) ...
+Doing something that fail (simulate an error) ...
+Doing cleanup !
+Doing cleanup !
+ERROR 42S02: Unknown table 'no_such_table'
+call proc_top_b(3);
+Starting ...
+Starting ...
+In prod_middle()
+In prod_middle()
+In proc_bottom()
+In proc_bottom()
+Doing something that *SHOULD* works ...
+Doing something that *SHOULD* works ...
+a b
+3 3
+The end
+The end
+call proc_top_b(1);
+Starting ...
+Starting ...
+In prod_middle()
+In prod_middle()
+In proc_bottom()
+In proc_bottom()
+Doing something that works ...
+Doing something that works ...
+a b
+1 1
+The end
+The end
+drop database demo;
diff --git a/mysql-test/r/signal_demo3.result b/mysql-test/r/signal_demo3.result
new file mode 100644
index 00000000000..fea41ec2ef9
--- /dev/null
+++ b/mysql-test/r/signal_demo3.result
@@ -0,0 +1,143 @@
+SET @start_global_value = @@global.max_error_count;
+SELECT @start_global_value;
+@start_global_value
+64
+SET @start_session_value = @@session.max_error_count;
+SELECT @start_session_value;
+@start_session_value
+64
+drop database if exists demo;
+create database demo;
+use demo;
+create procedure proc_1()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_1';
+call proc_2();
+end
+$$
+create procedure proc_2()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_2';
+call proc_3();
+end
+$$
+create procedure proc_3()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_3';
+call proc_4();
+end
+$$
+create procedure proc_4()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_4';
+call proc_5();
+end
+$$
+create procedure proc_5()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_5';
+call proc_6();
+end
+$$
+create procedure proc_6()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_6';
+call proc_7();
+end
+$$
+create procedure proc_7()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_7';
+call proc_8();
+end
+$$
+create procedure proc_8()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_8';
+call proc_9();
+end
+$$
+create procedure proc_9()
+begin
+declare exit handler for sqlexception
+resignal sqlstate '45000' set message_text='Oops in proc_9';
+## Do something that fails, to see how errors are reported
+drop table oops_it_is_not_here;
+end
+$$
+call proc_1();
+ERROR 45000: Oops in proc_1
+show warnings;
+Level Code Message
+Error 1051 Unknown table 'oops_it_is_not_here'
+Error 1642 Oops in proc_9
+Error 1642 Oops in proc_8
+Error 1642 Oops in proc_7
+Error 1642 Oops in proc_6
+Error 1642 Oops in proc_5
+Error 1642 Oops in proc_4
+Error 1642 Oops in proc_3
+Error 1642 Oops in proc_2
+Error 1642 Oops in proc_1
+SET @@session.max_error_count = 5;
+SELECT @@session.max_error_count;
+@@session.max_error_count
+5
+call proc_1();
+ERROR 45000: Oops in proc_1
+show warnings;
+Level Code Message
+Error 1642 Oops in proc_5
+Error 1642 Oops in proc_4
+Error 1642 Oops in proc_3
+Error 1642 Oops in proc_2
+Error 1642 Oops in proc_1
+SET @@session.max_error_count = 7;
+SELECT @@session.max_error_count;
+@@session.max_error_count
+7
+call proc_1();
+ERROR 45000: Oops in proc_1
+show warnings;
+Level Code Message
+Error 1642 Oops in proc_7
+Error 1642 Oops in proc_6
+Error 1642 Oops in proc_5
+Error 1642 Oops in proc_4
+Error 1642 Oops in proc_3
+Error 1642 Oops in proc_2
+Error 1642 Oops in proc_1
+SET @@session.max_error_count = 9;
+SELECT @@session.max_error_count;
+@@session.max_error_count
+9
+call proc_1();
+ERROR 45000: Oops in proc_1
+show warnings;
+Level Code Message
+Error 1642 Oops in proc_9
+Error 1642 Oops in proc_8
+Error 1642 Oops in proc_7
+Error 1642 Oops in proc_6
+Error 1642 Oops in proc_5
+Error 1642 Oops in proc_4
+Error 1642 Oops in proc_3
+Error 1642 Oops in proc_2
+Error 1642 Oops in proc_1
+drop database demo;
+SET @@global.max_error_count = @start_global_value;
+SELECT @@global.max_error_count;
+@@global.max_error_count
+64
+SET @@session.max_error_count = @start_session_value;
+SELECT @@session.max_error_count;
+@@session.max_error_count
+64
diff --git a/mysql-test/r/signal_sqlmode.result b/mysql-test/r/signal_sqlmode.result
new file mode 100644
index 00000000000..8fed85eb4a9
--- /dev/null
+++ b/mysql-test/r/signal_sqlmode.result
@@ -0,0 +1,86 @@
+SET @save_sql_mode=@@sql_mode;
+SET sql_mode='';
+drop procedure if exists p;
+drop procedure if exists p2;
+drop procedure if exists p3;
+create procedure p()
+begin
+declare utf8_var VARCHAR(128) CHARACTER SET UTF8;
+set utf8_var = concat(repeat('A', 128), 'X');
+select length(utf8_var), utf8_var;
+end
+$$
+create procedure p2()
+begin
+declare msg VARCHAR(129) CHARACTER SET UTF8;
+set msg = concat(repeat('A', 128), 'X');
+select length(msg), msg;
+signal sqlstate '55555' set message_text = msg;
+end
+$$
+create procedure p3()
+begin
+declare name VARCHAR(65) CHARACTER SET UTF8;
+set name = concat(repeat('A', 64), 'X');
+select length(name), name;
+signal sqlstate '55555' set
+message_text = 'Message',
+table_name = name;
+end
+$$
+call p;
+length(utf8_var) utf8_var
+128 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+Warnings:
+Warning 1265 Data truncated for column 'utf8_var' at row 1
+call p2;
+length(msg) msg
+129 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX
+ERROR 55555: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+call p3;
+length(name) name
+65 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX
+ERROR 55555: Message
+drop procedure p;
+drop procedure p2;
+drop procedure p3;
+SET sql_mode='STRICT_ALL_TABLES';
+create procedure p()
+begin
+declare utf8_var VARCHAR(128) CHARACTER SET UTF8;
+set utf8_var = concat(repeat('A', 128), 'X');
+select length(utf8_var), utf8_var;
+end
+$$
+create procedure p2()
+begin
+declare msg VARCHAR(129) CHARACTER SET UTF8;
+set msg = concat(repeat('A', 128), 'X');
+select length(msg), msg;
+signal sqlstate '55555' set message_text = msg;
+end
+$$
+create procedure p3()
+begin
+declare name VARCHAR(65) CHARACTER SET UTF8;
+set name = concat(repeat('A', 64), 'X');
+select length(name), name;
+signal sqlstate '55555' set
+message_text = 'Message',
+table_name = name;
+end
+$$
+call p;
+ERROR 22001: Data too long for column 'utf8_var' at row 1
+call p2;
+length(msg) msg
+129 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX
+ERROR HY000: Data too long for condition item 'MESSAGE_TEXT'
+call p3;
+length(name) name
+65 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAX
+ERROR HY000: Data too long for condition item 'TABLE_NAME'
+drop procedure p;
+drop procedure p2;
+drop procedure p3;
+SET @@sql_mode=@save_sql_mode;
diff --git a/mysql-test/r/sp-dynamic.result b/mysql-test/r/sp-dynamic.result
index 34b76a9424f..cdfeb8ab020 100644
--- a/mysql-test/r/sp-dynamic.result
+++ b/mysql-test/r/sp-dynamic.result
@@ -97,8 +97,6 @@ end|
call p1()|
a
1
-Warnings:
-Note 1051 Unknown table 't1'
call p1()|
a
1
@@ -371,9 +369,6 @@ call p1(@a)|
create table t1 (a int)
@rsql
create table t2 (a int)
-Warnings:
-Note 1051 Unknown table 't1'
-Note 1051 Unknown table 't2'
select @a|
@a
0
@@ -382,9 +377,6 @@ call p1(@a)|
create table t1 (a int)
@rsql
create table t2 (a int)
-Warnings:
-Note 1051 Unknown table 't1'
-Note 1051 Unknown table 't2'
select @a|
@a
0
diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result
index f5420a62f63..f532a5284a9 100644
--- a/mysql-test/r/sp-vars.result
+++ b/mysql-test/r/sp-vars.result
@@ -110,24 +110,6 @@ v7 v8 v9 v10 v11 v12 v13 v14 v15 v16
v17 v18 v19 v20
12.00 12.12 12.00 12.12
Warnings:
-Warning 1264 Out of range value for column 'v1' at row 1
-Warning 1264 Out of range value for column 'v1u' at row 1
-Warning 1264 Out of range value for column 'v2' at row 1
-Warning 1264 Out of range value for column 'v2u' at row 1
-Warning 1264 Out of range value for column 'v3' at row 1
-Warning 1264 Out of range value for column 'v3u' at row 1
-Warning 1264 Out of range value for column 'v4' at row 1
-Warning 1264 Out of range value for column 'v4u' at row 1
-Warning 1264 Out of range value for column 'v5' at row 1
-Warning 1264 Out of range value for column 'v5u' at row 1
-Warning 1264 Out of range value for column 'v6' at row 1
-Warning 1264 Out of range value for column 'v6u' at row 1
-Warning 1366 Incorrect integer value: 'String 10 ' for column 'v10' at row 1
-Warning 1366 Incorrect integer value: 'String10' for column 'v11' at row 1
-Warning 1265 Data truncated for column 'v12' at row 1
-Warning 1265 Data truncated for column 'v13' at row 1
-Warning 1366 Incorrect integer value: 'Hello, world' for column 'v16' at row 1
-Note 1265 Data truncated for column 'v18' at row 1
Note 1265 Data truncated for column 'v20' at row 1
CALL sp_vars_check_assignment();
i1 i2 i3 i4
@@ -143,21 +125,6 @@ d1 d2 d3
d1 d2 d3
1234.00 1234.12 1234.12
Warnings:
-Warning 1264 Out of range value for column 'i1' at row 1
-Warning 1264 Out of range value for column 'i2' at row 1
-Warning 1264 Out of range value for column 'i3' at row 1
-Warning 1264 Out of range value for column 'i4' at row 1
-Warning 1264 Out of range value for column 'i1' at row 1
-Warning 1264 Out of range value for column 'i2' at row 1
-Warning 1264 Out of range value for column 'i3' at row 1
-Warning 1264 Out of range value for column 'i4' at row 1
-Warning 1264 Out of range value for column 'u1' at row 1
-Warning 1264 Out of range value for column 'u2' at row 1
-Warning 1264 Out of range value for column 'u3' at row 1
-Warning 1264 Out of range value for column 'u4' at row 1
-Warning 1264 Out of range value for column 'u1' at row 1
-Warning 1264 Out of range value for column 'u2' at row 1
-Note 1265 Data truncated for column 'd3' at row 1
Note 1265 Data truncated for column 'd3' at row 1
SELECT sp_vars_check_ret1();
sp_vars_check_ret1()
@@ -198,24 +165,6 @@ v7 v8 v9 v10 v11 v12 v13 v14 v15 v16
v17 v18 v19 v20
12.00 12.12 12.00 12.12
Warnings:
-Warning 1264 Out of range value for column 'v1' at row 1
-Warning 1264 Out of range value for column 'v1u' at row 1
-Warning 1264 Out of range value for column 'v2' at row 1
-Warning 1264 Out of range value for column 'v2u' at row 1
-Warning 1264 Out of range value for column 'v3' at row 1
-Warning 1264 Out of range value for column 'v3u' at row 1
-Warning 1264 Out of range value for column 'v4' at row 1
-Warning 1264 Out of range value for column 'v4u' at row 1
-Warning 1264 Out of range value for column 'v5' at row 1
-Warning 1264 Out of range value for column 'v5u' at row 1
-Warning 1264 Out of range value for column 'v6' at row 1
-Warning 1264 Out of range value for column 'v6u' at row 1
-Warning 1366 Incorrect integer value: 'String 10 ' for column 'v10' at row 1
-Warning 1366 Incorrect integer value: 'String10' for column 'v11' at row 1
-Warning 1265 Data truncated for column 'v12' at row 1
-Warning 1265 Data truncated for column 'v13' at row 1
-Warning 1366 Incorrect integer value: 'Hello, world' for column 'v16' at row 1
-Note 1265 Data truncated for column 'v18' at row 1
Note 1265 Data truncated for column 'v20' at row 1
CALL sp_vars_check_assignment();
i1 i2 i3 i4
@@ -231,21 +180,6 @@ d1 d2 d3
d1 d2 d3
1234.00 1234.12 1234.12
Warnings:
-Warning 1264 Out of range value for column 'i1' at row 1
-Warning 1264 Out of range value for column 'i2' at row 1
-Warning 1264 Out of range value for column 'i3' at row 1
-Warning 1264 Out of range value for column 'i4' at row 1
-Warning 1264 Out of range value for column 'i1' at row 1
-Warning 1264 Out of range value for column 'i2' at row 1
-Warning 1264 Out of range value for column 'i3' at row 1
-Warning 1264 Out of range value for column 'i4' at row 1
-Warning 1264 Out of range value for column 'u1' at row 1
-Warning 1264 Out of range value for column 'u2' at row 1
-Warning 1264 Out of range value for column 'u3' at row 1
-Warning 1264 Out of range value for column 'u4' at row 1
-Warning 1264 Out of range value for column 'u1' at row 1
-Warning 1264 Out of range value for column 'u2' at row 1
-Note 1265 Data truncated for column 'd3' at row 1
Note 1265 Data truncated for column 'd3' at row 1
SELECT sp_vars_check_ret1();
sp_vars_check_ret1()
@@ -451,10 +385,6 @@ FF
HEX(v10)
FF
Warnings:
-Warning 1264 Out of range value for column 'v8' at row 1
-Warning 1264 Out of range value for column 'v9' at row 1
-Warning 1264 Out of range value for column 'v10' at row 1
-Warning 1264 Out of range value for column 'v1' at row 1
Warning 1264 Out of range value for column 'v5' at row 1
DROP PROCEDURE p1;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 67514c314f4..d8389c78845 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -526,8 +526,6 @@ end|
delete from t1|
create table t3 ( s char(16), d int)|
call into_test4()|
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
select * from t3|
s d
into4 NULL
@@ -1120,8 +1118,6 @@ end|
select f9()|
f9()
6
-Warnings:
-Note 1051 Unknown table 't3'
select f9() from t1 limit 1|
f9()
6
@@ -1162,8 +1158,6 @@ drop temporary table t3|
select f12_1()|
f12_1()
3
-Warnings:
-Note 1051 Unknown table 't3'
select f12_1() from t1 limit 1|
f12_1()
3
@@ -2069,12 +2063,7 @@ end if;
insert into t4 values (2, rc, t3);
end|
call bug1863(10)|
-Warnings:
-Note 1051 Unknown table 'temp_t1'
-Warning 1329 No data - zero rows fetched, selected, or processed
call bug1863(10)|
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
select * from t4|
f1 rc t3
2 0 NULL
@@ -2339,11 +2328,7 @@ begin
end|
call bug4579_1()|
call bug4579_1()|
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
call bug4579_1()|
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
drop procedure bug4579_1|
drop procedure bug4579_2|
drop table t3|
@@ -3736,9 +3721,6 @@ Table Create Table
tm1 CREATE TEMPORARY TABLE `tm1` (
`spv1` decimal(3,3) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
-Warnings:
-Warning 1264 Out of range value for column 'spv1' at row 1
-Warning 1366 Incorrect decimal value: 'test' for column 'spv1' at row 1
call bug12589_2()|
Table Create Table
tm1 CREATE TEMPORARY TABLE `tm1` (
@@ -6106,35 +6088,6 @@ bug5274_f2()
x
Warnings:
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
DROP FUNCTION bug5274_f1|
DROP FUNCTION bug5274_f2|
drop procedure if exists proc_21513|
@@ -6229,20 +6182,17 @@ f1(2)
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
-Warning 1329 No data - zero rows fetched, selected, or processed
PREPARE s1 FROM 'SELECT f1(2)';
EXECUTE s1;
f1(2)
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
-Warning 1329 No data - zero rows fetched, selected, or processed
EXECUTE s1;
f1(2)
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
-Warning 1329 No data - zero rows fetched, selected, or processed
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP FUNCTION f1;
@@ -6254,6 +6204,7 @@ create procedure mysqltest_db1.sp_bug28551() begin end;
call mysqltest_db1.sp_bug28551();
show warnings;
Level Code Message
+Note 1008 Can't drop database 'mysqltest_db1'; database doesn't exist
drop database mysqltest_db1;
drop database if exists mysqltest_db1;
drop table if exists test.t1;
diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result
index 831616f491b..228fe008447 100644
--- a/mysql-test/r/sp_notembedded.result
+++ b/mysql-test/r/sp_notembedded.result
@@ -21,9 +21,11 @@ end|
call bug4902_2()|
show warnings|
Level Code Message
+Note 1305 PROCEDURE bug4902_2 does not exist
call bug4902_2()|
show warnings|
Level Code Message
+Note 1305 PROCEDURE bug4902_2 does not exist
drop procedure bug4902_2|
drop table if exists t1|
create table t1 (
diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result
index 241f4198bf7..a9e0d7f457d 100644
--- a/mysql-test/r/strict.result
+++ b/mysql-test/r/strict.result
@@ -315,8 +315,8 @@ MOD(col1,0)
NULL
NULL
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
INSERT INTO t1 (col1) VALUES(-129);
ERROR 22003: Out of range value for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES(128);
@@ -343,7 +343,7 @@ SELECT MOD(col1,0) FROM t1 WHERE col1 > 0 LIMIT 1;
MOD(col1,0)
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
UPDATE t1 SET col1 = col1 - 50 WHERE col1 < 0;
ERROR 22003: Out of range value for column 'col1' at row 1
UPDATE t1 SET col2=col2 + 50 WHERE col2 > 0;
@@ -353,16 +353,16 @@ ERROR 22012: Division by 0
set @@sql_mode='ERROR_FOR_DIVISION_BY_ZERO';
INSERT INTO t1 values (1/0,1/0);
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
set @@sql_mode='ansi,traditional';
SELECT MOD(col1,0) FROM t1 WHERE col1 > 0 LIMIT 2;
MOD(col1,0)
NULL
NULL
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
INSERT INTO t1 (col1) VALUES ('');
ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('a59b');
@@ -374,8 +374,8 @@ Warnings:
Warning 1265 Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 values (1/0,1/0);
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
set @@sql_mode='ansi';
INSERT INTO t1 values (1/0,1/0);
set @@sql_mode='ansi,traditional';
@@ -457,8 +457,8 @@ Warnings:
Warning 1265 Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 values (1/0,1/0);
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
INSERT IGNORE INTO t1 VALUES(-32769,-1),(32768,65536);
Warnings:
Warning 1264 Out of range value for column 'col1' at row 1
@@ -541,8 +541,8 @@ Warnings:
Warning 1265 Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 values (1/0,1/0);
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
INSERT IGNORE INTO t1 VALUES(-8388609,-1),(8388608,16777216);
Warnings:
Warning 1264 Out of range value for column 'col1' at row 1
@@ -625,8 +625,8 @@ Warnings:
Warning 1265 Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 values (1/0,1/0);
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
INSERT IGNORE INTO t1 values (-2147483649, -1),(2147643648,4294967296);
Warnings:
Warning 1264 Out of range value for column 'col1' at row 1
@@ -707,8 +707,8 @@ Warnings:
Warning 1265 Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 values (1/0,1/0);
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
INSERT IGNORE INTO t1 VALUES(-9223372036854775809,-1),(9223372036854775808,18446744073709551616);
Warnings:
Warning 1264 Out of range value for column 'col1' at row 1
@@ -794,7 +794,7 @@ Warnings:
Note 1265 Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 values (1/0);
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
INSERT IGNORE INTO t1 VALUES(1000),(-1000);
Warnings:
Warning 1264 Out of range value for column 'col1' at row 1
@@ -861,7 +861,7 @@ Warnings:
Warning 1265 Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 (col1) VALUES (1/0);
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
INSERT IGNORE INTO t1 VALUES (+3.4E+39,-3.4E+39);
Warnings:
Warning 1264 Out of range value for column 'col1' at row 1
@@ -910,7 +910,7 @@ Warnings:
Warning 1265 Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 (col1) values (1/0);
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
INSERT IGNORE INTO t1 VALUES (+1.9E+309,-1.9E+309);
ERROR 22007: Illegal double '1.9E+309' value found during parsing
INSERT IGNORE INTO t1 VALUES ('+2.0E+309','-2.0E+309');
@@ -1080,13 +1080,13 @@ Warnings:
Warning 1292 Truncated incorrect datetime value: '31.10.2004 15.30 abc'
insert into t1 values(STR_TO_DATE('32.10.2004 15.30','%d.%m.%Y %H.%i'));
Warnings:
-Error 1411 Incorrect datetime value: '32.10.2004 15.30' for function str_to_date
+Warning 1411 Incorrect datetime value: '32.10.2004 15.30' for function str_to_date
insert into t1 values(STR_TO_DATE('2004.12.12 22:22:33 AM','%Y.%m.%d %r'));
Warnings:
-Error 1411 Incorrect time value: '22:22:33 AM' for function str_to_date
+Warning 1411 Incorrect time value: '22:22:33 AM' for function str_to_date
insert into t1 values(STR_TO_DATE('2004.12.12 abc','%Y.%m.%d %T'));
Warnings:
-Error 1411 Incorrect time value: 'abc' for function str_to_date
+Warning 1411 Incorrect time value: 'abc' for function str_to_date
insert into t1 values(STR_TO_DATE('31.10.2004 15.30','%d.%m.%Y %H.%i'));
insert into t1 values(STR_TO_DATE('2004.12.12 11:22:33 AM','%Y.%m.%d %r'));
insert into t1 values(STR_TO_DATE('2004.12.12 10:22:59','%Y.%m.%d %T'));
@@ -1104,9 +1104,9 @@ select count(*) from t1 where STR_TO_DATE('2004.12.12 10:22:61','%Y.%m.%d %T') I
count(*)
7
Warnings:
-Error 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_date
-Error 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_date
-Error 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_date
+Warning 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_date
+Warning 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_date
+Warning 1411 Incorrect datetime value: '2004.12.12 10:22:61' for function str_to_date
drop table t1;
create table t1 (col1 char(3), col2 integer);
insert into t1 (col1) values (cast(1000 as char(3)));
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 4476735735c..000b08113c1 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -1073,7 +1073,7 @@ NULL
SET @x=2;
UPDATE t1 SET i1 = @x;
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
SELECT @x;
@x
NULL
@@ -1086,8 +1086,8 @@ NULL
SET @x=4;
UPDATE t1 SET i1 = @x;
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
SELECT @x;
@x
NULL
@@ -1190,16 +1190,16 @@ create trigger t4_bu before update on t4 for each row set @t4_bu_called:=1|
insert into t1 values(10, 10)|
set @a:=1/0|
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
select 1/0 from t1|
1/0
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
create trigger t1_bi before insert on t1 for each row set @a:=1/0|
insert into t1 values(20, 20)|
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
drop trigger t1_bi|
create trigger t1_bi before insert on t1 for each row
begin
@@ -1219,7 +1219,7 @@ end|
set @check=0, @t4_bi_called=0, @t4_bu_called=0|
insert into t1 values(30, 30)|
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
select @check, @t4_bi_called, @t4_bu_called|
@check @t4_bi_called @t4_bu_called
2 1 1
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index c3d1e400b23..1ad46821bb7 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -185,7 +185,7 @@ select 1e10/0e0;
1e10/0e0
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
create table wl1612 (col1 int, col2 decimal(38,10), col3 numeric(38,10));
insert into wl1612 values(1,12345678901234567890.1234567890,12345678901234567890.1234567890);
select * from wl1612;
@@ -205,27 +205,27 @@ NULL
NULL
NULL
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
select col2/0 from wl1612;
col2/0
NULL
NULL
NULL
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
select col3/0 from wl1612;
col3/0
NULL
NULL
NULL
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
insert into wl1612 values(5,5000.0005,5000.0005);
insert into wl1612 values(6,5000.0005,5000.0005);
select sum(col2),sum(col3) from wl1612;
@@ -788,12 +788,12 @@ select 1 / 1E-500;
1 / 1E-500
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
select 1 / 0;
1 / 0
NULL
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
set sql_mode='ansi,traditional';
CREATE TABLE Sow6_2f (col1 NUMERIC(4,2));
INSERT INTO Sow6_2f VALUES (10.55);
@@ -819,11 +819,11 @@ NULL
NULL
NULL
Warnings:
-Error 1365 Division by 0
-Error 1365 Division by 0
-Error 1365 Division by 0
-Error 1365 Division by 0
-Error 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
+Warning 1365 Division by 0
INSERT INTO Sow6_2f VALUES ('a59b');
ERROR HY000: Incorrect decimal value: 'a59b' for column 'col1' at row 1
drop table Sow6_2f;
@@ -838,12 +838,12 @@ select 9999999999999999999999999999999999999999999999999999999999999999999999999
x
99999999999999999999999999999999999999999999999999999999999999999
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x;
x
100000000000000000000000000000000000000000000000000000000000000000
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
select 0.190287977636363637 + 0.040372670 * 0 - 0;
0.190287977636363637 + 0.040372670 * 0 - 0
0.190287977636363637
@@ -1380,15 +1380,15 @@ create table t1 (c1 decimal(64));
insert into t1 values(
89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1264 Out of range value for column 'c1' at row 1
insert into t1 values(
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 *
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999);
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
Warning 1264 Out of range value for column 'c1' at row 1
insert into t1 values(1e100);
Warnings:
@@ -1432,7 +1432,7 @@ select cast(19999999999999999999 as unsigned);
cast(19999999999999999999 as unsigned)
18446744073709551615
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
create table t1(a decimal(18));
insert into t1 values(123456789012345678);
alter table t1 modify column a decimal(19);
@@ -1444,12 +1444,12 @@ select cast(11.1234 as DECIMAL(3,2));
cast(11.1234 as DECIMAL(3,2))
9.99
Warnings:
-Error 1264 Out of range value for column 'cast(11.1234 as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(11.1234 as DECIMAL(3,2))' at row 1
select * from (select cast(11.1234 as DECIMAL(3,2))) t;
cast(11.1234 as DECIMAL(3,2))
9.99
Warnings:
-Error 1264 Out of range value for column 'cast(11.1234 as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(11.1234 as DECIMAL(3,2))' at row 1
select cast(a as DECIMAL(3,2))
from (select 11.1233 as a
UNION select 11.1234
@@ -1460,9 +1460,9 @@ cast(a as DECIMAL(3,2))
9.99
9.99
Warnings:
-Error 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
-Error 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
-Error 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
select cast(a as DECIMAL(3,2)), count(*)
from (select 11.1233 as a
UNION select 11.1234
@@ -1471,10 +1471,10 @@ UNION select 12.1234
cast(a as DECIMAL(3,2)) count(*)
9.99 3
Warnings:
-Error 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
-Error 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
-Error 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
-Error 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
+Warning 1264 Out of range value for column 'cast(a as DECIMAL(3,2))' at row 1
create table t1 (s varchar(100));
insert into t1 values (0.00000000010000000000000000364321973154977415791655470655996396089904010295867919921875);
drop table t1;
@@ -1560,7 +1560,7 @@ select cast(143.481 as decimal(2,1));
cast(143.481 as decimal(2,1))
9.9
Warnings:
-Error 1264 Out of range value for column 'cast(143.481 as decimal(2,1))' at row 1
+Warning 1264 Out of range value for column 'cast(143.481 as decimal(2,1))' at row 1
select cast(-3.4 as decimal(2,1));
cast(-3.4 as decimal(2,1))
-3.4
@@ -1568,12 +1568,12 @@ select cast(99.6 as decimal(2,0));
cast(99.6 as decimal(2,0))
99
Warnings:
-Error 1264 Out of range value for column 'cast(99.6 as decimal(2,0))' at row 1
+Warning 1264 Out of range value for column 'cast(99.6 as decimal(2,0))' at row 1
select cast(-13.4 as decimal(2,1));
cast(-13.4 as decimal(2,1))
-9.9
Warnings:
-Error 1264 Out of range value for column 'cast(-13.4 as decimal(2,1))' at row 1
+Warning 1264 Out of range value for column 'cast(-13.4 as decimal(2,1))' at row 1
select cast(98.6 as decimal(2,0));
cast(98.6 as decimal(2,0))
99
@@ -1674,7 +1674,7 @@ CREATE TABLE t1 SELECT
/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001
AS c1;
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DESC t1;
Field Type Null Key Default Extra
c1 decimal(65,0) NO 0
@@ -1797,7 +1797,7 @@ CREATE TABLE t1 (a DECIMAL(30,30));
INSERT INTO t1 VALUES (0.1),(0.2),(0.3);
CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1;
Warnings:
-Note 1265 Data truncated for column 'c1' at row 3
+Note 1265 Data truncated for column 'c1' at row 4
DESC t2;
Field Type Null Key Default Extra
c1 decimal(32,30) YES NULL
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index c1cd1840df8..da833c79bb7 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -812,16 +812,16 @@ select @@lc_time_names;
@@lc_time_names
en_US
LC_TIME_NAMES: testing locale with the last ID:
-set lc_time_names=108;
+set lc_time_names=109;
select @@lc_time_names;
@@lc_time_names
-zh_HK
+el_GR
LC_TIME_NAMES: testing a number beyond the valid ID range:
-set lc_time_names=109;
-ERROR HY000: Unknown locale: '109'
+set lc_time_names=110;
+ERROR HY000: Unknown locale: '110'
select @@lc_time_names;
@@lc_time_names
-zh_HK
+el_GR
LC_TIME_NAMES: testing that 0 is en_US:
set lc_time_names=0;
select @@lc_time_names;
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index b5e374aaf8c..e23e8930ddb 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -1111,8 +1111,8 @@ insert into v1 values(3);
ERROR HY000: CHECK OPTION failed 'test.v1'
insert ignore into v1 values (2),(3),(0);
Warnings:
-Error 1369 CHECK OPTION failed 'test.v1'
-Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
select * from t1;
a
1
@@ -1125,8 +1125,8 @@ create table t2 (a int);
insert into t2 values (2),(3),(0);
insert ignore into v1 SELECT a from t2;
Warnings:
-Error 1369 CHECK OPTION failed 'test.v1'
-Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
select * from t1 order by a desc;
a
1
@@ -1148,7 +1148,7 @@ a
update v1 set a=a+1;
update ignore v1,t2 set v1.a=v1.a+1 where v1.a=t2.a;
Warnings:
-Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
select * from t1;
a
1
@@ -1182,7 +1182,7 @@ insert into v1 values (1) on duplicate key update a=2;
ERROR HY000: CHECK OPTION failed 'test.v1'
insert ignore into v1 values (1) on duplicate key update a=2;
Warnings:
-Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
select * from t1;
a
1
@@ -1283,7 +1283,7 @@ insert ignore into v1 values (6);
ERROR HY000: CHECK OPTION failed 'test.v1'
insert ignore into v1 values (6),(3);
Warnings:
-Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
select * from t1;
s1
3
@@ -1328,9 +1328,9 @@ delete from t1;
load data infile '../../std_data/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines;
Warnings:
Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3
-Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 4
-Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
select * from t1 order by a,b;
a b
1 row 1
@@ -1354,7 +1354,7 @@ concat('|',a,'|') concat('|',b,'|')
delete from t1;
load data infile '../../std_data/loaddata2.dat' ignore into table v1 fields terminated by ',' enclosed by '''';
Warnings:
-Error 1369 CHECK OPTION failed 'test.v1'
+Warning 1369 CHECK OPTION failed 'test.v1'
Warning 1261 Row 2 doesn't contain data for all columns
select concat('|',a,'|'), concat('|',b,'|') from t1;
concat('|',a,'|') concat('|',b,'|')
diff --git a/mysql-test/std_data/loadxml.dat b/mysql-test/std_data/loadxml.dat
new file mode 100644
index 00000000000..b72fac9da74
--- /dev/null
+++ b/mysql-test/std_data/loadxml.dat
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="test">
+ <table_structure name="t1">
+ <field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
+ <field Field="b" Type="varchar(128)" Null="YES" Key="" Extra="" />
+ <options Name="t1" Engine="MyISAM" Version="10" Row_format="Dynamic" Rows="3" Avg_row_length="20" Data_length="60" Max_data_length="281474976710655" Index_length="1024" Data_free="0" Create_time="2007-02-09 09:08:36" Update_time="2007-02-09 09:08:54" Collation="latin1_swedish_ci" Create_options="" Comment="" />
+ </table_structure>
+ <table_data name="t1">
+ <row>
+ <field name="a">1</field>
+ <field name="b">b1</field>
+ </row>
+ <row>
+ <field name="a">2</field>
+ <field name="b">b2</field>
+ </row>
+ <row>
+ <field name="a">3</field>
+ <field name="b">b3</field>
+ </row>
+ <row>
+ <field name="a">11</field>
+ <field name="b">b11</field>
+ </row>
+
+ <!-- Check field values as tags -->
+ <row>
+ <a>111</a>
+ <b>b111</b>
+ </row>
+
+ <row>
+ <a>112</a>
+ <b>b112 &amp; &lt; &gt; &quot; &apos; &unknown; -- check entities</b>
+ </row>
+
+
+ <!-- Check field values in attributes -->
+ <row a=212 b="b212"></row>
+
+ <!-- Bug#29752 Linefeeds break LOAD XML INFILE -->
+ <!-- Check varios combinations of TAB and NL -->
+
+ <row
+ a=213 b="b213">
+ </row>
+
+ <row
+ a=214
+ b="b214">
+ </row>
+
+ <row a=215 b="b215"></row>
+
+ <row a=216 b="&bb
+b;"></row>
+
+ <!-- End of bug#29752 -->
+
+ </table_data>
+</database>
+</mysqldump>
+
diff --git a/mysql-test/std_data/loadxml2.dat b/mysql-test/std_data/loadxml2.dat
new file mode 100644
index 00000000000..f0d966cf9b6
--- /dev/null
+++ b/mysql-test/std_data/loadxml2.dat
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="test_of_xml_import">
+ <table_structure name="t1">
+ <field Field="id" Type="int(11)" Null="NO" Key="PRI" Extra="" />
+ <field Field="text" Type="text" Null="YES" Key="" Extra="" />
+ <key Table="t1" Non_unique="0" Key_name="PRIMARY" Seq_in_index="1" Column_name="id" Collation="A" Cardinality="1" Null="" Index_type="BTREE" Comment="" Index_Comment="" />
+ <options Name="t1" Engine="MyISAM" Version="10" Row_format="Dynamic" Rows="1" Avg_row_length="32" Data_length="32" Max_data_length="281474976710655" Index_length="2048" Data_free="0" Create_time="2009-06-18 10:02:37" Update_time="2009-06-18 10:02:43" Collation="latin1_swedish_ci" Create_options="" Comment="" />
+ </table_structure>
+ <table_data name="t1">
+ <row>
+ <field name="id">1</field>
+ <field name="text">line1
+line2
+line3</field>
+ </row>
+ </table_data>
+</database>
+</mysqldump>
diff --git a/mysql-test/suite/binlog/r/binlog_index.result b/mysql-test/suite/binlog/r/binlog_index.result
index d49ceb00501..69d877c5adc 100644
--- a/mysql-test/suite/binlog/r/binlog_index.result
+++ b/mysql-test/suite/binlog/r/binlog_index.result
@@ -34,7 +34,7 @@ purge binary logs TO 'master-bin.000002';
ERROR HY000: Fatal error during log purge
show warnings;
Level Code Message
-Error 1377 a problem with deleting master-bin.000001; consider examining correspondence of your binlog index file to the actual binlog files
+Warning 1377 a problem with deleting master-bin.000001; consider examining correspondence of your binlog index file to the actual binlog files
Error 1377 Fatal error during log purge
reset master;
End of tests
diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result
index 4c2c32ad8f1..3047ff54cf0 100644
--- a/mysql-test/suite/binlog/r/binlog_unsafe.result
+++ b/mysql-test/suite/binlog/r/binlog_unsafe.result
@@ -43,12 +43,6 @@ END|
CALL proc();
Warnings:
Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
---- Insert from stored function ----
CREATE FUNCTION func()
RETURNS INT
@@ -67,12 +61,6 @@ func()
0
Warnings:
Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
---- Insert from trigger ----
CREATE TRIGGER trig
BEFORE INSERT ON trigger_table
@@ -90,12 +78,6 @@ INSERT INTO trigger_table VALUES ('bye.');
Warnings:
Note 1592 Statement may not be safe to log in statement format.
Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
---- Insert from prepared statement ----
PREPARE p1 FROM 'INSERT INTO t1 VALUES (@@global.sync_binlog)';
PREPARE p2 FROM 'INSERT INTO t1 VALUES (@@session.insert_id)';
@@ -155,12 +137,6 @@ func5()
0
Warnings:
Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
==== Variables that should *not* be unsafe ====
INSERT INTO t1 VALUES (@@session.pseudo_thread_id);
INSERT INTO t1 VALUES (@@session.pseudo_thread_id);
@@ -215,9 +191,6 @@ END|
CALL p1();
Warnings:
Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
-Note 1592 Statement may not be safe to log in statement format.
DROP PROCEDURE p1;
DROP TABLE t1;
DROP TABLE IF EXISTS t1;
diff --git a/mysql-test/suite/funcs_1/r/innodb_func_view.result b/mysql-test/suite/funcs_1/r/innodb_func_view.result
index 4beb0c8aaf2..172f410b949 100644
--- a/mysql-test/suite/funcs_1/r/innodb_func_view.result
+++ b/mysql-test/suite/funcs_1/r/innodb_func_view.result
@@ -945,8 +945,8 @@ AaBbCcDdEeFfGgHhIiJjÄäÜüÖö 9999999999999999999999999999999999.999999999999
0.000000000000000000000000000000 4
-1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select left('AaBbCcDdEeFfGgHhIiJjÄäÜüÖö',`t1_values`.`my_decimal`) AS `LEFT('AaBbCcDdEeFfGgHhIiJjÄäÜüÖö', my_decimal)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -960,8 +960,8 @@ AaBbCcDdEeFfGgHhIiJjÄäÜüÖö 9999999999999999999999999999999999.999999999999
0.000000000000000000000000000000 4
-1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -2587,9 +2587,9 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
0 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_decimal` as unsigned) AS `CAST(my_decimal AS UNSIGNED INTEGER)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2603,9 +2603,9 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
0 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -2955,8 +2955,8 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
-1 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_decimal` as signed) AS `CAST(my_decimal AS SIGNED INTEGER)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2970,8 +2970,8 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
-1 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -3282,10 +3282,10 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 30
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_double` as decimal(37,2)) AS `CAST(my_double AS DECIMAL(37,2))`,`t1_values`.`my_double` AS `my_double`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3300,10 +3300,10 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 30
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
DROP VIEW v1;
@@ -3372,9 +3372,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 29
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3389,9 +3389,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 29
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
DROP VIEW v1;
@@ -3408,11 +3408,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 28
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ''
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
Warning 1292 Truncated incorrect DECIMAL value: '-1'
Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333'
@@ -3430,11 +3430,11 @@ NULL NULL 1
-1.00 -1
-3333.33 -3333.3333
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ''
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
Warning 1292 Truncated incorrect DECIMAL value: '-1'
Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333'
@@ -3454,9 +3454,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 27
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3471,9 +3471,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 27
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
DROP VIEW v1;
@@ -3490,11 +3490,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 26
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' '
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
@@ -3510,11 +3510,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 26
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' '
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
diff --git a/mysql-test/suite/funcs_1/r/innodb_storedproc_02.result b/mysql-test/suite/funcs_1/r/innodb_storedproc_02.result
index 65fc5b5afc9..3e2d084aa0c 100644
--- a/mysql-test/suite/funcs_1/r/innodb_storedproc_02.result
+++ b/mysql-test/suite/funcs_1/r/innodb_storedproc_02.result
@@ -550,9 +550,6 @@ exit handler 2
exit handler 2
exit handler 1
exit handler 1
-Warnings:
-Note 1051 Unknown table 'tqq'
-Note 1051 Unknown table 'tqq'
create table res_t1(w char unique, x char);
insert into res_t1 values ('a', 'b');
CREATE PROCEDURE h1 ()
diff --git a/mysql-test/suite/funcs_1/r/memory_func_view.result b/mysql-test/suite/funcs_1/r/memory_func_view.result
index 4e48d9412d1..a386272b8ab 100644
--- a/mysql-test/suite/funcs_1/r/memory_func_view.result
+++ b/mysql-test/suite/funcs_1/r/memory_func_view.result
@@ -946,8 +946,8 @@ AaBbCcDdEeFfGgHhIiJjÄäÜüÖö 9999999999999999999999999999999999.999999999999
0.000000000000000000000000000000 4
-1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select left('AaBbCcDdEeFfGgHhIiJjÄäÜüÖö',`t1_values`.`my_decimal`) AS `LEFT('AaBbCcDdEeFfGgHhIiJjÄäÜüÖö', my_decimal)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -961,8 +961,8 @@ AaBbCcDdEeFfGgHhIiJjÄäÜüÖö 9999999999999999999999999999999999.999999999999
0.000000000000000000000000000000 4
-1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -2588,9 +2588,9 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
0 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_decimal` as unsigned) AS `CAST(my_decimal AS UNSIGNED INTEGER)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2604,9 +2604,9 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
0 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -2956,8 +2956,8 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
-1 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_decimal` as signed) AS `CAST(my_decimal AS SIGNED INTEGER)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2971,8 +2971,8 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
-1 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -3283,10 +3283,10 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 30
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_double` as decimal(37,2)) AS `CAST(my_double AS DECIMAL(37,2))`,`t1_values`.`my_double` AS `my_double`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3301,10 +3301,10 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 30
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
DROP VIEW v1;
@@ -3373,9 +3373,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 29
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3390,9 +3390,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 29
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
DROP VIEW v1;
@@ -3409,11 +3409,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 28
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ''
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
Warning 1292 Truncated incorrect DECIMAL value: '-1'
Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333'
@@ -3431,11 +3431,11 @@ NULL NULL 1
-1.00 -1
-3333.33 -3333.3333
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ''
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
Warning 1292 Truncated incorrect DECIMAL value: '-1'
Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333'
@@ -3455,9 +3455,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 27
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3472,9 +3472,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 27
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
DROP VIEW v1;
@@ -3491,11 +3491,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 26
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' '
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
@@ -3511,11 +3511,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 26
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' '
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
diff --git a/mysql-test/suite/funcs_1/r/memory_storedproc_02.result b/mysql-test/suite/funcs_1/r/memory_storedproc_02.result
index 6b474621685..16dde71400e 100644
--- a/mysql-test/suite/funcs_1/r/memory_storedproc_02.result
+++ b/mysql-test/suite/funcs_1/r/memory_storedproc_02.result
@@ -551,9 +551,6 @@ exit handler 2
exit handler 2
exit handler 1
exit handler 1
-Warnings:
-Note 1051 Unknown table 'tqq'
-Note 1051 Unknown table 'tqq'
create table res_t1(w char unique, x char);
insert into res_t1 values ('a', 'b');
CREATE PROCEDURE h1 ()
diff --git a/mysql-test/suite/funcs_1/r/myisam_func_view.result b/mysql-test/suite/funcs_1/r/myisam_func_view.result
index 4e48d9412d1..a386272b8ab 100644
--- a/mysql-test/suite/funcs_1/r/myisam_func_view.result
+++ b/mysql-test/suite/funcs_1/r/myisam_func_view.result
@@ -946,8 +946,8 @@ AaBbCcDdEeFfGgHhIiJjÄäÜüÖö 9999999999999999999999999999999999.999999999999
0.000000000000000000000000000000 4
-1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select left('AaBbCcDdEeFfGgHhIiJjÄäÜüÖö',`t1_values`.`my_decimal`) AS `LEFT('AaBbCcDdEeFfGgHhIiJjÄäÜüÖö', my_decimal)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -961,8 +961,8 @@ AaBbCcDdEeFfGgHhIiJjÄäÜüÖö 9999999999999999999999999999999999.999999999999
0.000000000000000000000000000000 4
-1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -2588,9 +2588,9 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
0 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_decimal` as unsigned) AS `CAST(my_decimal AS UNSIGNED INTEGER)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2604,9 +2604,9 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
0 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -2956,8 +2956,8 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
-1 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_decimal` as signed) AS `CAST(my_decimal AS SIGNED INTEGER)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2971,8 +2971,8 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
-1 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -3283,10 +3283,10 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 30
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_double` as decimal(37,2)) AS `CAST(my_double AS DECIMAL(37,2))`,`t1_values`.`my_double` AS `my_double`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3301,10 +3301,10 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 30
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
DROP VIEW v1;
@@ -3373,9 +3373,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 29
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3390,9 +3390,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 29
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
DROP VIEW v1;
@@ -3409,11 +3409,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 28
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ''
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
Warning 1292 Truncated incorrect DECIMAL value: '-1'
Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333'
@@ -3431,11 +3431,11 @@ NULL NULL 1
-1.00 -1
-3333.33 -3333.3333
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ''
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
Warning 1292 Truncated incorrect DECIMAL value: '-1'
Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333'
@@ -3455,9 +3455,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 27
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3472,9 +3472,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 27
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
DROP VIEW v1;
@@ -3491,11 +3491,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 26
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' '
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
@@ -3511,11 +3511,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 26
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' '
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
diff --git a/mysql-test/suite/funcs_1/r/myisam_storedproc_02.result b/mysql-test/suite/funcs_1/r/myisam_storedproc_02.result
index 6b474621685..16dde71400e 100644
--- a/mysql-test/suite/funcs_1/r/myisam_storedproc_02.result
+++ b/mysql-test/suite/funcs_1/r/myisam_storedproc_02.result
@@ -551,9 +551,6 @@ exit handler 2
exit handler 2
exit handler 1
exit handler 1
-Warnings:
-Note 1051 Unknown table 'tqq'
-Note 1051 Unknown table 'tqq'
create table res_t1(w char unique, x char);
insert into res_t1 values ('a', 'b');
CREATE PROCEDURE h1 ()
diff --git a/mysql-test/suite/funcs_1/r/ndb_func_view.result b/mysql-test/suite/funcs_1/r/ndb_func_view.result
index 4beb0c8aaf2..172f410b949 100644
--- a/mysql-test/suite/funcs_1/r/ndb_func_view.result
+++ b/mysql-test/suite/funcs_1/r/ndb_func_view.result
@@ -945,8 +945,8 @@ AaBbCcDdEeFfGgHhIiJjÄäÜüÖö 9999999999999999999999999999999999.999999999999
0.000000000000000000000000000000 4
-1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select left('AaBbCcDdEeFfGgHhIiJjÄäÜüÖö',`t1_values`.`my_decimal`) AS `LEFT('AaBbCcDdEeFfGgHhIiJjÄäÜüÖö', my_decimal)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -960,8 +960,8 @@ AaBbCcDdEeFfGgHhIiJjÄäÜüÖö 9999999999999999999999999999999999.999999999999
0.000000000000000000000000000000 4
-1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -2587,9 +2587,9 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
0 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_decimal` as unsigned) AS `CAST(my_decimal AS UNSIGNED INTEGER)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2603,9 +2603,9 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
0 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -2955,8 +2955,8 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
-1 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_decimal` as signed) AS `CAST(my_decimal AS SIGNED INTEGER)`,`t1_values`.`my_decimal` AS `my_decimal`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -2970,8 +2970,8 @@ NULL NULL 1
0 0.000000000000000000000000000000 4
-1 -1.000000000000000000000000000000 5
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1292 Truncated incorrect DECIMAL value: ''
DROP VIEW v1;
@@ -3282,10 +3282,10 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 30
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_double` as decimal(37,2)) AS `CAST(my_double AS DECIMAL(37,2))`,`t1_values`.`my_double` AS `my_double`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3300,10 +3300,10 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 30
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
+Warning 1292 Truncated incorrect DECIMAL value: ''
+Warning 1264 Out of range value for column 'CAST(my_double AS DECIMAL(37,2))' at row 1
DROP VIEW v1;
@@ -3372,9 +3372,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 29
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varbinary_1000` as decimal(37,2)) AS `CAST(my_varbinary_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varbinary_1000` AS `my_varbinary_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3389,9 +3389,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 29
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
DROP VIEW v1;
@@ -3408,11 +3408,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 28
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ''
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
Warning 1292 Truncated incorrect DECIMAL value: '-1'
Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333'
@@ -3430,11 +3430,11 @@ NULL NULL 1
-1.00 -1
-3333.33 -3333.3333
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ''
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
Warning 1292 Truncated incorrect DECIMAL value: '-1'
Warning 1292 Truncated incorrect DECIMAL value: '-3333.3333'
@@ -3454,9 +3454,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 27
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(`t1_values`.`my_varchar_1000` as decimal(37,2)) AS `CAST(my_varchar_1000 AS DECIMAL(37,2))`,`t1_values`.`my_varchar_1000` AS `my_varchar_1000`,`t1_values`.`id` AS `id` from `t1_values` latin1 latin1_swedish_ci
@@ -3471,9 +3471,9 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 27
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
DROP VIEW v1;
@@ -3490,11 +3490,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 26
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' '
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
@@ -3510,11 +3510,11 @@ NULL NULL 1
-1.00 -1 5
-3333.33 -3333.3333 26
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' '
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: '<--------30 characters------->'
-Error 1366 Incorrect decimal value: '' for column '' at row -1
+Warning 1366 Incorrect decimal value: '' for column '' at row -1
Warning 1292 Truncated incorrect DECIMAL value: ' ---äÖüß@µ*$-- '
DROP VIEW v1;
diff --git a/mysql-test/suite/funcs_1/r/ndb_storedproc_02.result b/mysql-test/suite/funcs_1/r/ndb_storedproc_02.result
index 65fc5b5afc9..3e2d084aa0c 100644
--- a/mysql-test/suite/funcs_1/r/ndb_storedproc_02.result
+++ b/mysql-test/suite/funcs_1/r/ndb_storedproc_02.result
@@ -550,9 +550,6 @@ exit handler 2
exit handler 2
exit handler 1
exit handler 1
-Warnings:
-Note 1051 Unknown table 'tqq'
-Note 1051 Unknown table 'tqq'
create table res_t1(w char unique, x char);
insert into res_t1 values ('a', 'b');
CREATE PROCEDURE h1 ()
diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result
index 3efb361dc82..ab917fce339 100644
--- a/mysql-test/suite/funcs_1/r/storedproc.result
+++ b/mysql-test/suite/funcs_1/r/storedproc.result
@@ -7128,8 +7128,6 @@ CALL sp1();
x y z
000 000 000
Warnings:
-Warning 1264 Out of range value for column 'x' at row 1
-Warning 1264 Out of range value for column 'y' at row 1
Warning 1264 Out of range value for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7168,8 +7166,6 @@ CALL sp1();
x y z
00000 00000 00000
Warnings:
-Warning 1264 Out of range value for column 'x' at row 1
-Warning 1264 Out of range value for column 'y' at row 1
Warning 1264 Out of range value for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7208,8 +7204,6 @@ CALL sp1();
x y z
00000000 00000000 00000000
Warnings:
-Warning 1264 Out of range value for column 'x' at row 1
-Warning 1264 Out of range value for column 'y' at row 1
Warning 1264 Out of range value for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7248,8 +7242,6 @@ CALL sp1();
x y z
0000000000 0000000000 0000000000
Warnings:
-Warning 1264 Out of range value for column 'x' at row 1
-Warning 1264 Out of range value for column 'y' at row 1
Warning 1264 Out of range value for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7288,8 +7280,6 @@ CALL sp1();
x y z
00000000000000000000 00000000000000000000 00000000000000000000
Warnings:
-Warning 1264 Out of range value for column 'x' at row 1
-Warning 1264 Out of range value for column 'y' at row 1
Warning 1264 Out of range value for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7310,8 +7300,6 @@ CALL sp1();
x y z
-9999999999 -9999999999 -9999999999
Warnings:
-Warning 1264 Out of range value for column 'x' at row 1
-Warning 1264 Out of range value for column 'y' at row 1
Warning 1264 Out of range value for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7323,8 +7311,6 @@ CALL sp1();
x y z
0 0 0
Warnings:
-Note 1265 Data truncated for column 'x' at row 1
-Note 1265 Data truncated for column 'y' at row 1
Note 1265 Data truncated for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7336,8 +7322,6 @@ CALL sp1();
x y z
0000000000 0000000000 0000000000
Warnings:
-Warning 1264 Out of range value for column 'x' at row 1
-Warning 1264 Out of range value for column 'y' at row 1
Warning 1264 Out of range value for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7349,8 +7333,6 @@ CALL sp1();
x y z
0000000000 0000000000 0000000000
Warnings:
-Note 1265 Data truncated for column 'x' at row 1
-Note 1265 Data truncated for column 'y' at row 1
Note 1265 Data truncated for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7362,8 +7344,6 @@ CALL sp1();
x y z
0 0 0
Warnings:
-Note 1265 Data truncated for column 'x' at row 1
-Note 1265 Data truncated for column 'y' at row 1
Note 1265 Data truncated for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7375,8 +7355,6 @@ CALL sp1();
x y z
0 0 0
Warnings:
-Note 1265 Data truncated for column 'x' at row 1
-Note 1265 Data truncated for column 'y' at row 1
Note 1265 Data truncated for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7388,8 +7366,6 @@ CALL sp1();
x y z
0000000000 0000000000 0000000000
Warnings:
-Note 1265 Data truncated for column 'x' at row 1
-Note 1265 Data truncated for column 'y' at row 1
Note 1265 Data truncated for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -7401,8 +7377,6 @@ CALL sp1();
x y z
0000000000 0000000000 0000000000
Warnings:
-Note 1265 Data truncated for column 'x' at row 1
-Note 1265 Data truncated for column 'y' at row 1
Note 1265 Data truncated for column 'z' at row 1
DROP PROCEDURE IF EXISTS sp1;
CREATE PROCEDURE sp1( )
@@ -13782,9 +13756,6 @@ END//
CALL sp1();
x y @x
NULL a 3
-Warnings:
-Warning 1265 Data truncated for column 'y' at row 3
-Warning 1265 Data truncated for column 'y' at row 1
SELECT @v1, @v2;
@v1 @v2
4 a
@@ -15465,14 +15436,6 @@ count done
10 1
Warnings:
Warning 1265 Data truncated for column 'name' at row 1
-Warning 1265 Data truncated for column 'name' at row 2
-Warning 1265 Data truncated for column 'name' at row 3
-Warning 1265 Data truncated for column 'name' at row 4
-Warning 1265 Data truncated for column 'name' at row 5
-Warning 1265 Data truncated for column 'name' at row 6
-Warning 1265 Data truncated for column 'name' at row 7
-Warning 1265 Data truncated for column 'name' at row 8
-Warning 1265 Data truncated for column 'name' at row 9
DROP PROCEDURE sp3;
drop table res_t3_itisalongname_1381742_itsaverylongname_1381742;
@@ -16387,7 +16350,6 @@ fn7(99999999999)
9999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn8;
CREATE FUNCTION fn8( f1 decimal (0) unsigned zerofill) returns decimal (0) unsigned zerofill
@@ -16432,7 +16394,6 @@ fn11(99999999999)
9999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn12;
CREATE FUNCTION fn12( f1 decimal (0, 0) unsigned zerofill) returns decimal (0, 0) unsigned zerofill
@@ -16533,7 +16494,6 @@ SELECT fn21_d_z(1.00e+00);
fn21_d_z(1.00e+00)
0000000000000000000000000000000000000000000000000000000000000010
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn22;
CREATE FUNCTION fn22( f1 decimal unsigned) returns decimal unsigned
@@ -16545,7 +16505,6 @@ SELECT fn22(1.00e+00);
fn22(1.00e+00)
10
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn23;
CREATE FUNCTION fn23( f1 decimal unsigned zerofill) returns decimal unsigned zerofill
@@ -16557,7 +16516,6 @@ SELECT fn23(1.00e+00);
fn23(1.00e+00)
0000000010
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn24;
CREATE FUNCTION fn24( f1 decimal zerofill) returns decimal zerofill
@@ -16903,7 +16861,6 @@ fn56(-8388601)
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn57;
CREATE FUNCTION fn57( f1 numeric) returns numeric
BEGIN
@@ -16936,7 +16893,6 @@ SELECT fn59(9999999999);
fn59(9999999999)
9999999999
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn60;
CREATE FUNCTION fn60( f1 numeric (0) unsigned zerofill) returns numeric (0) unsigned zerofill
@@ -16982,7 +16938,6 @@ SELECT fn63(9999999999);
fn63(9999999999)
9999999999
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn64;
CREATE FUNCTION fn64( f1 numeric (0, 0) unsigned zerofill) returns numeric (0, 0) unsigned zerofill
@@ -17018,8 +16973,6 @@ fn66(-1e+36)
-999999999999999999999999999999989.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn67;
CREATE FUNCTION fn67( f1 numeric (63, 30) unsigned) returns numeric (63, 30) unsigned
@@ -17032,7 +16985,6 @@ fn67(1e+36)
999999999999999999999999999999999.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn68;
CREATE FUNCTION fn68( f1 numeric (63, 30) unsigned zerofill) returns numeric (63, 30) unsigned zerofill
@@ -17045,7 +16997,6 @@ fn68(1e+36)
999999999999999999999999999999999.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn69;
CREATE FUNCTION fn69( f1 numeric (63, 30) zerofill) returns numeric (63, 30) zerofill
@@ -17213,7 +17164,6 @@ fn84(-32601)
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn85;
CREATE FUNCTION fn85( f1 tinyint) returns tinyint
BEGIN
@@ -17253,7 +17203,6 @@ fn88(-101)
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
DROP FUNCTION IF EXISTS fn89;
CREATE FUNCTION fn89( f1 enum('1enum', '2enum')) returns enum('1enum', '2enum')
BEGIN
@@ -17511,7 +17460,6 @@ f1
9999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp8;
CREATE PROCEDURE sp8( f1 decimal (0) unsigned zerofill)
@@ -17556,7 +17504,6 @@ f1
9999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp12;
CREATE PROCEDURE sp12( f1 decimal (0, 0) unsigned zerofill)
@@ -17678,7 +17625,6 @@ CALL sp21(1.00e+00);
f1
0000000000000000000000000000000000000000000000000000000000000010
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp22;
CREATE PROCEDURE sp22( f1 decimal unsigned)
@@ -17690,7 +17636,6 @@ CALL sp22(1.00e+00);
f1
10
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp23;
CREATE PROCEDURE sp23( f1 decimal unsigned zerofill)
@@ -17702,7 +17647,6 @@ CALL sp23(1.00e+00);
f1
0000000010
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp24;
CREATE PROCEDURE sp24( f1 decimal zerofill)
@@ -18048,7 +17992,6 @@ f1
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp57;
CREATE PROCEDURE sp57( f1 numeric)
BEGIN
@@ -18081,7 +18024,6 @@ CALL sp59(9999999999);
f1
9999999999
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp60;
CREATE PROCEDURE sp60( f1 numeric (0) unsigned zerofill)
@@ -18127,7 +18069,6 @@ CALL sp63(9999999999);
f1
9999999999
Warnings:
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp64;
CREATE PROCEDURE sp64( f1 numeric (0, 0) unsigned zerofill)
@@ -18163,16 +18104,12 @@ f1
-999999999999999999999999999999989.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
CALL sp66_n( -1000000000000000000000000000000000000 );
f1
-999999999999999999999999999999989.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp67_nu;
CREATE PROCEDURE sp67_nu( f1 numeric (63, 30) unsigned)
@@ -18185,14 +18122,12 @@ f1
999999999999999999999999999999999.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
CALL sp67_nu( 1000000000000000000000000000000000000 );
f1
999999999999999999999999999999999.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp68_nuz;
CREATE PROCEDURE sp68_nuz( f1 numeric (63, 30) unsigned zerofill)
@@ -18205,14 +18140,12 @@ f1
999999999999999999999999999999999.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
CALL sp68_nuz( 1000000000000000000000000000000000000 );
f1
999999999999999999999999999999999.999999999999999999999999999999
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
-Note 1265 Data truncated for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp69_n_z;
CREATE PROCEDURE sp69_n_z( f1 numeric (63, 30) zerofill)
@@ -18395,7 +18328,6 @@ f1
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp85;
CREATE PROCEDURE sp85( f1 tinyint)
BEGIN
@@ -18435,7 +18367,6 @@ f1
Warnings:
Warning 1264 Out of range value for column 'f1' at row 1
Warning 1264 Out of range value for column 'f1' at row 1
-Warning 1264 Out of range value for column 'f1' at row 1
DROP PROCEDURE IF EXISTS sp89;
CREATE PROCEDURE sp89( f1 enum('1enum', '2enum'))
BEGIN
@@ -22263,9 +22194,9 @@ END latin1 latin1_swedish_ci latin1_swedish_ci
set @@sql_mode='';
CALL sp4();
Level Code Message
-Error 1365 Division by 0
+Warning 1365 Division by 0
Warnings:
-Error 1365 Division by 0
+Warning 1365 Division by 0
DROP PROCEDURE sp4;
set @@sql_mode='';
diff --git a/mysql-test/suite/funcs_1/t/disabled.def b/mysql-test/suite/funcs_1/t/disabled.def
index 3f260ca49ba..23f15b78103 100644
--- a/mysql-test/suite/funcs_1/t/disabled.def
+++ b/mysql-test/suite/funcs_1/t/disabled.def
@@ -10,4 +10,4 @@
#
##############################################################################
-ndb_trig_1011ext: Bug#32656 NDB: Duplicate key error aborts transaction in handler. Doesn't talk back to SQL
+ndb_trig_1011ext: Bug#47564
diff --git a/mysql-test/suite/im/r/im_cmd_line.result b/mysql-test/suite/im/r/im_cmd_line.result
deleted file mode 100644
index a862d465904..00000000000
--- a/mysql-test/suite/im/r/im_cmd_line.result
+++ /dev/null
@@ -1,47 +0,0 @@
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SHOW INSTANCES;
-instance_name state
-mysqld1 XXXXX
-mysqld2 offline
---> Listing users...
-im_admin
-
-==> Adding user 'testuser'...
-
---> IM password file:
-testuser:*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
-im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
---> EOF
-
---> Printing out line for 'testuser'...
-testuser:*0D3CED9BEC10A777AEC23CCC353A8C08A633045E
-
---> Listing users...
-im_admin
-testuser
-
-==> Changing the password of 'testuser'...
-
---> IM password file:
-im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
-testuser:*39C549BDECFBA8AFC3CE6B948C9359A0ECE08DE2
---> EOF
-
---> Printing out line for 'testuser'...
-testuser:*39C549BDECFBA8AFC3CE6B948C9359A0ECE08DE2
-
---> Listing users...
-testuser
-im_admin
-
-==> Dropping user 'testuser'...
-
---> IM password file:
-im_admin:*598D51AD2DFF7792045D6DF3DDF9AA1AF737B295
---> EOF
-
---> Listing users...
-im_admin
-
diff --git a/mysql-test/suite/im/r/im_daemon_life_cycle.result b/mysql-test/suite/im/r/im_daemon_life_cycle.result
deleted file mode 100644
index b3afb15f207..00000000000
--- a/mysql-test/suite/im/r/im_daemon_life_cycle.result
+++ /dev/null
@@ -1,26 +0,0 @@
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SHOW INSTANCES;
-instance_name state
-mysqld1 XXXXX
-mysqld2 offline
-Killing the process...
-Waiting...
-Success: the process was restarted.
-Success: server is ready to accept connection on socket.
-
---------------------------------------------------------------------
--- Test for BUG#12751
---------------------------------------------------------------------
-START INSTANCE mysqld2;
-Success: the process has been started.
-Killing the process...
-Waiting...
-Success: the process was restarted.
-Success: server is ready to accept connection on socket.
-SHOW INSTANCE STATUS mysqld1;
-instance_name state version_number version mysqld_compatible
-mysqld1 STATE VERSION_NUMBER VERSION no
-STOP INSTANCE mysqld2;
-Success: the process has been stopped.
diff --git a/mysql-test/suite/im/r/im_instance_conf.result b/mysql-test/suite/im/r/im_instance_conf.result
deleted file mode 100644
index d04ae0270ab..00000000000
--- a/mysql-test/suite/im/r/im_instance_conf.result
+++ /dev/null
@@ -1,225 +0,0 @@
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SHOW INSTANCES;
-instance_name state
-mysqld1 XXXXX
-mysqld2 offline
---------------------------------------------------------------------
-server_id = 1
-server_id = 2
---------------------------------------------------------------------
-CREATE INSTANCE mysqld3
-server_id = 3,
-socket = "$MYSQL_TMP_DIR/mysqld_3.sock";
-SHOW INSTANCES;
-instance_name state
-mysqld3 offline
-mysqld2 offline
-mysqld1 online
---------------------------------------------------------------------
-server_id = 1
-server_id = 2
-server_id=3
---------------------------------------------------------------------
-CREATE INSTANCE mysqld1;
-ERROR HY000: Instance already exists
-CREATE INSTANCE mysqld2;
-ERROR HY000: Instance already exists
-CREATE INSTANCE mysqld3;
-ERROR HY000: Instance already exists
---------------------------------------------------------------------
-nonguarded
---------------------------------------------------------------------
-CREATE INSTANCE mysqld4
-nonguarded,
-server_id = 4,
-socket = "$MYSQL_TMP_DIR/mysqld_4.sock";
-SHOW INSTANCES;
-instance_name state
-mysqld3 offline
-mysqld4 offline
-mysqld1 online
-mysqld2 offline
---------------------------------------------------------------------
-nonguarded
-nonguarded
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
-CREATE INSTANCE mysqld5
-test-A = 000,
-test-B = test,
-server_id = 5,
-socket = "$MYSQL_TMP_DIR/mysqld_5.sock";
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld4 offline
-mysqld5 offline
-mysqld2 offline
-mysqld3 offline
---------------------------------------------------------------------
-test-A=000
---------------------------------------------------------------------
-test-B=test
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
-CREATE INSTANCE mysqld6
-test-C1 = 10 ,
-test-C2 = 02 ,
-server_id = 6,
-socket = "$MYSQL_TMP_DIR/mysqld_6.sock";
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld2 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
---------------------------------------------------------------------
-test-C1=10
---------------------------------------------------------------------
-test-C2=02
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
-CREATE INSTANCE mysqld7 test-D = test-D-value ;
-ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld2 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
-CREATE INSTANCE mysqld8 test-E 0 ;
-ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld2 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
-CREATE INSTANCE mysqld8 test-F = ;
-ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld2 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
-CREATE INSTANCE mysqld9
-test-1=" hello world ",
-test-2=' ',
-server_id = 9,
-socket = "$MYSQL_TMP_DIR/mysqld_9.sock";
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld2 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
-mysqld9 offline
-CREATE INSTANCE mysqld10
-test-3='\b\babc\sdef',
-server_id = 10,
-socket = "$MYSQL_TMP_DIR/mysqld_10.sock";
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld9 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
-mysqld10 offline
-mysqld2 offline
-CREATE INSTANCE mysqld11
-test-4='abc\tdef',
-test-5='abc\ndef',
-server_id = 11,
-socket = "$MYSQL_TMP_DIR/mysqld_11.sock";
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld11 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
-mysqld10 offline
-mysqld2 offline
-mysqld9 offline
-CREATE INSTANCE mysqld12
-test-6="abc\rdef",
-test-7="abc\\def",
-server_id = 12,
-socket = "$MYSQL_TMP_DIR/mysqld_12.sock";
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld9 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
-mysqld10 offline
-mysqld2 offline
-mysqld12 offline
-mysqld11 offline
-CREATE INSTANCE mysqld13 test-bad=' \ ';
-ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld9 offline
-mysqld5 offline
-mysqld6 offline
-mysqld3 offline
-mysqld4 offline
-mysqld10 offline
-mysqld2 offline
-mysqld12 offline
-mysqld11 offline
---------------------------------------------------------------------
-test-1= hello world
---------------------------------------------------------------------
-test-2=
---------------------------------------------------------------------
-test-3=abc def
---------------------------------------------------------------------
-test-4=abc def
---------------------------------------------------------------------
-test-5=abc
---------------------------------------------------------------------
-test-6=abc def
---------------------------------------------------------------------
-test-7=abc\def
---------------------------------------------------------------------
---------------------------------------------------------------------
-CREATE INSTANCE qqq1;
-ERROR HY000: Malformed instance name.
diff --git a/mysql-test/suite/im/r/im_life_cycle.result b/mysql-test/suite/im/r/im_life_cycle.result
deleted file mode 100644
index dcabc8cf4f3..00000000000
--- a/mysql-test/suite/im/r/im_life_cycle.result
+++ /dev/null
@@ -1,73 +0,0 @@
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SHOW INSTANCES;
-instance_name state
-mysqld1 XXXXX
-mysqld2 offline
-
---------------------------------------------------------------------
--- 1.1.2.
---------------------------------------------------------------------
-START INSTANCE mysqld2;
-Success: the process has been started.
-SHOW VARIABLES LIKE 'port';
-Variable_name Value
-port IM_MYSQLD2_PORT
-
---------------------------------------------------------------------
--- 1.1.3.
---------------------------------------------------------------------
-STOP INSTANCE mysqld2;
-Success: the process has been stopped.
-
---------------------------------------------------------------------
--- 1.1.4.
---------------------------------------------------------------------
-START INSTANCE mysqld3;
-ERROR HY000: Unknown instance name
-START INSTANCE mysqld1;
-ERROR HY000: The instance is already started
-
---------------------------------------------------------------------
--- 1.1.5.
---------------------------------------------------------------------
-STOP INSTANCE mysqld3;
-ERROR HY000: Unknown instance name
-
---------------------------------------------------------------------
--- 1.1.6.
---------------------------------------------------------------------
-Killing the process...
-Waiting...
-Success: the process was restarted.
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld2 offline
-
---------------------------------------------------------------------
--- 1.1.7.
---------------------------------------------------------------------
-START INSTANCE mysqld2;
-Success: the process has been started.
-Killing the process...
-Waiting...
-Success: the process was killed.
-
---------------------------------------------------------------------
--- 1.1.8.
---------------------------------------------------------------------
-SHOW INSTANCE STATUS;
-ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
-
---------------------------------------------------------------------
--- BUG#12813
---------------------------------------------------------------------
-START INSTANCE mysqld1,mysqld2,mysqld3;
-ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
-STOP INSTANCE mysqld1,mysqld2,mysqld3;
-ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
-STOP INSTANCE mysqld2;
-ERROR HY000: Cannot stop instance. Perhaps the instance is not started, or was started manually, so IM cannot find the pidfile.
-End of 5.0 tests
diff --git a/mysql-test/suite/im/r/im_options.result b/mysql-test/suite/im/r/im_options.result
deleted file mode 100644
index 22bd5d5bdf6..00000000000
--- a/mysql-test/suite/im/r/im_options.result
+++ /dev/null
@@ -1,151 +0,0 @@
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SHOW INSTANCES;
-instance_name state
-mysqld1 XXXXX
-mysqld2 offline
-UNSET mysqld1.server_id;
-ERROR HY000: The instance is active. Stop the instance first
-SET mysqld1.server_id = 11;
-ERROR HY000: The instance is active. Stop the instance first
-CREATE INSTANCE mysqld3
-datadir = '/',
-server_id = 3,
-socket = "$MYSQL_TMP_DIR/mysqld_3.sock";
-START INSTANCE mysqld3;
-UNSET mysqld3.server_id;
-ERROR HY000: The instance is active. Stop the instance first
-SET mysqld3.server_id = 11;
-ERROR HY000: The instance is active. Stop the instance first
-STOP INSTANCE mysqld3;
-SHOW INSTANCE STATUS mysqld3;
-instance_name state version_number version mysqld_compatible
-mysqld3 offline VERSION_NUMBER VERSION no
-UNSET mysqld2.server_id;
-UNSET mysqld2.server_id;
-SHOW INSTANCE OPTIONS mysqld2;
-option_name value
-instance_name option_value
-socket option_value
-pid-file option_value
-port option_value
-datadir option_value
-log option_value
-log-error option_value
-log-slow-queries option_value
-language option_value
-character-sets-dir option_value
-basedir option_value
-shutdown-delay option_value
-skip-stack-trace option_value
-loose-skip-innodb option_value
-loose-skip-ndbcluster option_value
-nonguarded option_value
-log-output option_value
-SET mysqld2.server_id = 2;
-SET mysqld2.server_id = 2;
-SHOW INSTANCE OPTIONS mysqld2;
-option_name value
-instance_name option_value
-socket option_value
-pid-file option_value
-port option_value
-datadir option_value
-log option_value
-log-error option_value
-log-slow-queries option_value
-language option_value
-character-sets-dir option_value
-basedir option_value
-shutdown-delay option_value
-skip-stack-trace option_value
-loose-skip-innodb option_value
-loose-skip-ndbcluster option_value
-nonguarded option_value
-log-output option_value
-server_id option_value
-UNSET mysqld2.server_id = 11;
-ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use
-SET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc = 0010, mysqld3.ddd = 0020;
---------------------------------------------------------------------
-aaa
---------------------------------------------------------------------
-bbb
---------------------------------------------------------------------
-ccc=0010
---------------------------------------------------------------------
-ddd=0020
---------------------------------------------------------------------
-UNSET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc, mysqld3.ddd;
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
-SET mysqld2.aaa, mysqld3.bbb, mysqld.ccc = 0010;
-ERROR HY000: Unknown instance name
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
-SET mysqld2.aaa, mysqld3.bbb, mysqld1.ccc = 0010;
-ERROR HY000: The instance is active. Stop the instance first
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
-UNSET mysqld2.server_id, mysqld3.server_id, mysqld.ccc;
-ERROR HY000: Unknown instance name
---------------------------------------------------------------------
-server_id = 1
-server_id=2
-server_id=3
---------------------------------------------------------------------
-UNSET mysqld2.server_id, mysqld3.server_id, mysqld1.ccc;
-ERROR HY000: The instance is active. Stop the instance first
---------------------------------------------------------------------
-server_id = 1
-server_id=2
-server_id=3
---------------------------------------------------------------------
-DROP INSTANCE mysqld3;
-SET mysqld2.server_id=222;
-SET mysqld2.server_id = 222;
-SET mysqld2.server_id = 222 ;
-SET mysqld2 . server_id = 222 ;
-SET mysqld2 . server_id = 222 , mysqld2 . aaa , mysqld2 . bbb ;
---------------------------------------------------------------------
-server_id = 1
-server_id=222
---------------------------------------------------------------------
-aaa
---------------------------------------------------------------------
-bbb
---------------------------------------------------------------------
-UNSET mysqld2 . aaa , mysqld2 . bbb ;
---------------------------------------------------------------------
-server_id = 1
-server_id=222
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
---------------------------------------------------------------------
-server_id = 1
-server_id=222
---------------------------------------------------------------------
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SHOW INSTANCES;
-instance_name state
-mysqld1 online
-mysqld2 offline
-FLUSH INSTANCES;
-ERROR HY000: At least one instance is active. Stop all instances first
-STOP INSTANCE mysqld1;
-SHOW INSTANCES;
-instance_name state
-mysqld1 offline
-mysqld2 offline
-FLUSH INSTANCES;
diff --git a/mysql-test/suite/im/r/im_utils.result b/mysql-test/suite/im/r/im_utils.result
deleted file mode 100644
index 586a5ab6a8d..00000000000
--- a/mysql-test/suite/im/r/im_utils.result
+++ /dev/null
@@ -1,96 +0,0 @@
-SHOW VARIABLES LIKE 'server_id';
-Variable_name Value
-server_id 1
-SHOW INSTANCES;
-instance_name state
-mysqld1 XXXXX
-mysqld2 offline
-SHOW INSTANCE OPTIONS mysqld1;
-option_name value
-instance_name VALUE
-socket VALUE
-pid-file VALUE
-port VALUE
-datadir VALUE
-log VALUE
-log-error VALUE
-log-slow-queries VALUE
-language VALUE
-character-sets-dir VALUE
-basedir VALUE
-server_id VALUE
-shutdown-delay VALUE
-skip-stack-trace VALUE
-loose-skip-innodb VALUE
-loose-skip-ndbcluster VALUE
-log-output VALUE
-SHOW INSTANCE OPTIONS mysqld2;
-option_name value
-instance_name VALUE
-socket VALUE
-pid-file VALUE
-port VALUE
-datadir VALUE
-log VALUE
-log-error VALUE
-log-slow-queries VALUE
-language VALUE
-character-sets-dir VALUE
-basedir VALUE
-server_id VALUE
-shutdown-delay VALUE
-skip-stack-trace VALUE
-loose-skip-innodb VALUE
-loose-skip-ndbcluster VALUE
-nonguarded VALUE
-log-output VALUE
-START INSTANCE mysqld2;
-Success: the process has been started.
-STOP INSTANCE mysqld2;
-Success: the process has been stopped.
-SHOW mysqld1 LOG FILES;
-Logfile Path File size
-ERROR LOG PATH FILE_SIZE
-GENERAL LOG PATH FILE_SIZE
-SLOW LOG PATH FILE_SIZE
-SHOW mysqld2 LOG FILES;
-Logfile Path File size
-ERROR LOG PATH FILE_SIZE
-GENERAL LOG PATH FILE_SIZE
-SLOW LOG PATH FILE_SIZE
-SHOW mysqld1 LOG ERROR 10;
-Log
-LOG_DATA
-SHOW mysqld1 LOG SLOW 10;
-Log
-LOG_DATA
-SHOW mysqld1 LOG GENERAL 10;
-Log
-LOG_DATA
-SHOW mysqld1 LOG ERROR 10, 2;
-Log
-LOG_DATA
-SHOW mysqld1 LOG SLOW 10, 2;
-Log
-LOG_DATA
-SHOW mysqld1 LOG GENERAL 10, 2;
-Log
-LOG_DATA
-SHOW mysqld2 LOG ERROR 10;
-Log
-LOG_DATA
-SHOW mysqld2 LOG SLOW 10;
-Log
-LOG_DATA
-SHOW mysqld2 LOG GENERAL 10;
-Log
-LOG_DATA
-SHOW mysqld2 LOG ERROR 10, 2;
-Log
-LOG_DATA
-SHOW mysqld2 LOG SLOW 10, 2;
-Log
-LOG_DATA
-SHOW mysqld2 LOG GENERAL 10, 2;
-Log
-LOG_DATA
diff --git a/mysql-test/suite/im/t/disabled.def b/mysql-test/suite/im/t/disabled.def
deleted file mode 100644
index 56828810bf1..00000000000
--- a/mysql-test/suite/im/t/disabled.def
+++ /dev/null
@@ -1,20 +0,0 @@
-##############################################################################
-#
-# List the test cases that are to be disabled temporarily.
-#
-# Separate the test case name and the comment with ':'.
-#
-# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment>
-#
-# Do not use any TAB characters for whitespace.
-#
-##############################################################################
-im_options : Bug#20294 2006-07-24 stewart Instance manager test im_options fails randomly
-im_daemon_life_cycle : Bug#20294 2007-05-14 alik Instance manager tests fail randomly
-im_cmd_line : Bug#20294 2007-05-14 alik Instance manager tests fail randomly
-im_utils : Bug#20294 2007-05-30 alik Instance manager tests fail randomly
-im_instance_conf : Bug#20294 2007-05-30 alik Instance manager tests fail randomly
-im_life_cycle : BUG#27851 Instance manager dies on ASSERT in ~Thread_registry() or from not being able to close a mysqld instance.
-im_instance_conf : BUG#28743 Instance manager generates warnings in test suite
-im_utils : BUG#28743 Instance manager generates warnings in test suite
-
diff --git a/mysql-test/suite/im/t/im_check_env.inc b/mysql-test/suite/im/t/im_check_env.inc
deleted file mode 100644
index 883e5d00fe4..00000000000
--- a/mysql-test/suite/im/t/im_check_env.inc
+++ /dev/null
@@ -1,26 +0,0 @@
-# This file is intended to be used in each IM-test. It contains stamements,
-# that ensure that starting conditions (environment) for the IM-test are as
-# expected.
-
-# Check the running instances.
-
---connect (mysql1_con,localhost,root,,mysql,$IM_MYSQLD1_PORT,$IM_MYSQLD1_SOCK)
-
---connection mysql1_con
-
-SHOW VARIABLES LIKE 'server_id';
-
---source include/not_windows.inc
-
---connection default
-
-# Let IM detect that mysqld1 is online. This delay should be longer than
-# monitoring interval.
-
---sleep 2
-
-# Check that IM understands that mysqld1 is online, while mysqld2 is
-# offline.
-
---replace_result starting XXXXX online XXXXX
-SHOW INSTANCES;
diff --git a/mysql-test/suite/im/t/im_cmd_line.imtest b/mysql-test/suite/im/t/im_cmd_line.imtest
deleted file mode 100644
index e8264b5bb8a..00000000000
--- a/mysql-test/suite/im/t/im_cmd_line.imtest
+++ /dev/null
@@ -1,68 +0,0 @@
-###########################################################################
-#
-# Tests for user-management command-line options.
-#
-###########################################################################
-
---source suite/im/t/im_check_env.inc
-
-###########################################################################
-
-# List users so we are sure about starting conditions.
-
---echo --> Listing users...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
---echo
-
-# Add a new user.
-
---echo ==> Adding user 'testuser'...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --add-user --username=testuser --password=abc 2>&1 >/dev/null
---echo
-
---echo --> IM password file:
---exec cat $IM_PASSWORD_PATH
---echo --> EOF
---echo
-
---echo --> Printing out line for 'testuser'...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --print-password-line --username=testuser --password=abc | tail -2 | head -1
---echo
-
---echo --> Listing users...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
---echo
-
-# Edit user's attributes.
-
---echo ==> Changing the password of 'testuser'...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --edit-user --username=testuser --password=xyz 2>&1 >/dev/null
---echo
-
---echo --> IM password file:
---exec cat $IM_PASSWORD_PATH
---echo --> EOF
---echo
-
---echo --> Printing out line for 'testuser'...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --print-password-line --username=testuser --password=xyz | tail -2 | head -1
---echo
-
---echo --> Listing users...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
---echo
-
-# Drop user.
-
---echo ==> Dropping user 'testuser'...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --drop-user --username=testuser 2>&1 >/dev/null
---echo
-
---echo --> IM password file:
---exec cat $IM_PASSWORD_PATH
---echo --> EOF
---echo
-
---echo --> Listing users...
---exec $IM_EXE --defaults-file="$IM_DEFAULTS_PATH" --list-users 2>&1 >/dev/null
---echo
diff --git a/mysql-test/suite/im/t/im_daemon_life_cycle-im.opt b/mysql-test/suite/im/t/im_daemon_life_cycle-im.opt
deleted file mode 100644
index 3a45c7a41f7..00000000000
--- a/mysql-test/suite/im/t/im_daemon_life_cycle-im.opt
+++ /dev/null
@@ -1,3 +0,0 @@
---run-as-service
---log=$MYSQLTEST_VARDIR/log/im.log
---monitoring-interval=1
diff --git a/mysql-test/suite/im/t/im_daemon_life_cycle.imtest b/mysql-test/suite/im/t/im_daemon_life_cycle.imtest
deleted file mode 100644
index c42ab89cc49..00000000000
--- a/mysql-test/suite/im/t/im_daemon_life_cycle.imtest
+++ /dev/null
@@ -1,100 +0,0 @@
-let $UTIL=$MYSQL_TEST_DIR/suite/im/t;
-
-###########################################################################
-#
-# This file contains test for (1.2) test suite.
-#
-# Consult WL#2789 for more information.
-#
-###########################################################################
-
---exec $UTIL/log.sh im_daemon_life_cycle im_daemon_life_cycle.imtest started.
-
-###########################################################################
-
---source suite/im/t/im_check_env.inc
-
-# Turn on reconnect, not on by default anymore.
---enable_reconnect
-
-###########################################################################
-#
-# The main daemon-life-cycle test case -- check that IM-angel will restart
-# IM-main if it got killed:
-# - kill IM-main and check that IM-angel will restart it;
-# - wait for IM-main to start accepting connections before continue test
-# case;
-#
-# NOTE: timeout is 55 seconds. Timeout should be more than shutdown-delay
-# specified for managed MySQL instance. Now shutdown-delay is 10 seconds
-# (set in mysql-test-run.pl). So, 55 seconds should be enough to make 5
-# attempts.
-#
-###########################################################################
-
---exec $UTIL/log.sh im_daemon_life_cycle Main-test: starting...
-
---exec $UTIL/log.sh im_daemon_life_cycle Killing IM-main...
---exec $UTIL/kill_n_check.sh $IM_PATH_PID restarted 55 im_daemon_life_cycle
-
---exec $UTIL/log.sh im_daemon_life_cycle Waiting for IM-main to start accepting connections...
---exec $UTIL/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 55 im_daemon_life_cycle
-
---exec $UTIL/log.sh im_daemon_life_cycle Main-test: done.
-
-###########################################################################
-#
-# BUG#12751: Instance Manager: client hangs
-# - start nonguarded instance (mysqld2);
-# - kill IM-main and get it restarted by IM-angel;
-# - check that guarded instance (mysqld1) is accepting connections.
-# - check that non-guarded instance (mysqld2) were not stopped.
-#
-###########################################################################
-
---echo
---echo --------------------------------------------------------------------
---echo -- Test for BUG#12751
---echo --------------------------------------------------------------------
-
---exec $UTIL/log.sh im_daemon_life_cycle BUG12751: starting...
-
-# 1. Start mysqld;
-
---exec $UTIL/log.sh im_daemon_life_cycle mysqld2: starting...
-START INSTANCE mysqld2;
-
---exec $UTIL/log.sh im_daemon_life_cycle mysqld2: waiting to start...
---exec $UTIL/wait_for_process.sh $IM_MYSQLD2_PATH_PID 55 started im_daemon_life_cycle
-
---exec $UTIL/log.sh im_daemon_life_cycle mysqld2: started.
-
-# 2. Restart IM-main;
-
---exec $UTIL/log.sh im_daemon_life_cycle Killing IM-main...
---exec $UTIL/kill_n_check.sh $IM_PATH_PID restarted 55 im_daemon_life_cycle
-
---exec $UTIL/log.sh im_daemon_life_cycle Waiting for IM-main to start accepting connections...
---exec $UTIL/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 55 im_daemon_life_cycle
-
-# 3. Issue some statement -- connection should be re-established.
-
---exec $UTIL/log.sh im_daemon_life_cycle Checking that IM-main processing commands...
-
---replace_column 2 STATE 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld1;
-
-# 4. Stop mysqld2, because it will not be stopped by IM, as it is nonguarded.
-# So, if it we do not stop it, it will be stopped by mysql-test-run.pl with
-# warning.
-
---exec $UTIL/log.sh im_daemon_life_cycle mysqld2: stopping...
-STOP INSTANCE mysqld2;
-
---exec $UTIL/log.sh im_daemon_life_cycle mysqld2: waiting to stop...
---exec $UTIL/wait_for_process.sh $IM_MYSQLD2_PATH_PID 55 stopped im_daemon_life_cycle
---exec $UTIL/log.sh im_daemon_life_cycle mysqld2: stopped.
-
-###########################################################################
-
---exec $UTIL/log.sh im_daemon_life_cycle BUG12751: done.
diff --git a/mysql-test/suite/im/t/im_instance_conf-im.opt b/mysql-test/suite/im/t/im_instance_conf-im.opt
deleted file mode 100644
index 34b74ce0c95..00000000000
--- a/mysql-test/suite/im/t/im_instance_conf-im.opt
+++ /dev/null
@@ -1 +0,0 @@
---monitoring-interval=1
diff --git a/mysql-test/suite/im/t/im_instance_conf.imtest b/mysql-test/suite/im/t/im_instance_conf.imtest
deleted file mode 100644
index b667df41f98..00000000000
--- a/mysql-test/suite/im/t/im_instance_conf.imtest
+++ /dev/null
@@ -1,244 +0,0 @@
-###########################################################################
-#
-# This test suite checks the following statements:
-# - CREATE INSTANCE <instance_name> [option1[=option1_value], ...];
-# - DROP INSTANCE <instance_name>;
-#
-# For CREATE INSTANCE we check that:
-# - CREATE INSTANCE succeeds for non-existing instance;
-# - CREATE INSTANCE fails for existing instance;
-# - CREATE INSTANCE can get additional options with and w/o values;
-# - CREATE INSTANCE parses options and handles grammar errors correctly.
-# Check that strings with spaces are handled correctly, unknown (for
-# mysqld) options should also be handled;
-# - CREATE INSTANCE updates both config file and internal configuration cache;
-# - CREATE INSTANCE allows to create instances only with properly formed
-# names (mysqld*);
-#
-# For DROP INSTANCE we check that:
-# - DROP INSTANCE succeeds for existing instance;
-# - DROP INSTANCE fails for non-existing instance;
-# - DROP INSTANCE fails for active instance.
-# - DROP INSTANCE updates both config file and internal configuration cache;
-#
-# NOTE: each CREATE INSTANCE statement must specify socket-file-name, otherwise
-# this results of the test can be affected by another running test suite.
-#
-###########################################################################
-
---source suite/im/t/im_check_env.inc
-
-###########################################################################
-#
-# Check starting conditions.
-#
-###########################################################################
-
-# Check that the configuration file contains only instances that we expect.
-
---echo --------------------------------------------------------------------
---exec grep '^server_id[^a-zA-Z0-9_\-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
-
-###########################################################################
-#
-# CREATE INSTANCE tests.
-#
-###########################################################################
-
-# Check that CREATE INSTANCE succeeds for non-existing instance and also check
-# that both config file and internal configuration cache have been updated.
-
-CREATE INSTANCE mysqld3
- server_id = 3,
- socket = "$MYSQL_TMP_DIR/mysqld_3.sock";
-
-SHOW INSTANCES;
-
---echo --------------------------------------------------------------------
---exec grep '^server_id[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
-
-# Check that CREATE INSTANCE fails for existing instance. Let's all three
-# existing instances (running one, stopped one and just created one). Just in
-# case...
-
---error 3012 # ER_CREATE_EXISTING_INSTANCE
-CREATE INSTANCE mysqld1;
-
---error 3012 # ER_CREATE_EXISTING_INSTANCE
-CREATE INSTANCE mysqld2;
-
---error 3012 # ER_CREATE_EXISTING_INSTANCE
-CREATE INSTANCE mysqld3;
-
-# Check that CREATE INSTANCE can get additional options with and w/o values.
-# Ensure that config file is updated properly.
-
-# - without values;
-
---echo --------------------------------------------------------------------
---exec grep "^nonguarded\$" $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
-
-CREATE INSTANCE mysqld4
- nonguarded,
- server_id = 4,
- socket = "$MYSQL_TMP_DIR/mysqld_4.sock";
-
-SHOW INSTANCES;
-
---echo --------------------------------------------------------------------
---exec grep "^nonguarded\$" $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
-
-# - with value;
-
---echo --------------------------------------------------------------------
---exec grep '^test-A[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-B[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
-CREATE INSTANCE mysqld5
- test-A = 000,
- test-B = test,
- server_id = 5,
- socket = "$MYSQL_TMP_DIR/mysqld_5.sock";
-
-SHOW INSTANCES;
-
---echo --------------------------------------------------------------------
---exec grep '^test-A[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-B[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
-
-# Check that CREATE INSTANCE parses options and handles grammar errors
-# correctly. Check that strings with spaces are handled correctly,
-# unknown (for mysqld) options should also be handled.
-
-# - check handling of extra spaces;
-
---echo --------------------------------------------------------------------
---exec grep '^test-C1[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-C2[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
-CREATE INSTANCE mysqld6
- test-C1 = 10 ,
- test-C2 = 02 ,
- server_id = 6,
- socket = "$MYSQL_TMP_DIR/mysqld_6.sock";
-
-SHOW INSTANCES;
-
---echo --------------------------------------------------------------------
---exec grep '^test-C1[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-C2[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
-
-# - check handling of grammar error;
-
---echo --------------------------------------------------------------------
---exec grep '^test-D[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-E[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
---error ER_SYNTAX_ERROR
-CREATE INSTANCE mysqld7 test-D = test-D-value ;
-SHOW INSTANCES;
-
---error ER_SYNTAX_ERROR
-CREATE INSTANCE mysqld8 test-E 0 ;
-SHOW INSTANCES;
-
---error ER_SYNTAX_ERROR
-CREATE INSTANCE mysqld8 test-F = ;
-SHOW INSTANCES;
-
---echo --------------------------------------------------------------------
---exec grep '^test-D[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-E[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
-# - check parsing of string option values
-
---echo --------------------------------------------------------------------
---exec grep '^test-1[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-2[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-3[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-4[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-5[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-6[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^test-7[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
-CREATE INSTANCE mysqld9
- test-1=" hello world ",
- test-2=' ',
- server_id = 9,
- socket = "$MYSQL_TMP_DIR/mysqld_9.sock";
-SHOW INSTANCES;
-
-CREATE INSTANCE mysqld10
- test-3='\b\babc\sdef',
- server_id = 10,
- socket = "$MYSQL_TMP_DIR/mysqld_10.sock";
-# test-3='abc def'
-SHOW INSTANCES;
-
-CREATE INSTANCE mysqld11
- test-4='abc\tdef',
- test-5='abc\ndef',
- server_id = 11,
- socket = "$MYSQL_TMP_DIR/mysqld_11.sock";
-SHOW INSTANCES;
-
-CREATE INSTANCE mysqld12
- test-6="abc\rdef",
- test-7="abc\\def",
- server_id = 12,
- socket = "$MYSQL_TMP_DIR/mysqld_12.sock";
-# test-6=abc
-SHOW INSTANCES;
-
---error ER_SYNTAX_ERROR
-CREATE INSTANCE mysqld13 test-bad=' \ ';
-SHOW INSTANCES;
-
---echo --------------------------------------------------------------------
---exec grep '^test-1[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-2[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-3[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-4[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-5[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-6[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-7[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
---exec grep '^test-bad' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
-
-# Check that CREATE INSTANCE allows to create instances only with properly
-# formed names (mysqld*).
-
---error 3014 # ER_MALFORMED_INSTANCE_NAME
-CREATE INSTANCE qqq1;
-
diff --git a/mysql-test/suite/im/t/im_life_cycle-im.opt b/mysql-test/suite/im/t/im_life_cycle-im.opt
deleted file mode 100644
index 34b74ce0c95..00000000000
--- a/mysql-test/suite/im/t/im_life_cycle-im.opt
+++ /dev/null
@@ -1 +0,0 @@
---monitoring-interval=1
diff --git a/mysql-test/suite/im/t/im_life_cycle.imtest b/mysql-test/suite/im/t/im_life_cycle.imtest
deleted file mode 100644
index 31f63d82505..00000000000
--- a/mysql-test/suite/im/t/im_life_cycle.imtest
+++ /dev/null
@@ -1,205 +0,0 @@
-let $UTIL=$MYSQL_TEST_DIR/suite/im/t;
-
-###########################################################################
-#
-# This file contains test for (1.1) test suite.
-#
-# Consult WL#2789 for more information.
-#
-###########################################################################
-
---source suite/im/t/im_check_env.inc
-
-###########################################################################
-#
-# 1.1.2. Check 'START INSTANCE' command:
-# - start the second instance;
-# - check that it is reported as online;
-# - execute some SQL-statement on mysqld2 to ensure that it is really up and
-# running;
-#
-###########################################################################
-
---echo
---echo --------------------------------------------------------------------
---echo -- 1.1.2.
---echo --------------------------------------------------------------------
-
-START INSTANCE mysqld2;
-# FIXME: START INSTANCE should be synchronous.
---exec $UTIL/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_life_cycle
-
-# FIXME: Result of SHOW INSTANCES here is not deterministic unless START
-# INSTANCE is synchronous. Even waiting for mysqld to start by looking at
-# its pid file is not enough, because it is unknown when IM detects that
-# mysqld has started.
-# SHOW INSTANCES;
-
---connect (mysql_con,localhost,root,,mysql,$IM_MYSQLD2_PORT,$IM_MYSQLD2_SOCK)
---connection mysql_con
-
---replace_result $IM_MYSQLD2_PORT IM_MYSQLD2_PORT
-SHOW VARIABLES LIKE 'port';
-
---connection default
---disconnect mysql_con
-
-###########################################################################
-#
-# 1.1.3. Check 'STOP INSTANCE' command:
-# - stop the second instance;
-# - check that it is reported as offline;
-# - TODO: try to execute some SQL-statement to ensure that it is really down;
-#
-###########################################################################
-
---echo
---echo --------------------------------------------------------------------
---echo -- 1.1.3.
---echo --------------------------------------------------------------------
-
-STOP INSTANCE mysqld2;
-# FIXME: STOP INSTANCE should be synchronous.
---exec $UTIL/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped im_life_cycle
-
-# FIXME: Result of SHOW INSTANCES here is not deterministic unless START
-# INSTANCE is synchronous. Even waiting for mysqld to start by looking at
-# its pid file is not enough, because it is unknown when IM detects that
-# mysqld has started.
-# SHOW INSTANCES;
-
-###########################################################################
-#
-# 1.1.4. Check that Instance Manager reports correct errors for 'START
-# INSTANCE' command:
-# - if the client tries to start unregistered instance;
-# - if the client tries to start already started instance;
-# - if the client submits invalid arguments;
-#
-###########################################################################
-
---echo
---echo --------------------------------------------------------------------
---echo -- 1.1.4.
---echo --------------------------------------------------------------------
-
---error 3000 # ER_BAD_INSTANCE_NAME
-START INSTANCE mysqld3;
-
---error 3002 # ER_INSTANCE_ALREADY_STARTED
-START INSTANCE mysqld1;
-
-###########################################################################
-#
-# 1.1.5. Check that Instance Manager reports correct errors for
-# 'STOP INSTANCE' command:
-# - if the client tries to start unregistered instance;
-# - if the client tries to start already stopped instance;
-# - if the client submits invalid arguments;
-#
-###########################################################################
-
---echo
---echo --------------------------------------------------------------------
---echo -- 1.1.5.
---echo --------------------------------------------------------------------
-
---error 3000 # ER_BAD_INSTANCE_NAME
-STOP INSTANCE mysqld3;
-
-# TODO: IM should be fixed.
-# BUG#12673: Instance Manager allows to stop the instance many times
-# --error 3002 # ER_INSTANCE_ALREADY_STARTED
-# STOP INSTANCE mysqld2;
-
-###########################################################################
-#
-# 1.1.6. Check that Instance Manager is able to restart guarded instances.
-#
-###########################################################################
-
---echo
---echo --------------------------------------------------------------------
---echo -- 1.1.6.
---echo --------------------------------------------------------------------
-
---exec $UTIL/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted 30 im_life_cycle
-
-# Give some time to IM to detect that mysqld was restarted. It should be
-# longer than monitoring interval.
-
---sleep 3
-
-SHOW INSTANCES;
-
-###########################################################################
-#
-# 1.1.7. Check that Instance Manager does not restart non-guarded instance.
-#
-###########################################################################
-
---echo
---echo --------------------------------------------------------------------
---echo -- 1.1.7.
---echo --------------------------------------------------------------------
-
-START INSTANCE mysqld2;
-# FIXME: START INSTANCE should be synchronous.
---exec $UTIL/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_life_cycle
-
-# FIXME: Result of SHOW INSTANCES here is not deterministic unless START
-# INSTANCE is synchronous. Even waiting for mysqld to start by looking at
-# its pid file is not enough, because it is unknown when IM detects that
-# mysqld has started.
-# SHOW INSTANCES;
-
---exec $UTIL/kill_n_check.sh $IM_MYSQLD2_PATH_PID killed 10 im_life_cycle
-
-# FIXME: Result of SHOW INSTANCES here is not deterministic unless START
-# INSTANCE is synchronous. Even waiting for mysqld to start by looking at
-# its pid file is not enough, because it is unknown when IM detects that
-# mysqld has started.
-# SHOW INSTANCES;
-
-###########################################################################
-#
-# 1.1.8. Check that Instance Manager returns an error on
-# incomplete SHOW INSTANCE STATUS command.
-#
-###########################################################################
-
---echo
---echo --------------------------------------------------------------------
---echo -- 1.1.8.
---echo --------------------------------------------------------------------
-
---error ER_SYNTAX_ERROR
-SHOW INSTANCE STATUS;
-
-#
-# Tests for bug fixes
-#
-
-#
-# Bug #12813 Instance Manager: START/STOP INSTANCE commands accept
-# a list as argument.
-#
-
---echo
---echo --------------------------------------------------------------------
---echo -- BUG#12813
---echo --------------------------------------------------------------------
-
---error ER_SYNTAX_ERROR
-START INSTANCE mysqld1,mysqld2,mysqld3;
-
---error ER_SYNTAX_ERROR
-STOP INSTANCE mysqld1,mysqld2,mysqld3;
-
-#
-# Bug #12673: Instance Manager: allows to stop the instance many times
-#
---error 3001
-STOP INSTANCE mysqld2;
-
---echo End of 5.0 tests
diff --git a/mysql-test/suite/im/t/im_options-im.opt b/mysql-test/suite/im/t/im_options-im.opt
deleted file mode 100644
index 34b74ce0c95..00000000000
--- a/mysql-test/suite/im/t/im_options-im.opt
+++ /dev/null
@@ -1 +0,0 @@
---monitoring-interval=1
diff --git a/mysql-test/suite/im/t/im_options.imtest b/mysql-test/suite/im/t/im_options.imtest
deleted file mode 100644
index d251b97d8e7..00000000000
--- a/mysql-test/suite/im/t/im_options.imtest
+++ /dev/null
@@ -1,248 +0,0 @@
-###########################################################################
-#
-# This test suite checks the following statements:
-# - SET <instance id>.<option name> = <option value>;
-# - UNSET <instance id>.<option name> = <option value>;
-# - FLUSH INSTANCES;
-#
-# For SET/UNSET we check that:
-# - SET ignores spaces correctly;
-# - UNSET does not allow option-value part (= <option value>);
-# - SET/UNSET can be applied several times w/o error;
-# - SET/UNSET is allowed only for stopped instances;
-# - SET/UNSET updates both the configuration cache in IM and
-# the configuration file;
-#
-# For FLUSH INSTANCES we check that:
-# - FLUSH INSTANCES is allowed only when all instances are stopped;
-#
-# According to the IM implementation details, we should play at least with the
-# following options:
-# - server_id
-# - port
-# - nonguarded
-#
-# Let's test SET statement on the option 'server_id'. It's expected that
-# originally the instances have the following server ids and states:
-# - mysqld1: server_id: 1; running (online)
-# - mysqld2: server_id: 2; stopped (offline)
-#
-# NOTE: each CREATE INSTANCE statement must specify socket-file-name, otherwise
-# this results of the test can be affected by another running test suite.
-#
-###########################################################################
-
---source suite/im/t/im_check_env.inc
-
-###########################################################################
-#
-# Check that SET/UNSET is allowed only for stopped instances.
-#
-###########################################################################
-
-# - check that SET/UNSET is denied for running instances;
-
---error 3015 # ER_INSTANCE_IS_ACTIVE
-UNSET mysqld1.server_id;
-
---error 3015 # ER_INSTANCE_IS_ACTIVE
-SET mysqld1.server_id = 11;
-
-# - check that SET/UNSET is denied for active instances:
-# - create dummy misconfigured instance;
-# - start it;
-# - try to set/unset options;
-
-CREATE INSTANCE mysqld3
- datadir = '/',
- server_id = 3,
- socket = "$MYSQL_TMP_DIR/mysqld_3.sock";
-START INSTANCE mysqld3;
-
-# FIXME: START INSTANCE should be synchronous.
---sleep 3
-# should be longer than monitoring interval and enough to start instance.
-
-# NOTE: We can not analyze state of the instance here -- it can be Failed or
-# Starting because Instance Manager is trying to start the misconfigured
-# instance several times.
-
---error 3015 # ER_INSTANCE_IS_ACTIVE
-UNSET mysqld3.server_id;
-
---error 3015 # ER_INSTANCE_IS_ACTIVE
-SET mysqld3.server_id = 11;
-
-STOP INSTANCE mysqld3;
-
-# FIXME: STOP INSTANCE should be synchronous.
---sleep 3
-# should be longer than monitoring interval and enough to stop instance.
-
---replace_column 3 VERSION_NUMBER 4 VERSION
-SHOW INSTANCE STATUS mysqld3;
-
-# - check that SET/UNSET succeed for stopped instances;
-# - check that SET/UNSET can be applied multiple times;
-
-UNSET mysqld2.server_id;
-UNSET mysqld2.server_id;
-
---replace_column 2 option_value
-SHOW INSTANCE OPTIONS mysqld2;
-
-SET mysqld2.server_id = 2;
-SET mysqld2.server_id = 2;
-
---replace_column 2 option_value
-SHOW INSTANCE OPTIONS mysqld2;
-
-# - check that UNSET does not allow option-value part (= <option value>);
-
---error ER_SYNTAX_ERROR
-UNSET mysqld2.server_id = 11;
-
-# - check that SET/UNSET working properly with multiple options;
-
-SET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc = 0010, mysqld3.ddd = 0020;
-
---echo --------------------------------------------------------------------
---exec grep "^aaa\$" $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
---exec grep "^bbb\$" $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
---exec grep '^ccc[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
---exec grep '^ddd[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
-
-UNSET mysqld2.aaa, mysqld3.bbb, mysqld2.ccc, mysqld3.ddd;
-
---echo --------------------------------------------------------------------
---exec grep "^aaa\$" $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep "^bbb\$" $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^ccc[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^ddd[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
-# - check that if some instance name is invalid or the active is active,
-# whole SET-statement will not be executed;
-
---error 3000 # ER_BAD_INSTANCE_NAME
-SET mysqld2.aaa, mysqld3.bbb, mysqld.ccc = 0010;
-
---echo --------------------------------------------------------------------
---exec grep "^aaa\$" $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep "^bbb\$" $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^ccc[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
---error 3015 # ER_INSTANCE_IS_ACTIVE
-SET mysqld2.aaa, mysqld3.bbb, mysqld1.ccc = 0010;
-
---echo --------------------------------------------------------------------
---exec grep "^aaa\$" $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep "^bbb\$" $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep '^ccc[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
-# - check that if some instance name is invalid or the active is active,
-# whole UNSET-statement will not be executed;
-
---error 3000 # ER_BAD_INSTANCE_NAME
-UNSET mysqld2.server_id, mysqld3.server_id, mysqld.ccc;
-
---echo --------------------------------------------------------------------
---exec grep '^server_id[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
-
---error 3015 # ER_INSTANCE_IS_ACTIVE
-UNSET mysqld2.server_id, mysqld3.server_id, mysqld1.ccc;
-
---echo --------------------------------------------------------------------
---exec grep '^server_id[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf;
---echo --------------------------------------------------------------------
-
-DROP INSTANCE mysqld3;
-
-# - check that spaces are handled correctly;
-
-SET mysqld2.server_id=222;
-SET mysqld2.server_id = 222;
-SET mysqld2.server_id = 222 ;
-SET mysqld2 . server_id = 222 ;
-SET mysqld2 . server_id = 222 , mysqld2 . aaa , mysqld2 . bbb ;
-
---echo --------------------------------------------------------------------
---exec grep '^server_id[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
---exec grep "^aaa\$" $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
---exec grep "^bbb\$" $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
-
-UNSET mysqld2 . aaa , mysqld2 . bbb ;
-
---echo --------------------------------------------------------------------
---exec grep '^server_id[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
---exec grep "^aaa\$" $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
---exec grep "^bbb\$" $MYSQLTEST_VARDIR/im.cnf || true;
---echo --------------------------------------------------------------------
-
-###########################################################################
-#
-# Check that SET/UNSET updates both the configuration cache in IM and
-# the configuration file.
-#
-###########################################################################
-
-# - check that the configuration file has been updated (i.e. contains
-# server_id=SERVER_ID for mysqld2);
-
---echo --------------------------------------------------------------------
---exec grep '^server_id[^a-zA-Z0-9_-]' $MYSQLTEST_VARDIR/im.cnf ;
---echo --------------------------------------------------------------------
-
-# - (for mysqld1) check that the running instance has not been affected:
-# connect to the instance and check that 'SHOW VARIABLES LIKE 'server_id''
-# returns zero;
-
---connection mysql1_con
-
-SHOW VARIABLES LIKE 'server_id';
-
---connection default
-
-# - check that internal cache of Instance Manager has been affected;
-# TODO: we should check only server_id option here.
-
-# SHOW INSTANCE OPTIONS mysqld2;
-
-###########################################################################
-#
-# Check that FLUSH INSTANCES is allowed only when all instances are stopped.
-#
-###########################################################################
-
-SHOW INSTANCES;
-
---error 3016 # ER_THERE_IS_ACTIVE_INSTACE
-FLUSH INSTANCES;
-
-STOP INSTANCE mysqld1;
-# FIXME: STOP INSTANCE should be synchronous.
---sleep 3
-# should be longer than monitoring interval and enough to stop instance.
-
-SHOW INSTANCES;
-
-FLUSH INSTANCES;
diff --git a/mysql-test/suite/im/t/im_utils-im.opt b/mysql-test/suite/im/t/im_utils-im.opt
deleted file mode 100644
index 34b74ce0c95..00000000000
--- a/mysql-test/suite/im/t/im_utils-im.opt
+++ /dev/null
@@ -1 +0,0 @@
---monitoring-interval=1
diff --git a/mysql-test/suite/im/t/im_utils.imtest b/mysql-test/suite/im/t/im_utils.imtest
deleted file mode 100644
index b935634e96c..00000000000
--- a/mysql-test/suite/im/t/im_utils.imtest
+++ /dev/null
@@ -1,107 +0,0 @@
-###########################################################################
-#
-# This file contains test for (2) test suite.
-#
-# Consult WL#2789 for more information.
-#
-###########################################################################
-
---source suite/im/t/im_check_env.inc
-
-let $UTIL=$MYSQL_TEST_DIR/suite/im/t;
-
-###########################################################################
-
-#
-# Check 'SHOW INSTANCE OPTIONS' command.
-#
-# Since configuration of an mysqld-instance contains directories, we should
-# completely ignore the second column (values) in order to make the test
-# case produce the same results on different installations;
-# TODO: ignore values of only directory-specific options.
-#
-
---replace_column 2 VALUE
-SHOW INSTANCE OPTIONS mysqld1;
-
---replace_column 2 VALUE
-SHOW INSTANCE OPTIONS mysqld2;
-
-#
-# Before checking log files, we should start the second instance (mysqld2) to
-# give it a chance to create log files.
-#
-
-START INSTANCE mysqld2;
---exec $UTIL/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_utils
-
-STOP INSTANCE mysqld2;
---exec $UTIL/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped im_utils
-
-#
-# Check 'SHOW LOG FILES' command:
-# - check that log files of both offline and online instances are accessible;
-# - since placement of the log files is installation-specific, we should
-# ignore it in comparisson;
-# - also, we should ignore log file size, since it may depend on the version
-# being tested;
-#
-
---replace_column 2 PATH 3 FILE_SIZE
-SHOW mysqld1 LOG FILES;
-
---replace_column 2 PATH 3 FILE_SIZE
-SHOW mysqld2 LOG FILES;
-
-#
-# Check 'SHOW LOG' command:
-# - check that all three kinds of logs are available for both offline and
-# online instances;
-# - we should ignore the value, because it is very specific and depends on
-# many factors; we only check that Instance Manager is able to provide log
-# files.
-#
-
-# mysqld1 (online) w/o the optional argument.
-
---replace_column 1 LOG_DATA
-SHOW mysqld1 LOG ERROR 10;
-
---replace_column 1 LOG_DATA
-SHOW mysqld1 LOG SLOW 10;
-
---replace_column 1 LOG_DATA
-SHOW mysqld1 LOG GENERAL 10;
-
-# mysqld1 (online) with the optional argument.
-
---replace_column 1 LOG_DATA
-SHOW mysqld1 LOG ERROR 10, 2;
-
---replace_column 1 LOG_DATA
-SHOW mysqld1 LOG SLOW 10, 2;
-
---replace_column 1 LOG_DATA
-SHOW mysqld1 LOG GENERAL 10, 2;
-
-# mysqld2 (offline) w/o the optional argument.
-
---replace_column 1 LOG_DATA
-SHOW mysqld2 LOG ERROR 10;
-
---replace_column 1 LOG_DATA
-SHOW mysqld2 LOG SLOW 10;
-
---replace_column 1 LOG_DATA
-SHOW mysqld2 LOG GENERAL 10;
-
-# mysqld2 (offline) with the optional argument.
-
---replace_column 1 LOG_DATA
-SHOW mysqld2 LOG ERROR 10, 2;
-
---replace_column 1 LOG_DATA
-SHOW mysqld2 LOG SLOW 10, 2;
-
---replace_column 1 LOG_DATA
-SHOW mysqld2 LOG GENERAL 10, 2;
diff --git a/mysql-test/suite/im/t/kill_n_check.sh b/mysql-test/suite/im/t/kill_n_check.sh
deleted file mode 100755
index 6f2a0825dcd..00000000000
--- a/mysql-test/suite/im/t/kill_n_check.sh
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/bin/sh
-
-###########################################################################
-
-# NOTE: this script returns 0 (success) even in case of failure (except for
-# usage-error). This is because this script is executed under
-# mysql-test-run[.pl] and it's better to examine particular problem in log
-# file, than just having said that the test case has failed.
-
-###########################################################################
-
-basename=`basename "$0"`
-dirname=`dirname "$0"`
-
-###########################################################################
-
-. "$dirname/utils.sh"
-
-###########################################################################
-
-check_restart()
-{
- if [ ! -r "$pid_path" ]; then
- log_debug "No '$pid_path' found."
- user_msg='the process was killed'
- return 1
- fi
-
- new_pid=`cat "$pid_path" 2>/dev/null`
- err_code=$?
-
- log_debug "err_code: $err_code; original_pid: $original_pid; new_pid: $new_pid."
-
- if [ $err_code -eq 0 -a "$original_pid" = "$new_pid" ]; then
- log_debug "The process was not restarted."
- user_msg='the process was not restarted'
- return 1
- fi
-
- log_debug "The process was restarted."
- user_msg='the process was restarted'
- return 0
-}
-
-###########################################################################
-
-if [ $# -ne 4 ]; then
- echo "Usage: $basename <pid file path> killed|restarted <timeout> <test id>"
- exit 1
-fi
-
-pid_path="$1"
-expected_result="$2"
-total_timeout="$3"
-test_id="$4"
-log_file="$MYSQLTEST_VARDIR/log/$test_id.script.log"
-
-log_debug "-- $basename: starting --"
-log_debug "pid_path: '$pid_path'"
-log_debug "expected_result: '$expected_result'"
-log_debug "total_timeout: '$total_timeout'"
-log_debug "test_id: '$test_id'"
-log_debug "log_file: '$log_file'"
-
-###########################################################################
-
-if [ "$expected_result" != 'killed' -a \
- "$expected_result" != 'restarted' ]; then
- log_error "Invalid second argument ($expected_result): 'killed' or 'restarted' expected."
- quit 0
-fi
-
-if [ -z "$pid_path" ]; then
- log_error "Invalid PID path ($pid_path)."
- quit 0
-fi
-
-if [ ! -r "$pid_path" ]; then
- log_error "PID file ($pid_path) does not exist."
- quit 0
-fi
-
-if [ -z "$total_timeout" ]; then
- log_error "Timeout is not specified."
- quit 0
-fi
-
-###########################################################################
-
-original_pid=`cat "$pid_path"`
-log_debug "original_pid: $original_pid."
-
-log_info "Killing the process..."
-
-kill -9 $original_pid
-
-###########################################################################
-
-log_info "Waiting..."
-
-if [ "$expected_result" = "restarted" ]; then
-
- # Wait for the process to restart.
-
- cur_attempt=1
-
- while true; do
-
- log_debug "cur_attempt: $cur_attempt."
-
- if check_restart; then
- log_info "Success: $user_msg."
- quit 0
- fi
-
- [ $cur_attempt -ge $total_timeout ] && break
-
- log_debug "Sleeping for 1 second..."
- sleep 1
-
- cur_attempt=`expr $cur_attempt + 1`
-
- done
-
- log_error "$user_msg."
- quit 0
-
-else # $expected_result == killed
-
- # Here we have to sleep for some long time to ensure that the process will
- # not be restarted.
-
- log_debug "Sleeping for $total_timeout seconds..."
- sleep $total_timeout
-
- new_pid=`cat "$pid_path" 2>/dev/null`
- log_debug "new_pid: $new_pid."
-
- if [ "$new_pid" -a "$new_pid" -ne "$original_pid" ]; then
- log_error "The process was restarted."
- else
- log_info "Success: the process was killed."
- fi
-
- quit 0
-
-fi
diff --git a/mysql-test/suite/im/t/log.sh b/mysql-test/suite/im/t/log.sh
deleted file mode 100755
index 33ef6d6701f..00000000000
--- a/mysql-test/suite/im/t/log.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-###########################################################################
-
-basename=`basename "$0"`
-dirname=`dirname "$0"`
-
-###########################################################################
-
-. "$dirname/utils.sh"
-
-###########################################################################
-
-if [ $# -lt 2 ]; then
- echo "Usage: $basename <test id> log message ..."
- exit 1
-fi
-
-test_id="$1"
-log_file="$MYSQLTEST_VARDIR/log/$test_id.script.log"
-
-shift
-
-log_debug "$*"
diff --git a/mysql-test/suite/im/t/utils.sh b/mysql-test/suite/im/t/utils.sh
deleted file mode 100644
index b3f4744947d..00000000000
--- a/mysql-test/suite/im/t/utils.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-###########################################################################
-#
-# This file provides utility functions and is included by other scripts.
-#
-# The following global variables must be set before calling functions from this
-# file:
-# - basename -- base name of the calling script (main application);
-# - log_file -- where to store log records;
-#
-###########################################################################
-
-log()
-{
- [ -z "$log_file" ] && return;
-
- log_level="$1"
- log_msg="$2"
- ts=`date`
-
- echo "[$ts] [$basename] [$log_level] $log_msg" >> "$log_file";
-}
-
-###########################################################################
-
-log_debug()
-{
- log 'DEBUG' "$1"
-}
-
-###########################################################################
-
-log_info()
-{
- log 'INFO' "$1"
- echo "$1"
-}
-
-###########################################################################
-
-log_error()
-{
- log 'ERROR' "$1"
- echo "Error: $1"
-}
-
-###########################################################################
-
-quit()
-{
- exit_status="$1"
-
- log_debug "-- $basename: finished (exit_status: $exit_status) --"
-
- exit $exit_status
-}
diff --git a/mysql-test/suite/im/t/wait_for_process.sh b/mysql-test/suite/im/t/wait_for_process.sh
deleted file mode 100755
index 2143ab2002f..00000000000
--- a/mysql-test/suite/im/t/wait_for_process.sh
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/bin/sh
-
-###########################################################################
-
-# NOTE: this script returns 0 (success) even in case of failure (except for
-# usage-error). This is because this script is executed under
-# mysql-test-run[.pl] and it's better to examine particular problem in log
-# file, than just having said that the test case has failed.
-
-###########################################################################
-
-basename=`basename "$0"`
-dirname=`dirname "$0"`
-
-###########################################################################
-
-. "$dirname/utils.sh"
-
-###########################################################################
-
-check_started()
-{
- if [ ! -r "$pid_path" ]; then
- log_debug "No PID-file ($pid_path) found -- not started."
- return 1
- fi
-
- new_pid=`cat "$pid_path" 2>/dev/null`
- err_code=$?
-
- log_debug "err_code: $err_code; new_pid: $new_pid."
-
- if [ $? -ne 0 -o -z "$new_pid" ]; then
- log_debug "The process was not started."
- return 1
- fi
-
- log_debug "The process was started."
- return 0
-}
-
-###########################################################################
-
-check_stopped()
-{
- if [ -r "$pid_path" ]; then
- log_debug "PID-file '$pid_path' exists -- not stopped."
- return 1
- fi
-
- log_debug "No PID-file ($pid_path) found -- stopped."
- return 0
-}
-
-###########################################################################
-
-if [ $# -ne 4 ]; then
- echo "Usage: $basename <pid file path> <total attempts> started|stopped <test id>"
- exit 1
-fi
-
-pid_path="$1"
-total_attempts="$2"
-event="$3"
-test_id="$4"
-log_file="$MYSQLTEST_VARDIR/log/$test_id.script.log"
-
-log_debug "-- $basename: starting --"
-log_debug "pid_path: '$pid_path'"
-log_debug "total_attempts: '$total_attempts'"
-log_debug "event: '$event'"
-log_debug "test_id: '$test_id'"
-log_debug "log_file: '$log_file'"
-
-###########################################################################
-
-case "$event" in
- started)
- check_fn='check_started';
- ;;
-
- stopped)
- check_fn='check_stopped';
- ;;
-
- *)
- log_error "Invalid third argument ('started' or 'stopped' expected)."
- quit 0
-esac
-
-###########################################################################
-
-cur_attempt=1
-
-while true; do
-
- log_debug "cur_attempt: $cur_attempt."
-
- if ( eval $check_fn ); then
- log_info "Success: the process has been $event."
- quit 0
- fi
-
- [ $cur_attempt -ge $total_attempts ] && break
-
- log_debug "Sleeping for 1 second..."
- sleep 1
-
- cur_attempt=`expr $cur_attempt + 1`
-
-done
-
-log_error "The process has not been $event in $total_attempts secs."
-quit 0
diff --git a/mysql-test/suite/im/t/wait_for_socket.sh b/mysql-test/suite/im/t/wait_for_socket.sh
deleted file mode 100755
index 2fa7d5c5b7e..00000000000
--- a/mysql-test/suite/im/t/wait_for_socket.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/sh
-
-###########################################################################
-
-# NOTE: this script returns 0 (success) even in case of failure (except for
-# usage-error). This is because this script is executed under
-# mysql-test-run[.pl] and it's better to examine particular problem in log
-# file, than just having said that the test case has failed.
-
-###########################################################################
-
-basename=`basename "$0"`
-dirname=`dirname "$0"`
-
-###########################################################################
-
-. "$dirname/utils.sh"
-
-###########################################################################
-
-if [ $# -ne 7 ]; then
- echo "Usage: wait_for_socket.sh <executable path> <socket path> <username> <password> <db> <timeout> <test id>"
- exit 1
-fi
-
-client_exe="$1"
-socket_path="$2"
-username="$3"
-password="$4"
-db="$5"
-total_timeout="$6"
-test_id="$7"
-log_file="$MYSQLTEST_VARDIR/log/$test_id.script.log"
-
-log_debug "-- $basename: starting --"
-log_debug "client_exe: '$client_exe'"
-log_debug "socket_path: '$socket_path'"
-log_debug "username: '$username'"
-log_debug "password: '$password'"
-log_debug "db: '$db'"
-log_debug "total_timeout: '$total_timeout'"
-log_debug "test_id: '$test_id'"
-log_debug "log_file: '$log_file'"
-
-###########################################################################
-
-if [ -z "$client_exe" ]; then
- log_error "Invalid path to client executable ($client_exe)."
- quit 0;
-fi
-
-if [ ! -x "$client_exe" ]; then
- log_error "Client by path '$client_exe' is not available."
- quit 0;
-fi
-
-if [ -z "$socket_path" ]; then
- log_error "Invalid socket patch ($socket_path)."
- quit 0
-fi
-
-###########################################################################
-
-client_args="--no-defaults --silent --socket=$socket_path --connect_timeout=1 "
-
-[ -n "$username" ] && client_args="$client_args --user=$username "
-[ -n "$password" ] && client_args="$client_args --password=$password "
-[ -n "$db" ] && client_args="$client_args $db"
-
-log_debug "client_args: '$client_args'"
-
-###########################################################################
-
-cur_attempt=1
-
-while true; do
-
- log_debug "cur_attempt: $cur_attempt."
-
- if ( echo 'quit' | "$client_exe" $client_args >/dev/null 2>&1 ); then
- log_info "Success: server is ready to accept connection on socket."
- quit 0
- fi
-
- [ $cur_attempt -ge $total_timeout ] && break
-
- sleep 1
-
- cur_attempt=`expr $cur_attempt + 1`
-
-done
-
-log_error "Server does not accept connections after $total_timeout seconds."
-quit 0
diff --git a/mysql-test/suite/innodb/r/innodb-zip.result b/mysql-test/suite/innodb/r/innodb-zip.result
index b26c4112826..a59758c8673 100644
--- a/mysql-test/suite/innodb/r/innodb-zip.result
+++ b/mysql-test/suite/innodb/r/innodb-zip.result
@@ -198,13 +198,11 @@ create table t1 (id int primary key) engine = innodb key_block_size = 0;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16]
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 9;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 1;
create table t4 (id int primary key) engine = innodb key_block_size = 2;
@@ -235,28 +233,24 @@ key_block_size = 8 row_format = redundant;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb
key_block_size = 8 row_format = compact;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb
key_block_size = 8 row_format = dynamic;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb
key_block_size = 8 row_format = default;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t5' (errno: 1478)
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@@ -268,24 +262,18 @@ key_block_size = 9 row_format = redundant;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
-Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = compact;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
-Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t2 (id int primary key) engine = innodb
key_block_size = 9 row_format = dynamic;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
-Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Error 1005 Can't create table 'test.t2' (errno: 1478)
SELECT table_schema, table_name, row_format
FROM information_schema.tables WHERE engine='innodb';
@@ -295,43 +283,36 @@ create table t1 (id int primary key) engine = innodb key_block_size = 1;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 2;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 4;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb key_block_size = 8;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb key_block_size = 16;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table 'test.t5' (errno: 1478)
create table t6 (id int primary key) engine = innodb row_format = compressed;
ERROR HY000: Can't create table 'test.t6' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
Error 1005 Can't create table 'test.t6' (errno: 1478)
create table t7 (id int primary key) engine = innodb row_format = dynamic;
ERROR HY000: Can't create table 'test.t7' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
Error 1005 Can't create table 'test.t7' (errno: 1478)
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
@@ -347,43 +328,36 @@ create table t1 (id int primary key) engine = innodb key_block_size = 1;
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t1' (errno: 1478)
create table t2 (id int primary key) engine = innodb key_block_size = 2;
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t2' (errno: 1478)
create table t3 (id int primary key) engine = innodb key_block_size = 4;
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t3' (errno: 1478)
create table t4 (id int primary key) engine = innodb key_block_size = 8;
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t4' (errno: 1478)
create table t5 (id int primary key) engine = innodb key_block_size = 16;
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t5' (errno: 1478)
create table t6 (id int primary key) engine = innodb row_format = compressed;
ERROR HY000: Can't create table 'test.t6' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t6' (errno: 1478)
create table t7 (id int primary key) engine = innodb row_format = dynamic;
ERROR HY000: Can't create table 'test.t7' (errno: 1478)
show errors;
Level Code Message
-Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.t7' (errno: 1478)
create table t8 (id int primary key) engine = innodb row_format = compact;
create table t9 (id int primary key) engine = innodb row_format = redundant;
diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def
index baf8c89f539..195fd1c0758 100644
--- a/mysql-test/suite/innodb/t/disabled.def
+++ b/mysql-test/suite/innodb/t/disabled.def
@@ -1 +1 @@
-innodb-index: InnoDB: Error: table `test`.`t1#1` already exists in InnoDB internal
+innodb-index : Bug#47563 2009-06-11 svoj InnoDB: Error: table `test`.`t1#1` already exists in InnoDB internal
diff --git a/mysql-test/suite/large_tests/r/lock_tables_big.result b/mysql-test/suite/large_tests/r/lock_tables_big.result
new file mode 100644
index 00000000000..de639143055
--- /dev/null
+++ b/mysql-test/suite/large_tests/r/lock_tables_big.result
@@ -0,0 +1 @@
+all done
diff --git a/mysql-test/suite/large_tests/t/lock_tables_big.test b/mysql-test/suite/large_tests/t/lock_tables_big.test
new file mode 100644
index 00000000000..41dcff3577c
--- /dev/null
+++ b/mysql-test/suite/large_tests/t/lock_tables_big.test
@@ -0,0 +1,32 @@
+#
+# Bug#24509 cannot use more than 2048 file descriptors on windows
+#
+--disable_query_log
+create database many_tables;
+use many_tables;
+let $max_tables=3000;
+let $i=$max_tables;
+
+--disable_warnings
+create table t (i int);
+let $table_list=t READ;
+
+while ($i)
+{
+ eval create table t$i (i int);
+ let $table_list= $table_list ,t$i READ;
+ dec $i;
+}
+
+#lock all tables we just created (resembles mysqldump startup is doing with --all-databases operation)
+#There will be 3 descriptors for each table (table.FRM, table.MYI and table.MYD files) means 9000 files
+#descriptors altogether. For Microsoft C runtime, this is way too many.
+
+eval LOCK TABLES $table_list;
+unlock tables;
+
+drop database many_tables;
+--disable_query_log
+--echo all done
+
+
diff --git a/mysql-test/suite/ndb/r/ndb_bitfield.result b/mysql-test/suite/ndb/r/ndb_bitfield.result
index 59c4d420b22..826f3a98348 100644
--- a/mysql-test/suite/ndb/r/ndb_bitfield.result
+++ b/mysql-test/suite/ndb/r/ndb_bitfield.result
@@ -204,7 +204,7 @@ b int
ERROR HY000: Can't create table 'test.t1' (errno: 906)
show warnings;
Level Code Message
-Error 1296 Got error 906 'Unsupported attribute type in index' from NDB
+Warning 1296 Got error 906 'Unsupported attribute type in index' from NDB
Error 1005 Can't create table 'test.t1' (errno: 906)
create table t1 (
pk1 int not null primary key,
@@ -214,7 +214,7 @@ key(b)
ERROR HY000: Can't create table 'test.t1' (errno: 906)
show warnings;
Level Code Message
-Error 1296 Got error 906 'Unsupported attribute type in index' from NDB
+Warning 1296 Got error 906 'Unsupported attribute type in index' from NDB
Error 1005 Can't create table 'test.t1' (errno: 906)
create table t1 (
pk1 int primary key,
diff --git a/mysql-test/suite/ndb/r/ndb_dd_basic.result b/mysql-test/suite/ndb/r/ndb_dd_basic.result
index 41e3d10fe5b..b956d3b0047 100644
--- a/mysql-test/suite/ndb/r/ndb_dd_basic.result
+++ b/mysql-test/suite/ndb/r/ndb_dd_basic.result
@@ -8,20 +8,20 @@ INITIAL_SIZE 16M
UNDO_BUFFER_SIZE = 1M
ENGINE=MYISAM;
Warnings:
-Error 1478 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
ALTER LOGFILE GROUP lg1
ADD UNDOFILE 'undofile02.dat'
INITIAL_SIZE = 4M
ENGINE=XYZ;
Warnings:
Warning 1286 Unknown table engine 'XYZ'
-Error 1478 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
USE LOGFILE GROUP lg1
INITIAL_SIZE 12M;
Warnings:
-Error 1478 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
+Warning 1478 Table storage engine 'MyISAM' does not support the create option 'TABLESPACE or LOGFILE GROUP'
set storage_engine=ndb;
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
diff --git a/mysql-test/suite/ndb/r/ndb_dd_ddl.result b/mysql-test/suite/ndb/r/ndb_dd_ddl.result
index d8d9e8631d5..2bf30f5c7fc 100644
--- a/mysql-test/suite/ndb/r/ndb_dd_ddl.result
+++ b/mysql-test/suite/ndb/r/ndb_dd_ddl.result
@@ -15,7 +15,7 @@ ENGINE NDB;
ERROR HY000: Failed to create LOGFILE GROUP
SHOW WARNINGS;
Level Code Message
-Error 1296 Got error 1514 'Currently there is a limit of one logfile group' from NDB
+Warning 1296 Got error 1514 'Currently there is a limit of one logfile group' from NDB
Error 1528 Failed to create LOGFILE GROUP
CREATE LOGFILE GROUP lg1
ADD UNDOFILE 'undofile.dat'
diff --git a/mysql-test/suite/ndb/r/ndb_gis.result b/mysql-test/suite/ndb/r/ndb_gis.result
index 374d702c408..61d15b7cb98 100644
--- a/mysql-test/suite/ndb/r/ndb_gis.result
+++ b/mysql-test/suite/ndb/r/ndb_gis.result
@@ -463,7 +463,7 @@ drop table t1;
End of 4.1 tests
CREATE TABLE t1 (name VARCHAR(100), square GEOMETRY);
Warnings:
-Error 1478 Table storage engine 'ndbcluster' does not support the create option 'Binlog of table with BLOB attribute and no PK'
+Warning 1478 Table storage engine 'ndbcluster' does not support the create option 'Binlog of table with BLOB attribute and no PK'
INSERT INTO t1 VALUES("center", GeomFromText('POLYGON (( 0 0, 0 2, 2 2, 2 0, 0 0))'));
INSERT INTO t1 VALUES("small", GeomFromText('POLYGON (( 0 0, 0 1, 1 1, 1 0, 0 0))'));
INSERT INTO t1 VALUES("big", GeomFromText('POLYGON (( 0 0, 0 3, 3 3, 3 0, 0 0))'));
@@ -1013,7 +1013,7 @@ drop table t1;
End of 4.1 tests
CREATE TABLE t1 (name VARCHAR(100), square GEOMETRY);
Warnings:
-Error 1478 Table storage engine 'ndbcluster' does not support the create option 'Binlog of table with BLOB attribute and no PK'
+Warning 1478 Table storage engine 'ndbcluster' does not support the create option 'Binlog of table with BLOB attribute and no PK'
INSERT INTO t1 VALUES("center", GeomFromText('POLYGON (( 0 0, 0 2, 2 2, 2 0, 0 0))'));
INSERT INTO t1 VALUES("small", GeomFromText('POLYGON (( 0 0, 0 1, 1 1, 1 0, 0 0))'));
INSERT INTO t1 VALUES("big", GeomFromText('POLYGON (( 0 0, 0 3, 3 3, 3 0, 0 0))'));
diff --git a/mysql-test/suite/ndb/r/ndb_multi_row.result b/mysql-test/suite/ndb/r/ndb_multi_row.result
index 3d34b16a1a8..96986490d23 100644
--- a/mysql-test/suite/ndb/r/ndb_multi_row.result
+++ b/mysql-test/suite/ndb/r/ndb_multi_row.result
@@ -63,6 +63,6 @@ t4
drop table t1, t2, t3, t4;
drop table if exists t1, t3, t4;
Warnings:
-Error 155 Table 'test.t1' doesn't exist
-Error 155 Table 'test.t3' doesn't exist
-Error 155 Table 'test.t4' doesn't exist
+Warning 155 Table 'test.t1' doesn't exist
+Warning 155 Table 'test.t3' doesn't exist
+Warning 155 Table 'test.t4' doesn't exist
diff --git a/mysql-test/suite/ndb/r/ndb_partition_error.result b/mysql-test/suite/ndb/r/ndb_partition_error.result
index d86dc382185..df2db5c5f06 100644
--- a/mysql-test/suite/ndb/r/ndb_partition_error.result
+++ b/mysql-test/suite/ndb/r/ndb_partition_error.result
@@ -14,7 +14,7 @@ partition x3 values less than (20) nodegroup 14);
ERROR HY000: Can't create table 'test.t1' (errno: 140)
show warnings;
Level Code Message
-Error 1296 Got error 771 'Given NODEGROUP doesn't exist in this cluster' from NDB
+Warning 1296 Got error 771 'Given NODEGROUP doesn't exist in this cluster' from NDB
Error 1005 Can't create table 'test.t1' (errno: 140)
CREATE TABLE t1 (
a int not null,
diff --git a/mysql-test/suite/ndb/r/ndb_row_format.result b/mysql-test/suite/ndb/r/ndb_row_format.result
index eea0692dd92..48a314c2fe9 100644
--- a/mysql-test/suite/ndb/r/ndb_row_format.result
+++ b/mysql-test/suite/ndb/r/ndb_row_format.result
@@ -8,7 +8,7 @@ ENGINE=NDB;
ERROR HY000: Can't create table 'test.t1' (errno: 138)
SHOW WARNINGS;
Level Code Message
-Error 1478 Table storage engine 'ndbcluster' does not support the create option 'Row format FIXED incompatible with variable sized attribute'
+Warning 1478 Table storage engine 'ndbcluster' does not support the create option 'Row format FIXED incompatible with variable sized attribute'
Error 1005 Can't create table 'test.t1' (errno: 138)
CREATE TABLE t1
( a INT KEY,
diff --git a/mysql-test/suite/ndb/r/ndb_single_user.result b/mysql-test/suite/ndb/r/ndb_single_user.result
index 8133e540d71..1d5f3041adb 100644
--- a/mysql-test/suite/ndb/r/ndb_single_user.result
+++ b/mysql-test/suite/ndb/r/ndb_single_user.result
@@ -9,7 +9,7 @@ ENGINE=NDB;
ERROR HY000: Failed to create LOGFILE GROUP
show warnings;
Level Code Message
-Error 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
+Warning 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
Error 1528 Failed to create LOGFILE GROUP
create table t1 (a int key, b int unique, c int) engine ndb;
CREATE LOGFILE GROUP lg1
@@ -25,14 +25,14 @@ ENGINE NDB;
ERROR HY000: Failed to create TABLESPACE
show warnings;
Level Code Message
-Error 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
+Warning 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
Error 1528 Failed to create TABLESPACE
DROP LOGFILE GROUP lg1
ENGINE =NDB;
ERROR HY000: Failed to drop LOGFILE GROUP
show warnings;
Level Code Message
-Error 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
+Warning 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
Error 1529 Failed to drop LOGFILE GROUP
CREATE TABLESPACE ts1
ADD DATAFILE 'datafile.dat'
@@ -45,7 +45,7 @@ ENGINE NDB;
ERROR HY000: Failed to alter: DROP DATAFILE
show warnings;
Level Code Message
-Error 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
+Warning 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
Error 1533 Failed to alter: DROP DATAFILE
ALTER TABLESPACE ts1
DROP DATAFILE 'datafile.dat'
@@ -55,7 +55,7 @@ ENGINE NDB;
ERROR HY000: Failed to drop TABLESPACE
show warnings;
Level Code Message
-Error 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
+Warning 1296 Got error 299 'Operation not allowed or aborted due to single user mode' from NDB
Error 1529 Failed to drop TABLESPACE
DROP TABLESPACE ts1
ENGINE NDB;
diff --git a/mysql-test/suite/ndb/r/ps_7ndb.result b/mysql-test/suite/ndb/r/ps_7ndb.result
index 73a2e0c1dda..e57fdcb6df6 100644
--- a/mysql-test/suite/ndb/r/ps_7ndb.result
+++ b/mysql-test/suite/ndb/r/ps_7ndb.result
@@ -59,8 +59,8 @@ def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
-def test t9 t9 c11 c11 246 9 6 Y 0 4 63
-def test t9 t9 c12 c12 246 10 6 Y 0 4 63
+def test t9 t9 c11 c11 246 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 246 10 6 Y 32768 4 63
def test t9 t9 c13 c13 10 10 10 Y 128 0 63
def test t9 t9 c14 c14 12 19 19 Y 128 0 63
def test t9 t9 c15 c15 7 19 19 N 9441 0 63
@@ -1790,8 +1790,8 @@ select * from t5 ;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test t5 t5 const01 const01 3 1 1 N 32769 0 63
def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
-def test t5 t5 const02 const02 246 4 3 N 1 1 63
-def test t5 t5 param02 param02 246 67 32 Y 0 30 63
+def test t5 t5 const02 const02 246 4 3 N 32769 1 63
+def test t5 t5 param02 param02 246 67 32 Y 32768 30 63
def test t5 t5 const03 const03 5 17 1 N 32769 31 63
def test t5 t5 param03 param03 5 23 1 Y 32768 31 63
def test t5 t5 const04 const04 253 3 3 N 1 0 8
@@ -1812,7 +1812,7 @@ def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
-def test t5 t5 param13 param13 246 67 0 Y 0 30 63
+def test t5 t5 param13 param13 246 67 0 Y 32768 30 63
def test t5 t5 param14 param14 252 4294967295 0 Y 16 0 8
def test t5 t5 param15 param15 252 4294967295 0 Y 144 0 63
const01 8
@@ -1910,8 +1910,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -1957,8 +1957,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2007,8 +2007,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2047,8 +2047,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2095,8 +2095,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2139,8 +2139,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2185,8 +2185,8 @@ def @arg07 5 23 1 Y 32896 31 63
def @arg08 5 23 1 Y 32896 31 63
def @arg09 5 23 1 Y 32896 31 63
def @arg10 5 23 1 Y 32896 31 63
-def @arg11 246 83 6 Y 128 30 63
-def @arg12 246 83 6 Y 128 30 63
+def @arg11 246 83 6 Y 32896 30 63
+def @arg12 246 83 6 Y 32896 30 63
def @arg13 251 16777216 10 Y 128 31 63
def @arg14 251 16777216 19 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
@@ -2223,8 +2223,8 @@ def @arg07 5 23 0 Y 32896 31 63
def @arg08 5 23 0 Y 32896 31 63
def @arg09 5 23 0 Y 32896 31 63
def @arg10 5 23 0 Y 32896 31 63
-def @arg11 246 83 0 Y 128 30 63
-def @arg12 246 83 0 Y 128 30 63
+def @arg11 246 83 0 Y 32896 30 63
+def @arg12 246 83 0 Y 32896 30 63
def @arg13 251 16777216 0 Y 128 31 63
def @arg14 251 16777216 0 Y 128 31 63
def @arg15 251 16777216 19 Y 128 31 63
diff --git a/mysql-test/suite/parts/inc/partition_mgm.inc b/mysql-test/suite/parts/inc/partition_mgm.inc
index 1ab548222a8..9dfa2b2ffb3 100644
--- a/mysql-test/suite/parts/inc/partition_mgm.inc
+++ b/mysql-test/suite/parts/inc/partition_mgm.inc
@@ -13,6 +13,7 @@
# part_optA-D Extra partitioning options (E.g. INDEX/DATA DIR) #
# #
# have_bug33158 NDB case insensitive create, but case sensitive rename #
+# no_truncate No support for truncate partition #
#------------------------------------------------------------------------------#
# Original Author: mattiasj #
# Original Date: 2008-06-27 #
@@ -518,6 +519,95 @@ DROP TABLE TableA;
}
# End of $can_only_key
+if ($no_truncate)
+{
+--echo # Verify that TRUNCATE PARTITION gives error
+eval CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+ b VARCHAR(255))
+ENGINE = $engine
+PARTITION BY KEY (a)
+(PARTITION LT1000,
+ PARTITION LT2000,
+ PARTITION MAX);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+--error ER_PARTITION_MGMT_ON_NONPARTITIONED, ER_ILLEGAL_HA
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+}
+if (!$no_truncate)
+{
+--echo # Testing TRUNCATE PARTITION
+eval CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+ b VARCHAR(255))
+ENGINE = $engine
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+ PARTITION LT2000 VALUES LESS THAN (2000),
+ PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+SELECT * FROM t1 ORDER BY a;
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+--echo # Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+--echo # Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+--echo # Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+--echo # Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+--echo # Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+--echo # Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+--echo # Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+--echo # Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+--echo # Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+--echo # Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+--echo # Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+--echo # Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+DROP TABLE t1;
+}
--echo # Cleaning up before exit
eval USE $old_db;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_archive.result b/mysql-test/suite/parts/r/partition_mgm_lc0_archive.result
index 30ff27df298..4f623813386 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc0_archive.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc0_archive.result
@@ -915,6 +915,18 @@ TableA CREATE TABLE `TableA` (
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Verify that TRUNCATE PARTITION gives error
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'Archive'
+PARTITION BY KEY (a)
+(PARTITION LT1000,
+PARTITION LT2000,
+PARTITION MAX);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result
index cd55ffbad03..19f16780d13 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result
@@ -915,6 +915,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'InnoDB'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=InnoDB AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = InnoDB,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = InnoDB,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+MySQL_Test_DB.t1 analyze status OK
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result
index faf776e03a3..69a43b64d87 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result
@@ -915,6 +915,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=MEMORY DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'Memory'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MEMORY AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MEMORY,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MEMORY,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MEMORY) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+MySQL_Test_DB.t1 analyze note The storage engine for the table doesn't support analyze
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result
index 827f7a15c24..9b4e85be9d0 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result
@@ -915,6 +915,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'MyISAM'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MyISAM,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MyISAM,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+MySQL_Test_DB.t1 analyze status OK
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result b/mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result
index 45b674638e7..15b3f424527 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result
@@ -181,6 +181,18 @@ TableA CREATE TABLE `TableA` (
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
# Cleaning up after KEY PARTITIONING test
DROP TABLE TableA;
+# Verify that TRUNCATE PARTITION gives error
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'NDBCluster'
+PARTITION BY KEY (a)
+(PARTITION LT1000,
+PARTITION LT2000,
+PARTITION MAX);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_archive.result b/mysql-test/suite/parts/r/partition_mgm_lc1_archive.result
index 443453a2d70..4cd8cafa3ee 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc1_archive.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc1_archive.result
@@ -882,6 +882,18 @@ TableA CREATE TABLE `tablea` (
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Verify that TRUNCATE PARTITION gives error
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'Archive'
+PARTITION BY KEY (a)
+(PARTITION LT1000,
+PARTITION LT2000,
+PARTITION MAX);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result
index 49ccc7b1808..952f4136cb6 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result
@@ -882,6 +882,170 @@ TableA CREATE TABLE `tablea` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'InnoDB'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=InnoDB AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = InnoDB,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = InnoDB,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+mysql_test_db.t1 analyze status OK
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result
index 6f34054428c..435a0d8313e 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result
@@ -882,6 +882,170 @@ TableA CREATE TABLE `tablea` (
) ENGINE=MEMORY DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'Memory'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MEMORY AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MEMORY,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MEMORY,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MEMORY) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+mysql_test_db.t1 analyze note The storage engine for the table doesn't support analyze
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result
index ac230e29c66..3a90ce4d73c 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result
@@ -882,6 +882,170 @@ TableA CREATE TABLE `tablea` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'MyISAM'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MyISAM,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MyISAM,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+mysql_test_db.t1 analyze status OK
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result b/mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result
index 0a53e1b4a9b..1d221caa163 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result
@@ -219,6 +219,18 @@ TableA CREATE TABLE `tablea` (
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
# Cleaning up after KEY PARTITIONING test
DROP TABLE TableA;
+# Verify that TRUNCATE PARTITION gives error
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'NDBCluster'
+PARTITION BY KEY (a)
+(PARTITION LT1000,
+PARTITION LT2000,
+PARTITION MAX);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_archive.result b/mysql-test/suite/parts/r/partition_mgm_lc2_archive.result
index fc0390c238d..6e8abfef06d 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc2_archive.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc2_archive.result
@@ -882,6 +882,18 @@ TableA CREATE TABLE `TableA` (
) ENGINE=ARCHIVE DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Verify that TRUNCATE PARTITION gives error
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'Archive'
+PARTITION BY KEY (a)
+(PARTITION LT1000,
+PARTITION LT2000,
+PARTITION MAX);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result
index da111137068..8e42bc9eb62 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result
@@ -882,6 +882,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'InnoDB'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=InnoDB AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = InnoDB,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = InnoDB,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+mysql_test_db.t1 analyze status OK
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result
index a1716ea36c8..24047912ab1 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result
@@ -882,6 +882,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=MEMORY DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'Memory'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MEMORY AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MEMORY,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MEMORY,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MEMORY) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+mysql_test_db.t1 analyze note The storage engine for the table doesn't support analyze
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result
index 6bdfa149de0..7a61a811ea3 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result
@@ -882,6 +882,170 @@ TableA CREATE TABLE `TableA` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
# Cleaning up after LIST PARTITIONING test
DROP TABLE TableA;
+# Testing TRUNCATE PARTITION
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'MyISAM'
+PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000),
+PARTITION LT2000 VALUES LESS THAN (2000),
+PARTITION MAX VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) NOT NULL AUTO_INCREMENT,
+ `b` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MyISAM AUTO_INCREMENT=2002 DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY RANGE (a)
+(PARTITION LT1000 VALUES LESS THAN (1000) ENGINE = MyISAM,
+ PARTITION LT2000 VALUES LESS THAN (2000) ENGINE = MyISAM,
+ PARTITION MAX VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
+SELECT * FROM t1 ORDER BY a;
+a b
+1 First
+2 Second
+999 Last in LT1000
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First in MAX
+2001 Second in MAX
+ALTER TABLE t1 ANALYZE PARTITION MAX;
+Table Op Msg_type Msg_text
+mysql_test_db.t1 analyze status OK
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (1)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (2)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (3)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE MAX (4)");
+SELECT * FROM t1 WHERE a >= 2000;
+a b
+2000 First after TRUNCATE MAX (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT1000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT1000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+1000 First in LT2000
+1001 Second in LT2000
+1999 Last in LT2000
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+# Truncate without FLUSH
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (1)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+# Truncate with FLUSH after
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (2)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+# Truncate with FLUSH before
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (3)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+# Truncate with FLUSH after INSERT
+FLUSH TABLES;
+ALTER TABLE t1 TRUNCATE PARTITION LT2000;
+INSERT INTO t1 VALUES (NULL, "First after TRUNCATE LT2000 (4)");
+SELECT * FROM t1 ORDER BY a;
+a b
+2000 First after TRUNCATE MAX (4)
+2001 First after TRUNCATE LT1000 (1)
+2002 First after TRUNCATE LT1000 (2)
+2003 First after TRUNCATE LT1000 (3)
+2004 First after TRUNCATE LT1000 (4)
+2005 First after TRUNCATE LT2000 (1)
+2006 First after TRUNCATE LT2000 (2)
+2007 First after TRUNCATE LT2000 (3)
+2008 First after TRUNCATE LT2000 (4)
+DROP TABLE t1;
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result b/mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result
index 8b9c5be1fb6..2f5dfe5e08e 100644
--- a/mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result
+++ b/mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result
@@ -219,6 +219,18 @@ TableA CREATE TABLE `TableA` (
) ENGINE=ndbcluster DEFAULT CHARSET=latin1
# Cleaning up after KEY PARTITIONING test
DROP TABLE TableA;
+# Verify that TRUNCATE PARTITION gives error
+CREATE TABLE t1
+(a BIGINT AUTO_INCREMENT PRIMARY KEY,
+b VARCHAR(255))
+ENGINE = 'NDBCluster'
+PARTITION BY KEY (a)
+(PARTITION LT1000,
+PARTITION LT2000,
+PARTITION MAX);
+INSERT INTO t1 VALUES (NULL, "First"), (NULL, "Second"), (999, "Last in LT1000"), (NULL, "First in LT2000"), (NULL, "Second in LT2000"), (1999, "Last in LT2000"), (NULL, "First in MAX"), (NULL, "Second in MAX");
+ALTER TABLE t1 TRUNCATE PARTITION MAX;
+Got one of the listed errors
# Cleaning up before exit
USE test;
DROP DATABASE MySQL_Test_DB;
diff --git a/mysql-test/suite/parts/t/disabled.def b/mysql-test/suite/parts/t/disabled.def
index 518a3c90422..8a1dafe59a2 100644
--- a/mysql-test/suite/parts/t/disabled.def
+++ b/mysql-test/suite/parts/t/disabled.def
@@ -1,3 +1,3 @@
-partition_basic_ndb : Bug#19899 Crashing the server
+partition_basic_ndb : Bug#44919 parts-suite in mtr tries to use features not supported by ndb
# http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-limitations-syntax.html
partition_syntax_ndb : Bug#36735 Not supported
diff --git a/mysql-test/suite/parts/t/partition_mgm_lc0_archive.test b/mysql-test/suite/parts/t/partition_mgm_lc0_archive.test
index 5b4f2568d46..313da329a9f 100644
--- a/mysql-test/suite/parts/t/partition_mgm_lc0_archive.test
+++ b/mysql-test/suite/parts/t/partition_mgm_lc0_archive.test
@@ -35,6 +35,7 @@
##### Storage engine to be tested
--source include/have_archive.inc
let $engine= 'Archive';
+let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines
diff --git a/mysql-test/suite/parts/t/partition_mgm_lc0_ndb.test b/mysql-test/suite/parts/t/partition_mgm_lc0_ndb.test
index 686c69cca25..736e45067bc 100644
--- a/mysql-test/suite/parts/t/partition_mgm_lc0_ndb.test
+++ b/mysql-test/suite/parts/t/partition_mgm_lc0_ndb.test
@@ -41,6 +41,8 @@ let $can_only_key= 1;
# Allow hash/list/range partitioning with ndb
#SET new=on;
let $engine= 'NDBCluster';
+# NDB does not yet support TRUNCATE PARTITION
+let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines
diff --git a/mysql-test/suite/parts/t/partition_mgm_lc1_archive.test b/mysql-test/suite/parts/t/partition_mgm_lc1_archive.test
index 2bc643db75f..58eef828f06 100644
--- a/mysql-test/suite/parts/t/partition_mgm_lc1_archive.test
+++ b/mysql-test/suite/parts/t/partition_mgm_lc1_archive.test
@@ -32,6 +32,7 @@
##### Storage engine to be tested
--source include/have_archive.inc
let $engine= 'Archive';
+let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines
diff --git a/mysql-test/suite/parts/t/partition_mgm_lc1_ndb.test b/mysql-test/suite/parts/t/partition_mgm_lc1_ndb.test
index a70b9b5c41c..ac425eb84ff 100644
--- a/mysql-test/suite/parts/t/partition_mgm_lc1_ndb.test
+++ b/mysql-test/suite/parts/t/partition_mgm_lc1_ndb.test
@@ -38,6 +38,8 @@ let $can_only_key= 1;
# Allow hash/list/range partitioning with ndb
#SET new=on;
let $engine= 'NDBCluster';
+# NDB does not yet support TRUNCATE PARTITION
+let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines
diff --git a/mysql-test/suite/parts/t/partition_mgm_lc2_archive.test b/mysql-test/suite/parts/t/partition_mgm_lc2_archive.test
index d0e2591804d..92036178e59 100644
--- a/mysql-test/suite/parts/t/partition_mgm_lc2_archive.test
+++ b/mysql-test/suite/parts/t/partition_mgm_lc2_archive.test
@@ -32,6 +32,7 @@
##### Storage engine to be tested
--source include/have_archive.inc
let $engine= 'Archive';
+let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines
diff --git a/mysql-test/suite/parts/t/partition_mgm_lc2_ndb.test b/mysql-test/suite/parts/t/partition_mgm_lc2_ndb.test
index 67fdfdde70b..725ba3b5e74 100644
--- a/mysql-test/suite/parts/t/partition_mgm_lc2_ndb.test
+++ b/mysql-test/suite/parts/t/partition_mgm_lc2_ndb.test
@@ -37,6 +37,8 @@ let $can_only_key= 1;
# Allow hash/list/range partitioning with ndb
#SET new=on;
let $engine= 'NDBCluster';
+# NDB does not yet support TRUNCATE PARTITION
+let $no_truncate= 1;
#------------------------------------------------------------------------------#
# Execute the tests to be applied to all storage engines
diff --git a/mysql-test/suite/rpl/r/rpl_EE_err.result b/mysql-test/suite/rpl/r/rpl_EE_err.result
index 16fa931e303..8c1277445b2 100644
--- a/mysql-test/suite/rpl/r/rpl_EE_err.result
+++ b/mysql-test/suite/rpl/r/rpl_EE_err.result
@@ -8,4 +8,4 @@ create table t1 (a int) engine=myisam;
flush tables;
drop table if exists t1;
Warnings:
-Error 2 Can't find file: 't1' (errno: 2)
+Warning 2 Can't find file: 't1' (errno: 2)
diff --git a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result
index 99a0fd21f66..3321b9b4969 100644
--- a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result
+++ b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result
@@ -18,7 +18,7 @@ start slave;
SELECT RELEASE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP");
RELEASE_LOCK("debug_lock.before_get_UNIX_TIMESTAMP")
1
-Slave_IO_Errno= 2013
+Slave_IO_Errno= 2003
SELECT IS_FREE_LOCK("debug_lock.before_get_SERVER_ID");
IS_FREE_LOCK("debug_lock.before_get_SERVER_ID")
1
@@ -31,7 +31,7 @@ start slave;
SELECT RELEASE_LOCK("debug_lock.before_get_SERVER_ID");
RELEASE_LOCK("debug_lock.before_get_SERVER_ID")
1
-Slave_IO_Errno= 2013
+Slave_IO_Errno= 2003
set global debug= '';
reset master;
include/stop_slave.inc
diff --git a/mysql-test/suite/rpl/r/rpl_row_sp007_innodb.result b/mysql-test/suite/rpl/r/rpl_row_sp007_innodb.result
index 9a2822835f8..5a6a9ace4c5 100644
--- a/mysql-test/suite/rpl/r/rpl_row_sp007_innodb.result
+++ b/mysql-test/suite/rpl/r/rpl_row_sp007_innodb.result
@@ -22,8 +22,6 @@ END|
< ---- Master selects-- >
-------------------------
CALL test.p1(12);
-Warnings:
-Note 1051 Unknown table 't1'
SELECT * FROM test.t1;
num
12
diff --git a/mysql-test/suite/rpl/t/disabled.def b/mysql-test/suite/rpl/t/disabled.def
index 38fc9e21322..85747264b6f 100644
--- a/mysql-test/suite/rpl/t/disabled.def
+++ b/mysql-test/suite/rpl/t/disabled.def
@@ -10,4 +10,4 @@
#
##############################################################################
-rpl_cross_version : Bug#42311 2009-03-27 joro rpl_cross_version fails on macosx
+rpl_cross_version : Bug#43913 2009-03-27 joro rpl_cross_version can't pass on conflicts complainig clash with --slave-load-tm
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index f0c769251cf..7e93b638acb 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1456,3 +1456,22 @@ SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) from t1 GROUP BY b;
DROP TABLE t1;
--echo End of 5.0 tests
+
+
+--echo Start of 5.4 tests
+#
+# Bug#26474: Add Sinhala script (Sri Lanka) collation to MySQL
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TABLE t1 (
+ predicted_order int NOT NULL,
+ utf8_encoding VARCHAR(10) NOT NULL
+) CHARACTER SET utf8;
+INSERT INTO t1 VALUES (19, x'E0B696'), (30, x'E0B69AE0B798'), (61, x'E0B6AF'), (93, x'E0B799'), (52, x'E0B6A6'), (73, x'E0B6BBE0B78AE2808D'), (3, x'E0B686'), (56, x'E0B6AA'), (55, x'E0B6A9'), (70, x'E0B6B9'), (94, x'E0B79A'), (80, x'E0B785'), (25, x'E0B69AE0B791'), (48, x'E0B6A2'), (13, x'E0B690'), (86, x'E0B793'), (91, x'E0B79F'), (81, x'E0B786'), (79, x'E0B784'), (14, x'E0B691'), (99, x'E0B78A'), (8, x'E0B68B'), (68, x'E0B6B7'), (22, x'E0B69A'), (16, x'E0B693'), (33, x'E0B69AE0B7B3'), (38, x'E0B69AE0B79D'), (21, x'E0B683'), (11, x'E0B68E'), (77, x'E0B782'), (40, x'E0B69AE0B78A'), (101, x'E0B78AE2808DE0B6BB'), (35, x'E0B69AE0B79A'), (1, x'E0B7B4'), (9, x'E0B68C'), (96, x'E0B79C'), (6, x'E0B689'), (95, x'E0B79B'), (88, x'E0B796'), (64, x'E0B6B3'), (26, x'E0B69AE0B792'), (82, x'E0B78F'), (28, x'E0B69AE0B794'), (39, x'E0B69AE0B79E'), (97, x'E0B79D'), (2, x'E0B685'), (75, x'E0B780'), (34, x'E0B69AE0B799'), (69, x'E0B6B8'), (83, x'E0B790'), (18, x'E0B695'), (90, x'E0B7B2'), (17, x'E0B694'), (72, x'E0B6BB'), (66, x'E0B6B5'), (59, x'E0B6AD'), (44, x'E0B69E'), (15, x'E0B692'), (23, x'E0B69AE0B78F'), (65, x'E0B6B4'), (42, x'E0B69C'), (63, x'E0B6B1'), (85, x'E0B792'), (47, x'E0B6A1'), (49, x'E0B6A3'), (92, x'E0B7B3'), (78, x'E0B783'), (36, x'E0B69AE0B79B'), (4, x'E0B687'), (24, x'E0B69AE0B790'), (87, x'E0B794'), (37, x'E0B69AE0B79C'), (32, x'E0B69AE0B79F'), (29, x'E0B69AE0B796'), (43, x'E0B69D'), (62, x'E0B6B0'), (100, x'E0B78AE2808DE0B6BA'), (60, x'E0B6AE'), (45, x'E0B69F'), (12, x'E0B68F'), (46, x'E0B6A0'), (50, x'E0B6A5'), (51, x'E0B6A4'), (5, x'E0B688'), (76, x'E0B781'), (89, x'E0B798'), (74, x'E0B6BD'), (10, x'E0B68D'), (57, x'E0B6AB'), (71, x'E0B6BA'), (58, x'E0B6AC'), (27, x'E0B69AE0B793'), (54, x'E0B6A8'), (84, x'E0B791'), (31, x'E0B69AE0B7B2'), (98, x'E0B79E'), (53, x'E0B6A7'), (41, x'E0B69B'), (67, x'E0B6B6'), (7, x'E0B68A'), (20, x'E0B682');
+SELECT predicted_order, hex(utf8_encoding) FROM t1 ORDER BY utf8_encoding COLLATE utf8_sinhala_ci;
+DROP TABLE t1;
+
+--echo End of 5.4 tests
+
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index e92f3e96303..71d3d5a140b 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -694,3 +694,35 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN
DROP TABLE t1, t2;
--echo End of 5.0 tests
+
+#
+# Bug#36785: Wrong error message when group_concat() exceeds max length
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+CREATE TABLE t1 (a VARCHAR(6), b INT);
+CREATE TABLE t2 (a VARCHAR(6), b INT);
+
+INSERT INTO t1 VALUES ('111111', 1);
+INSERT INTO t1 VALUES ('222222', 2);
+INSERT INTO t1 VALUES ('333333', 3);
+INSERT INTO t1 VALUES ('444444', 4);
+INSERT INTO t1 VALUES ('555555', 5);
+
+SET group_concat_max_len = 5;
+SET @old_sql_mode = @@sql_mode, @@sql_mode = 'traditional';
+
+SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b LIMIT 3;
+--error ER_CUT_VALUE_GROUP_CONCAT
+INSERT INTO t2 SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b;
+UPDATE t1 SET a = '11111' WHERE b = 1;
+UPDATE t1 SET a = '22222' WHERE b = 2;
+--error ER_CUT_VALUE_GROUP_CONCAT
+INSERT INTO t2 SELECT GROUP_CONCAT(a), b FROM t1 GROUP BY b;
+
+SET group_concat_max_len = DEFAULT;
+SET @@sql_mode = @old_sql_mode;
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 66b9eabd385..032c9ade643 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -1318,3 +1318,45 @@ insert into t1 values (-1),(null);
explain select 1 as a from t1,(select decode(f1,f1) as b from t1) a;
explain select 1 as a from t1,(select encode(f1,f1) as b from t1) a;
drop table t1;
+
+
+
+--echo Start of 5.4 tests
+#
+# WL#4584 Internationalized number format
+#
+SELECT format(12345678901234567890.123, 3);
+SELECT format(12345678901234567890.123, 3, NULL);
+SELECT format(12345678901234567890.123, 3, 'ar_AE');
+SELECT format(12345678901234567890.123, 3, 'ar_SA');
+SELECT format(12345678901234567890.123, 3, 'be_BY');
+SELECT format(12345678901234567890.123, 3, 'de_DE');
+SELECT format(12345678901234567890.123, 3, 'en_IN');
+SELECT format(12345678901234567890.123, 3, 'en_US');
+SELECT format(12345678901234567890.123, 3, 'it_CH');
+SELECT format(12345678901234567890.123, 3, 'ru_RU');
+SELECT format(12345678901234567890.123, 3, 'ta_IN');
+
+CREATE TABLE t1 (fmt CHAR(5) NOT NULL);
+INSERT INTO t1 VALUES ('ar_AE');
+INSERT INTO t1 VALUES ('ar_SA');
+INSERT INTO t1 VALUES ('be_BY');
+INSERT INTO t1 VALUES ('de_DE');
+INSERT INTO t1 VALUES ('en_IN');
+INSERT INTO t1 VALUES ('en_US');
+INSERT INTO t1 VALUES ('it_CH');
+INSERT INTO t1 VALUES ('ru_RU');
+INSERT INTO t1 VALUES ('ta_IN');
+SELECT fmt, format(12345678901234567890.123, 3, fmt) FROM t1 ORDER BY fmt;
+SELECT fmt, format(12345678901234567890.123, 0, fmt) FROM t1 ORDER BY fmt;
+SELECT fmt, format(12345678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+SELECT fmt, format(-12345678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+SELECT fmt, format(-02345678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+SELECT fmt, format(-00345678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+SELECT fmt, format(-00045678901234567890, 3, fmt) FROM t1 ORDER BY fmt;
+DROP TABLE t1;
+
+SELECT format(123, 1, 'Non-existent-locale');
+
+--echo End of 5.4 tests
+
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index c09a4fbf490..3ff3b96d829 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -570,13 +570,13 @@ explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
-explain extended select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
+explain extended select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
-select ord(a1) + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
+select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
#
# Queries with expressions in the select clause
@@ -1033,3 +1033,124 @@ SELECT a, MAX(b) FROM t WHERE b GROUP BY a;
DROP TABLE t;
--echo End of 5.1 tests
+
+
+--echo #
+--echo # WL#3220 (Loose index scan for COUNT DISTINCT)
+--echo #
+
+CREATE TABLE t1 (a INT, b INT, c INT, KEY (a,b));
+INSERT INTO t1 VALUES (1,1,1), (1,2,1), (1,3,1), (1,4,1);
+INSERT INTO t1 SELECT a, b + 4, 1 FROM t1;
+INSERT INTO t1 SELECT a + 1, b, 1 FROM t1;
+CREATE TABLE t2 (a INT, b INT, c INT, d INT, e INT, f INT, KEY (a,b,c));
+INSERT INTO t2 VALUES (1,1,1,1,1,1), (1,2,1,1,1,1), (1,3,1,1,1,1),
+ (1,4,1,1,1,1);
+INSERT INTO t2 SELECT a, b + 4, c,d,e,f FROM t2;
+INSERT INTO t2 SELECT a + 1, b, c,d,e,f FROM t2;
+
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1;
+SELECT COUNT(DISTINCT a) FROM t1;
+
+EXPLAIN SELECT COUNT(DISTINCT a,b) FROM t1;
+SELECT COUNT(DISTINCT a,b) FROM t1;
+
+EXPLAIN SELECT COUNT(DISTINCT b,a) FROM t1;
+SELECT COUNT(DISTINCT b,a) FROM t1;
+
+EXPLAIN SELECT COUNT(DISTINCT b) FROM t1;
+SELECT COUNT(DISTINCT b) FROM t1;
+
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
+SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
+
+EXPLAIN SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
+SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
+
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
+SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
+
+EXPLAIN SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
+SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
+
+EXPLAIN SELECT COUNT(DISTINCT a, b + 0) FROM t1;
+SELECT COUNT(DISTINCT a, b + 0) FROM t1;
+
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
+SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
+
+EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
+SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
+
+EXPLAIN SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
+SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
+
+EXPLAIN SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
+SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
+
+EXPLAIN SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
+SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
+
+EXPLAIN SELECT COUNT(DISTINCT a), 12 FROM t1;
+SELECT COUNT(DISTINCT a), 12 FROM t1;
+
+EXPLAIN SELECT COUNT(DISTINCT a, b, c) FROM t2;
+SELECT COUNT(DISTINCT a, b, c) FROM t2;
+
+EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
+SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
+
+EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
+SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
+
+EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
+SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
+
+EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
+SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
+
+EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
+SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
+
+EXPLAIN SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
+SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
+
+EXPLAIN SELECT COUNT(DISTINCT c, a, b) FROM t2
+ WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
+SELECT COUNT(DISTINCT c, a, b) FROM t2
+ WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
+
+EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
+ GROUP BY b;
+SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
+ GROUP BY b;
+
+EXPLAIN SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
+SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
+
+EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
+SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
+
+EXPLAIN SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
+SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
+
+EXPLAIN SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
+ WHERE b = 13 AND c = 42 GROUP BY a;
+SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
+ WHERE b = 13 AND c = 42 GROUP BY a;
+
+EXPLAIN SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
+SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
+
+EXPLAIN SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
+SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
+
+EXPLAIN SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
+SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
+
+EXPLAIN SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
+SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
+
+DROP TABLE t1,t2;
+
+--echo # end of WL#3220 tests
diff --git a/mysql-test/t/index_merge_innodb.test b/mysql-test/t/index_merge_innodb.test
index 04516f45bfe..10d772797a2 100644
--- a/mysql-test/t/index_merge_innodb.test
+++ b/mysql-test/t/index_merge_innodb.test
@@ -21,14 +21,10 @@ let $index_merge_random_rows_in_EXPLAIN = 1;
# InnoDB does not support Merge tables (affects include/index_merge1.inc)
let $merge_table_support= 0;
-# The first two tests are disabled because of non deterministic explain output.
-# If include/index_merge1.inc can be enabled for InnoDB and all other
-# storage engines, please remove the subtest for Bug#21277 from
-# include/index_merge2.inc.
-# This test exists already in include/index_merge1.inc.
+# -- [DISABLED Bug#45727]
# --source include/index_merge1.inc
# --source include/index_merge_ror.inc
+# --source include/index_merge2.inc
---source include/index_merge2.inc
--source include/index_merge_2sweeps.inc
--source include/index_merge_ror_cpk.inc
diff --git a/mysql-test/t/information_schema-big.test b/mysql-test/t/information_schema-big.test
new file mode 100644
index 00000000000..c9cd65f0851
--- /dev/null
+++ b/mysql-test/t/information_schema-big.test
@@ -0,0 +1,48 @@
+# This test uses grants, which can't get tested for embedded server
+-- source include/big_test.inc
+-- source include/not_embedded.inc
+
+# check that CSV engine was compiled in, as the result of the test depends
+# on the presence of the log tables (which are CSV-based).
+--source include/have_csv.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t0,t1,t2,t3,t4,t5;
+DROP VIEW IF EXISTS v1;
+--enable_warnings
+
+
+--echo #
+--echo # Bug#18925: subqueries with MIN/MAX functions on INFORMARTION_SCHEMA
+--echo #
+
+SELECT t.table_name, c1.column_name
+ FROM information_schema.tables t
+ INNER JOIN
+ information_schema.columns c1
+ ON t.table_schema = c1.table_schema AND
+ t.table_name = c1.table_name
+ WHERE t.table_schema = 'information_schema' AND
+ c1.ordinal_position =
+ ( SELECT COALESCE(MIN(c2.ordinal_position),1)
+ FROM information_schema.columns c2
+ WHERE c2.table_schema = t.table_schema AND
+ c2.table_name = t.table_name AND
+ c2.column_name LIKE '%SCHEMA%'
+ )
+ AND t.table_name NOT LIKE 'innodb%';
+SELECT t.table_name, c1.column_name
+ FROM information_schema.tables t
+ INNER JOIN
+ information_schema.columns c1
+ ON t.table_schema = c1.table_schema AND
+ t.table_name = c1.table_name
+ WHERE t.table_schema = 'information_schema' AND
+ c1.ordinal_position =
+ ( SELECT COALESCE(MIN(c2.ordinal_position),1)
+ FROM information_schema.columns c2
+ WHERE c2.table_schema = 'information_schema' AND
+ c2.table_name = t.table_name AND
+ c2.column_name LIKE '%SCHEMA%'
+ )
+ AND t.table_name NOT LIKE 'innodb%';
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index 6060c78f791..b590ec306d6 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -914,41 +914,6 @@ DROP PROCEDURE p1;
DROP USER mysql_bug20230@localhost;
#
-# Bug#18925 subqueries with MIN/MAX functions on INFORMARTION_SCHEMA
-#
-
-SELECT t.table_name, c1.column_name
- FROM information_schema.tables t
- INNER JOIN
- information_schema.columns c1
- ON t.table_schema = c1.table_schema AND
- t.table_name = c1.table_name
- WHERE t.table_schema = 'information_schema' AND
- c1.ordinal_position =
- ( SELECT COALESCE(MIN(c2.ordinal_position),1)
- FROM information_schema.columns c2
- WHERE c2.table_schema = t.table_schema AND
- c2.table_name = t.table_name AND
- c2.column_name LIKE '%SCHEMA%'
- )
- AND t.table_name not like 'innodb_%';
-SELECT t.table_name, c1.column_name
- FROM information_schema.tables t
- INNER JOIN
- information_schema.columns c1
- ON t.table_schema = c1.table_schema AND
- t.table_name = c1.table_name
- WHERE t.table_schema = 'information_schema' AND
- c1.ordinal_position =
- ( SELECT COALESCE(MIN(c2.ordinal_position),1)
- FROM information_schema.columns c2
- WHERE c2.table_schema = 'information_schema' AND
- c2.table_name = t.table_name AND
- c2.column_name LIKE '%SCHEMA%'
- )
- AND t.table_name not like 'innodb_%';
-
-#
# Bug#2123 query with a simple non-correlated subquery over
# INFORMARTION_SCHEMA.TABLES
#
diff --git a/mysql-test/t/loadxml.test b/mysql-test/t/loadxml.test
new file mode 100644
index 00000000000..accd08c8bfe
--- /dev/null
+++ b/mysql-test/t/loadxml.test
@@ -0,0 +1,107 @@
+#
+# Tests for "LOAD XML" - a contributed patch from Erik Wetterberg.
+#
+
+# Running the $MYSQL_DUMP tool against an embedded server does not work.
+--source include/not_embedded.inc
+
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+
+create table t1 (a int, b varchar(64));
+
+
+--echo -- Load a static XML file
+load xml infile '../../std_data/loadxml.dat' into table t1
+rows identified by '<row>';
+select * from t1 order by a;
+delete from t1;
+
+
+--echo -- Load a static XML file with 'IGNORE num ROWS'
+load xml infile '../../std_data/loadxml.dat' into table t1
+rows identified by '<row>' ignore 4 rows;
+select * from t1 order by a;
+
+
+--echo -- Check 'mysqldump --xml' + 'LOAD XML' round trip
+--exec $MYSQL_DUMP --xml test t1 > "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" 2>&1
+delete from t1;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--eval load xml infile '$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml' into table t1 rows identified by '<row>';
+select * from t1 order by a;
+
+--echo --Check that default row tag is '<row>
+delete from t1;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+--eval load xml infile '$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml' into table t1;
+select * from t1 order by a;
+
+--echo -- Check that 'xml' is not a keyword
+select 1 as xml;
+
+
+#
+# Bug #42520 killing load .. infile Assertion failed: ! is_set(), file .\sql_error.cc, line 8
+#
+
+--disable_query_log
+delete from t1;
+insert into t1 values (1, '12345678900987654321'), (2, 'asdfghjkl;asdfghjkl;');
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+insert into t1 select * from t1;
+--exec $MYSQL_DUMP --xml test t1 > "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" 2>&1
+--enable_query_log
+
+connect (addconroot, localhost, root,,);
+connection addconroot;
+create table t2(fl text);
+--let $PSEUDO_THREAD_ID=`select @@pseudo_thread_id `
+
+--send LOAD XML LOCAL INFILE "$MYSQLTEST_VARDIR/tmp/loadxml-dump.xml" INTO TABLE t2 ROWS IDENTIFIED BY '<person>';
+
+sleep 3;
+
+
+connection default;
+--replace_column 1 # 3 localhost 6 #
+show processlist;
+
+--disable_query_log
+--eval kill $PSEUDO_THREAD_ID
+--enable_query_log
+
+disconnect addconroot;
+
+#
+# Clean up
+#
+remove_file $MYSQLTEST_VARDIR/tmp/loadxml-dump.xml;
+drop table t1;
+drop table t2;
+
+#
+# Bug #36750 LOAD XML doesn't understand new line (feed) characters in multi line text fields
+#
+
+create table t1 (
+ id int(11) not null,
+ text text,
+ primary key (id)
+) engine=MyISAM default charset=latin1;
+load xml infile '../../std_data/loadxml2.dat' into table t1;
+select * from t1;
+drop table t1;
+
diff --git a/mysql-test/t/locale.test b/mysql-test/t/locale.test
new file mode 100644
index 00000000000..a6291d9048d
--- /dev/null
+++ b/mysql-test/t/locale.test
@@ -0,0 +1,34 @@
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+--echo Start of 5.4 tests
+
+--echo #
+--echo # WL#4642 Greek locale for DAYNAME, MONTHNAME, DATE_FORMAT
+--echo #
+
+SET NAMES utf8;
+
+SET @@lc_time_names=109;
+SELECT @@lc_time_names;
+
+CREATE TABLE t1 (a DATE);
+INSERT INTO t1 VALUES
+('2006-01-01'),('2006-01-02'),('2006-01-03'),
+('2006-01-04'),('2006-01-05'),('2006-01-06'),('2006-01-07');
+SELECT a, date_format(a,'%a') as abday, dayname(a) as day FROM t1 ORDER BY a;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DATE);
+INSERT INTO t1 VALUES
+('2006-01-01'),('2006-02-01'),('2006-03-01'),
+('2006-04-01'),('2006-05-01'),('2006-06-01'),
+('2006-07-01'),('2006-08-01'),('2006-09-01'),
+('2006-10-01'),('2006-11-01'),('2006-12-01');
+SELECT a, date_format(a,'%b') as abmon, monthname(a) as mon FROM t1 ORDER BY a;
+
+SELECT format(123456.789, 3, 'el_GR');
+DROP TABLE t1;
+
+--echo End of 5.4 tests
diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test
index a10767579fb..a42dcfd618d 100644
--- a/mysql-test/t/metadata.test
+++ b/mysql-test/t/metadata.test
@@ -130,3 +130,60 @@ SELECT COALESCE(d, d), IFNULL(d, d), IF(i, d, d),
DROP TABLE t1;
--echo End of 5.0 tests
+
+# Verify that column metadata is correct for all possible data types.
+# Originally about BUG#42980 "Client doesn't set NUM_FLAG for DECIMAL"
+
+create table t1(
+# numeric types
+bool_col bool,
+boolean_col boolean,
+bit_col bit(5),
+tiny tinyint,
+tiny_uns tinyint unsigned,
+small smallint,
+small_uns smallint unsigned,
+medium mediumint,
+medium_uns mediumint unsigned,
+int_col int,
+int_col_uns int unsigned,
+big bigint,
+big_uns bigint unsigned,
+decimal_col decimal(10,5),
+# synonyms of DECIMAL
+numeric_col numeric(10),
+fixed_col fixed(10),
+dec_col dec(10),
+decimal_col_uns decimal(10,5) unsigned,
+fcol float,
+fcol_uns float unsigned,
+dcol double,
+double_precision_col double precision,
+dcol_uns double unsigned,
+# date/time types
+date_col date,
+time_col time,
+timestamp_col timestamp,
+year_col year,
+datetime_col datetime,
+# string types
+char_col char(5),
+varchar_col varchar(10),
+binary_col binary(10),
+varbinary_col varbinary(10),
+tinyblob_col tinyblob,
+blob_col blob,
+mediumblob_col mediumblob,
+longblob_col longblob,
+text_col text,
+mediumtext_col mediumtext,
+longtext_col longtext,
+enum_col enum("A","B","C"),
+set_col set("F","E","D")
+);
+
+--enable_metadata
+select * from t1;
+--disable_metadata
+
+drop table t1;
diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test
index 11e65be45fc..ea72cef5b62 100644
--- a/mysql-test/t/partition_pruning.test
+++ b/mysql-test/t/partition_pruning.test
@@ -1159,3 +1159,22 @@ INSERT INTO t1 VALUES ('2006-03-01 12:00:00');
-- echo must use p0 only:
explain partitions select * from t1 where recdate < '2006-01-01 00:00:00';
drop table t1;
+
+-- echo #
+-- echo # BUG#33730 Full table scan instead selected partitions for query more than 10 partitions
+-- echo #
+create table t0 (a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (a int)
+ partition by range(a+0) (
+ partition p0 values less than (64),
+ partition p1 values less than (128),
+ partition p2 values less than (255)
+);
+insert into t1 select A.a + 10*B.a from t0 A, t0 B;
+
+# this will use interval_via_walking
+explain partitions select * from t1 where a between 10 and 13;
+explain partitions select * from t1 where a between 10 and 10+33;
+
+drop table t0, t1;
diff --git a/mysql-test/t/partition_truncate.test b/mysql-test/t/partition_truncate.test
new file mode 100644
index 00000000000..93b9cf62d14
--- /dev/null
+++ b/mysql-test/t/partition_truncate.test
@@ -0,0 +1,26 @@
+#
+# Simple tests to verify truncate partition syntax
+#
+--source include/have_partition.inc
+--disable_warnings
+drop table if exists t1, t2, t3, t4;
+--enable_warnings
+
+create table t1 (a int)
+partition by list (a)
+(partition p1 values in (0));
+--error ER_WRONG_PARTITION_NAME
+alter table t1 truncate partition p1,p1;
+--error ER_WRONG_PARTITION_NAME
+alter table t1 truncate partition p0;
+drop table t1;
+
+create table t1 (a int)
+partition by list (a)
+subpartition by hash (a)
+subpartitions 1
+(partition p1 values in (1)
+ (subpartition sp1));
+--error ER_WRONG_PARTITION_NAME
+alter table t1 truncate partition sp1;
+drop table t1;
diff --git a/mysql-test/t/signal.test b/mysql-test/t/signal.test
new file mode 100644
index 00000000000..bdb6625ba32
--- /dev/null
+++ b/mysql-test/t/signal.test
@@ -0,0 +1,2685 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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
+
+# Tests for SIGNAL and RESIGNAL
+
+--echo #
+--echo # PART 1: syntax
+--echo #
+
+--echo #
+--echo # Test every new reserved and non reserved keywords
+--echo #
+
+--disable_warnings
+drop table if exists signal_non_reserved;
+--enable_warnings
+
+create table signal_non_reserved (
+ class_origin int,
+ subclass_origin int,
+ constraint_catalog int,
+ constraint_schema int,
+ constraint_name int,
+ catalog_name int,
+ schema_name int,
+ table_name int,
+ column_name int,
+ cursor_name int,
+ message_text int,
+ sqlcode int
+);
+
+drop table signal_non_reserved;
+
+--disable_warnings
+drop table if exists diag_non_reserved;
+--enable_warnings
+
+create table diag_non_reserved (
+ diagnostics int,
+ current int,
+ stacked int,
+ exception int
+);
+
+drop table diag_non_reserved;
+
+--disable_warnings
+drop table if exists diag_cond_non_reserved;
+--enable_warnings
+
+create table diag_cond_non_reserved (
+ condition_identifier int,
+ condition_number int,
+ condition_name int,
+ connection_name int,
+ message_length int,
+ message_octet_length int,
+ parameter_mode int,
+ parameter_name int,
+ parameter_ordinal_position int,
+ returned_sqlstate int,
+ routine_catalog int,
+ routine_name int,
+ routine_schema int,
+ server_name int,
+ specific_name int,
+ trigger_catalog int,
+ trigger_name int,
+ trigger_schema int
+);
+
+drop table diag_cond_non_reserved;
+
+--disable_warnings
+drop table if exists diag_stmt_non_reserved;
+--enable_warnings
+
+create table diag_stmt_non_reserved (
+ number int,
+ more int,
+ command_function int,
+ command_function_code int,
+ dynamic_function int,
+ dynamic_function_code int,
+ row_count int,
+ transactions_committed int,
+ transactions_rolled_back int,
+ transaction_active int
+);
+
+drop table diag_stmt_non_reserved;
+
+--disable_warnings
+drop table if exists test_reserved;
+--enable_warnings
+
+--error ER_PARSE_ERROR
+create table test_reserved (signal int);
+
+--error ER_PARSE_ERROR
+create table test_reserved (resignal int);
+
+--error ER_PARSE_ERROR
+create table test_reserved (condition int);
+
+--echo #
+--echo # Test the SIGNAL syntax
+--echo #
+
+--disable_warnings
+drop procedure if exists test_invalid;
+drop procedure if exists test_signal_syntax;
+drop function if exists test_signal_func;
+--enable_warnings
+
+delimiter $$;
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL;
+end $$
+
+--error ER_SP_COND_MISMATCH
+create procedure test_invalid()
+begin
+ SIGNAL foo;
+end $$
+
+--error ER_SIGNAL_BAD_CONDITION_TYPE
+create procedure test_invalid()
+begin
+ DECLARE foo CONDITION FOR 1234;
+ SIGNAL foo;
+end $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo;
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ SIGNAL SQLSTATE '23000';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ SIGNAL SQLSTATE VALUE '23000';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET CLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET SUBCLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET CONSTRAINT_CATALOG = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET CONSTRAINT_SCHEMA = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET CONSTRAINT_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET CATALOG_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET SCHEMA_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET TABLE_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET COLUMN_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET CURSOR_NAME = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MESSAGE_TEXT = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+--error ER_DUP_SIGNAL_SET
+create procedure test_invalid()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET CLASS_ORIGIN = 'foo', CLASS_ORIGIN = 'bar';
+end $$
+
+--error ER_DUP_SIGNAL_SET
+create procedure test_invalid()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MESSAGE_TEXT = 'foo', MESSAGE_TEXT = 'bar';
+end $$
+
+--error ER_DUP_SIGNAL_SET
+create procedure test_invalid()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 'foo', MYSQL_ERRNO = 'bar';
+end $$
+
+create procedure test_signal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET
+ CLASS_ORIGIN = 'foo',
+ SUBCLASS_ORIGIN = 'foo',
+ CONSTRAINT_CATALOG = 'foo',
+ CONSTRAINT_SCHEMA = 'foo',
+ CONSTRAINT_NAME = 'foo',
+ CATALOG_NAME = 'foo',
+ SCHEMA_NAME = 'foo',
+ TABLE_NAME = 'foo',
+ COLUMN_NAME = 'foo',
+ CURSOR_NAME = 'foo',
+ MESSAGE_TEXT = 'foo',
+ MYSQL_ERRNO = 'foo';
+end $$
+drop procedure test_signal_syntax $$
+
+--error ER_SP_BAD_SQLSTATE
+SIGNAL SQLSTATE '00000' $$
+
+--error ER_SP_BAD_SQLSTATE
+SIGNAL SQLSTATE '00001' $$
+
+--error ER_SP_BAD_SQLSTATE
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '00000';
+end $$
+
+--error ER_SP_BAD_SQLSTATE
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '00001';
+end $$
+
+--echo #
+--echo # Test conditions information that SIGNAL can not set
+--echo #
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET bla_bla = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET CONDITION_IDENTIFIER = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET CONDITION_NUMBER = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET CONNECTION_NAME = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET MESSAGE_LENGTH = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET MESSAGE_OCTET_LENGTH = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET PARAMETER_MODE = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET PARAMETER_NAME = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET PARAMETER_ORDINAL_POSITION = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET RETURNED_SQLSTATE = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET ROUTINE_CATALOG = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET ROUTINE_NAME = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET ROUTINE_SCHEMA = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET SERVER_NAME = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET SPECIFIC_NAME = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET TRIGGER_CATALOG = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET TRIGGER_NAME = 'foo';
+end $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ SIGNAL SQLSTATE '12345' SET TRIGGER_SCHEMA = 'foo';
+end $$
+
+delimiter ;$$
+
+--echo #
+--echo # Test the RESIGNAL syntax
+--echo #
+
+--disable_warnings
+drop procedure if exists test_invalid;
+drop procedure if exists test_resignal_syntax;
+--enable_warnings
+
+delimiter $$;
+
+--error ER_SP_COND_MISMATCH
+create procedure test_invalid()
+begin
+ RESIGNAL foo;
+end $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL;
+end $$
+drop procedure test_resignal_syntax $$
+
+--error ER_SIGNAL_BAD_CONDITION_TYPE
+create procedure test_invalid()
+begin
+ DECLARE foo CONDITION FOR 1234;
+ RESIGNAL foo;
+end $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo;
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SQLSTATE '23000';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SQLSTATE VALUE '23000';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET CLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET CLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET SUBCLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET SUBCLASS_ORIGIN = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET CONSTRAINT_CATALOG = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET CONSTRAINT_CATALOG = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET CONSTRAINT_SCHEMA = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET CONSTRAINT_SCHEMA = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET CONSTRAINT_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET CONSTRAINT_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET CATALOG_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET CATALOG_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET SCHEMA_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET SCHEMA_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET TABLE_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET TABLE_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET COLUMN_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET COLUMN_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET CURSOR_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET CURSOR_NAME = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET MESSAGE_TEXT = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET MESSAGE_TEXT = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ RESIGNAL SET MYSQL_ERRNO = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET MYSQL_ERRNO = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+--error ER_DUP_SIGNAL_SET
+create procedure test_invalid()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET CLASS_ORIGIN = 'foo', CLASS_ORIGIN = 'bar';
+end $$
+
+--error ER_DUP_SIGNAL_SET
+create procedure test_invalid()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET MESSAGE_TEXT = 'foo', MESSAGE_TEXT = 'bar';
+end $$
+
+--error ER_DUP_SIGNAL_SET
+create procedure test_invalid()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET MYSQL_ERRNO = 'foo', MYSQL_ERRNO = 'bar';
+end $$
+
+create procedure test_resignal_syntax()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ RESIGNAL foo SET
+ CLASS_ORIGIN = 'foo',
+ SUBCLASS_ORIGIN = 'foo',
+ CONSTRAINT_CATALOG = 'foo',
+ CONSTRAINT_SCHEMA = 'foo',
+ CONSTRAINT_NAME = 'foo',
+ CATALOG_NAME = 'foo',
+ SCHEMA_NAME = 'foo',
+ TABLE_NAME = 'foo',
+ COLUMN_NAME = 'foo',
+ CURSOR_NAME = 'foo',
+ MESSAGE_TEXT = 'foo';
+end $$
+drop procedure test_resignal_syntax $$
+
+--error ER_SP_BAD_SQLSTATE
+create procedure test_invalid()
+begin
+ RESIGNAL SQLSTATE '00000';
+end $$
+
+--error ER_SP_BAD_SQLSTATE
+create procedure test_invalid()
+begin
+ RESIGNAL SQLSTATE '00001';
+end $$
+
+delimiter ;$$
+
+--echo #
+--echo # PART 2: non preparable statements
+--echo #
+
+--error ER_UNSUPPORTED_PS
+prepare stmt from 'SIGNAL SQLSTATE \'23000\'';
+
+--error ER_UNSUPPORTED_PS
+prepare stmt from 'RESIGNAL SQLSTATE \'23000\'';
+
+--echo #
+--echo # PART 3: runtime execution
+--echo #
+
+--disable_warnings
+drop procedure if exists test_signal;
+drop procedure if exists test_resignal;
+drop table if exists t_warn;
+drop table if exists t_cursor;
+--enable_warnings
+
+# Helper tables
+create table t_warn(a integer(2));
+create table t_cursor(a integer);
+
+--echo #
+--echo # SIGNAL can also appear in a query
+--echo #
+
+--error ER_SP_COND_MISMATCH
+SIGNAL foo;
+
+SIGNAL SQLSTATE '01000';
+
+--error ER_SIGNAL_NOT_FOUND
+SIGNAL SQLSTATE '02000';
+
+--error ER_SIGNAL_EXCEPTION
+SIGNAL SQLSTATE '23000';
+
+--error ER_SIGNAL_EXCEPTION
+SIGNAL SQLSTATE VALUE '23000';
+
+--error ER_WRONG_VALUE_FOR_VAR
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 65536;
+
+--error ER_WRONG_VALUE_FOR_VAR
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 99999;
+
+--error ER_WRONG_VALUE_FOR_VAR
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 4294967295;
+
+--error ER_WRONG_VALUE_FOR_VAR
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 0;
+
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = -1;
+
+--error 65535
+SIGNAL SQLSTATE 'HY000' SET MYSQL_ERRNO = 65535;
+
+--echo #
+--echo # RESIGNAL can also appear in a query
+--echo #
+
+--error ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER
+RESIGNAL;
+
+--error ER_SP_COND_MISMATCH
+RESIGNAL foo;
+
+--error ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER
+RESIGNAL SQLSTATE '12345';
+
+--error ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER
+RESIGNAL SQLSTATE VALUE '12345';
+
+--echo #
+--echo # Different kind of SIGNAL conditions
+--echo #
+
+delimiter $$;
+
+create procedure test_signal()
+begin
+ # max range
+ DECLARE foo CONDITION FOR SQLSTATE 'AABBB';
+ SIGNAL foo SET MYSQL_ERRNO = 65535;
+end $$
+
+--error 65535
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # max range
+ DECLARE foo CONDITION FOR SQLSTATE 'AABBB';
+ SIGNAL foo SET MYSQL_ERRNO = 65536;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Error
+ DECLARE foo CONDITION FOR SQLSTATE '99999';
+ SIGNAL foo SET MYSQL_ERRNO = 9999;
+end $$
+
+--error 9999
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # warning
+ DECLARE too_few_records CONDITION FOR SQLSTATE '01000';
+ SIGNAL too_few_records SET MYSQL_ERRNO = 1261;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Not found
+ DECLARE sp_fetch_no_data CONDITION FOR SQLSTATE '02000';
+ SIGNAL sp_fetch_no_data SET MYSQL_ERRNO = 1329;
+end $$
+
+--error ER_SP_FETCH_NO_DATA
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Error
+ DECLARE sp_cursor_already_open CONDITION FOR SQLSTATE '24000';
+ SIGNAL sp_cursor_already_open SET MYSQL_ERRNO = 1325;
+end $$
+
+--error ER_SP_CURSOR_ALREADY_OPEN
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Severe error
+ DECLARE lock_deadlock CONDITION FOR SQLSTATE '40001';
+ SIGNAL lock_deadlock SET MYSQL_ERRNO = 1213;
+end $$
+
+--error ER_LOCK_DEADLOCK
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Unknown -> error
+ DECLARE foo CONDITION FOR SQLSTATE "99999";
+ SIGNAL foo;
+end $$
+
+--error ER_SIGNAL_EXCEPTION
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # warning, no subclass
+ DECLARE warn CONDITION FOR SQLSTATE "01000";
+ SIGNAL warn;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # warning, with subclass
+ DECLARE warn CONDITION FOR SQLSTATE "01123";
+ SIGNAL warn;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Not found, no subclass
+ DECLARE not_found CONDITION FOR SQLSTATE "02000";
+ SIGNAL not_found;
+end $$
+
+--error ER_SIGNAL_NOT_FOUND
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Not found, with subclass
+ DECLARE not_found CONDITION FOR SQLSTATE "02XXX";
+ SIGNAL not_found;
+end $$
+
+--error ER_SIGNAL_NOT_FOUND
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Error, no subclass
+ DECLARE error CONDITION FOR SQLSTATE "12000";
+ SIGNAL error;
+end $$
+
+--error ER_SIGNAL_EXCEPTION
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Error, with subclass
+ DECLARE error CONDITION FOR SQLSTATE "12ABC";
+ SIGNAL error;
+end $$
+
+--error ER_SIGNAL_EXCEPTION
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Severe error, no subclass
+ DECLARE error CONDITION FOR SQLSTATE "40000";
+ SIGNAL error;
+end $$
+
+--error ER_SIGNAL_EXCEPTION
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ # Severe error, with subclass
+ DECLARE error CONDITION FOR SQLSTATE "40001";
+ SIGNAL error;
+end $$
+
+--error ER_SIGNAL_EXCEPTION
+call test_signal() $$
+drop procedure test_signal $$
+
+--echo #
+--echo # Test the scope of condition
+--echo #
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '99999';
+ begin
+ DECLARE foo CONDITION FOR 8888;
+ end;
+ SIGNAL foo SET MYSQL_ERRNO=9999; /* outer */
+end $$
+
+--error 9999
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR 9999;
+ begin
+ DECLARE foo CONDITION FOR SQLSTATE '88888';
+ SIGNAL foo SET MYSQL_ERRNO=8888; /* inner */
+ end;
+end $$
+
+--error 8888
+call test_signal() $$
+drop procedure test_signal $$
+
+--echo #
+--echo # Test SET MYSQL_ERRNO
+--echo #
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '99999';
+ SIGNAL foo SET MYSQL_ERRNO = 1111;
+end $$
+
+--error 1111
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01000";
+ SIGNAL warn SET MYSQL_ERRNO = 1111;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02000";
+ SIGNAL not_found SET MYSQL_ERRNO = 1111;
+end $$
+
+--error 1111
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "55000";
+ SIGNAL error SET MYSQL_ERRNO = 1111;
+end $$
+
+--error 1111
+call test_signal() $$
+drop procedure test_signal $$
+
+--echo #
+--echo # Test SET MESSAGE_TEXT
+--echo #
+
+--error ER_SIGNAL_EXCEPTION
+SIGNAL SQLSTATE '77777' SET MESSAGE_TEXT='' $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '77777';
+ SIGNAL foo SET
+ MESSAGE_TEXT = "",
+ MYSQL_ERRNO=5678;
+end $$
+
+--error 5678
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '99999';
+ SIGNAL foo SET
+ MESSAGE_TEXT = "Something bad happened",
+ MYSQL_ERRNO=9999;
+end $$
+
+--error 9999
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01000";
+ SIGNAL warn SET MESSAGE_TEXT = "Something bad happened";
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02000";
+ SIGNAL not_found SET MESSAGE_TEXT = "Something bad happened";
+end $$
+
+--error ER_SIGNAL_NOT_FOUND
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "55000";
+ SIGNAL error SET MESSAGE_TEXT = "Something bad happened";
+end $$
+
+--error ER_SIGNAL_EXCEPTION
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE something CONDITION FOR SQLSTATE "01000";
+ SIGNAL something SET MESSAGE_TEXT = _utf8 "This is a UTF8 text";
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE something CONDITION FOR SQLSTATE "01000";
+ SIGNAL something SET MESSAGE_TEXT = "";
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01111";
+ SIGNAL warn SET MESSAGE_TEXT = "á a";
+end $$
+
+call test_signal() $$
+show warnings $$
+drop procedure test_signal $$
+
+--echo #
+--echo # Test SET complex expressions
+--echo #
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ MYSQL_ERRNO = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ CLASS_ORIGIN = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ SUBCLASS_ORIGIN = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ CONSTRAINT_CATALOG = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ CONSTRAINT_SCHEMA = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ CONSTRAINT_NAME = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ CATALOG_NAME = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ SCHEMA_NAME = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ TABLE_NAME = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ COLUMN_NAME = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ CURSOR_NAME = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE '99999';
+ SIGNAL error SET
+ MESSAGE_TEXT = NULL;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE something CONDITION FOR SQLSTATE '99999';
+ DECLARE message_text VARCHAR(64) DEFAULT "Local string variable";
+ DECLARE sqlcode INTEGER DEFAULT 1234;
+
+ SIGNAL something SET
+ MESSAGE_TEXT = message_text,
+ MYSQL_ERRNO = sqlcode;
+end $$
+
+--error 1234
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal(message_text VARCHAR(64), sqlcode INTEGER)
+begin
+ DECLARE something CONDITION FOR SQLSTATE "12345";
+
+ SIGNAL something SET
+ MESSAGE_TEXT = message_text,
+ MYSQL_ERRNO = sqlcode;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal("Parameter string", NULL) $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal(NULL, 1234) $$
+
+--error 5678
+call test_signal("Parameter string", 5678) $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE something CONDITION FOR SQLSTATE "AABBB";
+
+ SIGNAL something SET
+ MESSAGE_TEXT = @message_text,
+ MYSQL_ERRNO = @sqlcode;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+
+set @sqlcode= 12 $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+
+set @message_text= "User variable" $$
+
+--error 12
+call test_signal() $$
+drop procedure test_signal $$
+
+--error ER_PARSE_ERROR
+create procedure test_invalid()
+begin
+ DECLARE something CONDITION FOR SQLSTATE "AABBB";
+
+ SIGNAL something SET
+ MESSAGE_TEXT = @message_text := 'illegal',
+ MYSQL_ERRNO = @sqlcode := 1234;
+end $$
+
+create procedure test_signal()
+begin
+ DECLARE aaa VARCHAR(64);
+ DECLARE bbb VARCHAR(64);
+ DECLARE ccc VARCHAR(64);
+ DECLARE ddd VARCHAR(64);
+ DECLARE eee VARCHAR(64);
+ DECLARE fff VARCHAR(64);
+ DECLARE ggg VARCHAR(64);
+ DECLARE hhh VARCHAR(64);
+ DECLARE iii VARCHAR(64);
+ DECLARE jjj VARCHAR(64);
+ DECLARE kkk VARCHAR(64);
+
+ DECLARE warn CONDITION FOR SQLSTATE "01234";
+
+ set aaa= repeat("A", 64);
+ set bbb= repeat("B", 64);
+ set ccc= repeat("C", 64);
+ set ddd= repeat("D", 64);
+ set eee= repeat("E", 64);
+ set fff= repeat("F", 64);
+ set ggg= repeat("G", 64);
+ set hhh= repeat("H", 64);
+ set iii= repeat("I", 64);
+ set jjj= repeat("J", 64);
+ set kkk= repeat("K", 64);
+
+ SIGNAL warn SET
+ CLASS_ORIGIN = aaa,
+ SUBCLASS_ORIGIN = bbb,
+ CONSTRAINT_CATALOG = ccc,
+ CONSTRAINT_SCHEMA = ddd,
+ CONSTRAINT_NAME = eee,
+ CATALOG_NAME = fff,
+ SCHEMA_NAME = ggg,
+ TABLE_NAME = hhh,
+ COLUMN_NAME = iii,
+ CURSOR_NAME = jjj,
+ MESSAGE_TEXT = kkk,
+ MYSQL_ERRNO = 65535;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01234";
+
+ SIGNAL warn SET
+ MYSQL_ERRNO = 999999999999999999999999999999999999999999999999999;
+end $$
+
+--error ER_WRONG_VALUE_FOR_VAR
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE aaax VARCHAR(65);
+ DECLARE bbbx VARCHAR(65);
+ DECLARE cccx VARCHAR(65);
+ DECLARE dddx VARCHAR(65);
+ DECLARE eeex VARCHAR(65);
+ DECLARE fffx VARCHAR(65);
+ DECLARE gggx VARCHAR(65);
+ DECLARE hhhx VARCHAR(65);
+ DECLARE iiix VARCHAR(65);
+ DECLARE jjjx VARCHAR(65);
+ DECLARE kkkx VARCHAR(65);
+ DECLARE lllx VARCHAR(129);
+
+ DECLARE warn CONDITION FOR SQLSTATE "01234";
+
+ set aaax= concat(repeat("A", 64), "X");
+ set bbbx= concat(repeat("B", 64), "X");
+ set cccx= concat(repeat("C", 64), "X");
+ set dddx= concat(repeat("D", 64), "X");
+ set eeex= concat(repeat("E", 64), "X");
+ set fffx= concat(repeat("F", 64), "X");
+ set gggx= concat(repeat("G", 64), "X");
+ set hhhx= concat(repeat("H", 64), "X");
+ set iiix= concat(repeat("I", 64), "X");
+ set jjjx= concat(repeat("J", 64), "X");
+ set kkkx= concat(repeat("K", 64), "X");
+ set lllx= concat(repeat("1", 100),
+ repeat("2", 20),
+ repeat("8", 8),
+ "X");
+
+ SIGNAL warn SET
+ CLASS_ORIGIN = aaax,
+ SUBCLASS_ORIGIN = bbbx,
+ CONSTRAINT_CATALOG = cccx,
+ CONSTRAINT_SCHEMA = dddx,
+ CONSTRAINT_NAME = eeex,
+ CATALOG_NAME = fffx,
+ SCHEMA_NAME = gggx,
+ TABLE_NAME = hhhx,
+ COLUMN_NAME = iiix,
+ CURSOR_NAME = jjjx,
+ MESSAGE_TEXT = lllx,
+ MYSQL_ERRNO = 10000;
+end $$
+
+#NOTE: the warning text for ER_TRUNCATED_WRONG_VALUE contains
+# value: '%-.128s', so the warning printed truncates the value too,
+# which affects MESSAGE_TEXT (the X is missing)
+
+call test_signal() $$
+drop procedure test_signal $$
+
+# Test that HANDLER can catch conditions raised by SIGNAL
+
+create procedure test_signal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01234";
+ DECLARE CONTINUE HANDLER for SQLSTATE "01234"
+ begin
+ select "Caught by SQLSTATE";
+ end;
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "Raising a warning",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01234";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "Caught by number";
+ end;
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "Raising a warning",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01234";
+ DECLARE CONTINUE HANDLER for SQLWARNING
+ begin
+ select "Caught by SQLWARNING";
+ end;
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "Raising a warning",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+ DECLARE CONTINUE HANDLER for SQLSTATE "02ABC"
+ begin
+ select "Caught by SQLSTATE";
+ end;
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "Raising a not found",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "Caught by number";
+ end;
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "Raising a not found",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+ DECLARE CONTINUE HANDLER for NOT FOUND
+ begin
+ select "Caught by NOT FOUND";
+ end;
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "Raising a not found",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "55555";
+ DECLARE CONTINUE HANDLER for SQLSTATE "55555"
+ begin
+ select "Caught by SQLSTATE";
+ end;
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "Raising an error",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "55555";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "Caught by number";
+ end;
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "Raising an error",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "55555";
+ DECLARE CONTINUE HANDLER for SQLEXCEPTION
+ begin
+ select "Caught by SQLEXCEPTION";
+ end;
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "Raising an error",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_signal() $$
+drop procedure test_signal $$
+
+--echo #
+--echo # Test where SIGNAL can be used
+--echo #
+
+create function test_signal_func() returns integer
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01XXX";
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "This function SIGNAL a warning",
+ MYSQL_ERRNO = 1012;
+
+ return 5;
+end $$
+
+select test_signal_func() $$
+drop function test_signal_func $$
+
+create function test_signal_func() returns integer
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02XXX";
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "This function SIGNAL not found",
+ MYSQL_ERRNO = 1012;
+
+ return 5;
+end $$
+
+--error 1012
+select test_signal_func() $$
+drop function test_signal_func $$
+
+create function test_signal_func() returns integer
+begin
+ DECLARE error CONDITION FOR SQLSTATE "50000";
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "This function SIGNAL an error",
+ MYSQL_ERRNO = 1012;
+
+ return 5;
+end $$
+
+--error 1012
+select test_signal_func() $$
+drop function test_signal_func $$
+
+--disable_warnings
+drop table if exists t1 $$
+--enable_warnings
+
+create table t1 (a integer) $$
+
+create trigger t1_ai after insert on t1 for each row
+begin
+ DECLARE msg VARCHAR(128);
+ DECLARE warn CONDITION FOR SQLSTATE "01XXX";
+
+ set msg= concat("This trigger SIGNAL a warning, a=", NEW.a);
+ SIGNAL warn SET
+ MESSAGE_TEXT = msg,
+ MYSQL_ERRNO = 1012;
+end $$
+
+insert into t1 values (1), (2) $$
+
+drop trigger t1_ai $$
+
+create trigger t1_ai after insert on t1 for each row
+begin
+ DECLARE msg VARCHAR(128);
+ DECLARE not_found CONDITION FOR SQLSTATE "02XXX";
+
+ set msg= concat("This trigger SIGNAL a not found, a=", NEW.a);
+ SIGNAL not_found SET
+ MESSAGE_TEXT = msg,
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 1012
+insert into t1 values (3), (4) $$
+
+drop trigger t1_ai $$
+
+create trigger t1_ai after insert on t1 for each row
+begin
+ DECLARE msg VARCHAR(128);
+ DECLARE error CONDITION FOR SQLSTATE "03XXX";
+
+ set msg= concat("This trigger SIGNAL an error, a=", NEW.a);
+ SIGNAL error SET
+ MESSAGE_TEXT = msg,
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 1012
+insert into t1 values (5), (6) $$
+
+drop table t1 $$
+
+create table t1 (errno integer, msg varchar(128)) $$
+
+create trigger t1_ai after insert on t1 for each row
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01XXX";
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = NEW.msg,
+ MYSQL_ERRNO = NEW.errno;
+end $$
+
+insert into t1 set errno=1012, msg='Warning message 1 in trigger' $$
+insert into t1 set errno=1013, msg='Warning message 2 in trigger' $$
+
+drop table t1 $$
+
+--disable_warnings
+drop table if exists t1 $$
+drop procedure if exists p1 $$
+drop function if exists f1 $$
+--enable_warnings
+
+create table t1 (s1 int) $$
+insert into t1 values (1) $$
+
+create procedure p1()
+begin
+ declare a int;
+ declare c cursor for select f1() from t1;
+ declare continue handler for sqlstate '03000'
+ select "caught 03000";
+ declare continue handler for 1326
+ select "caught cursor is not open";
+
+ select "Before open";
+ open c;
+ select "Before fetch";
+ fetch c into a;
+ select "Before close";
+ close c;
+end $$
+
+create function f1() returns int
+begin
+ signal sqlstate '03000';
+ return 5;
+end $$
+
+## FIXME : MEMORY plugin warning, valgrind leak, bug#36518
+## call p1() $$
+
+drop table t1 $$
+drop procedure p1 $$
+drop function f1 $$
+
+--echo #
+--echo # Test the RESIGNAL runtime
+--echo #
+
+# 6 tests:
+# {Signaled warning, Signaled Not Found, Signaled Error,
+# warning, not found, error} --> RESIGNAL
+
+create procedure test_resignal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01234";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "Raising a warning",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02222";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "Raising a not found",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 1012
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "55555";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "Raising an error",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 1012
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlwarning
+ begin
+ select "before RESIGNAL";
+ RESIGNAL;
+ select "after RESIGNAL";
+ end;
+
+ insert into t_warn set a= 9999999999999999;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE x integer;
+ DECLARE c cursor for select * from t_cursor;
+ DECLARE CONTINUE HANDLER for not found
+ begin
+ select "before RESIGNAL";
+ RESIGNAL;
+ select "after RESIGNAL";
+ end;
+
+ open c;
+ fetch c into x;
+ close c;
+end $$
+
+--error ER_SP_FETCH_NO_DATA
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlexception
+ begin
+ select "before RESIGNAL";
+ RESIGNAL;
+ select "after RESIGNAL";
+ end;
+
+ drop table no_such_table;
+end $$
+
+--error ER_BAD_TABLE_ERROR
+call test_resignal() $$
+drop procedure test_resignal $$
+
+# 6 tests:
+# {Signaled warning, Signaled Not Found, Signaled Error,
+# warning, not found, error} --> RESIGNAL SET ...
+
+create procedure test_resignal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01234";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SET
+ MESSAGE_TEXT = "RESIGNAL of a warning",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "Raising a warning",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02111";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SET
+ MESSAGE_TEXT = "RESIGNAL of a not found",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "Raising a not found",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 5555
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "33333";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SET
+ MESSAGE_TEXT = "RESIGNAL of an error",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "Raising an error",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 5555
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlwarning
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SET
+ MESSAGE_TEXT = "RESIGNAL of a warning",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ insert into t_warn set a= 9999999999999999;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE x integer;
+ DECLARE c cursor for select * from t_cursor;
+ DECLARE CONTINUE HANDLER for not found
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SET
+ MESSAGE_TEXT = "RESIGNAL of not found",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ open c;
+ fetch c into x;
+ close c;
+end $$
+
+--error 5555
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlexception
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SET
+ MESSAGE_TEXT = "RESIGNAL of an error",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ drop table no_such_table;
+end $$
+
+--error 5555
+call test_resignal() $$
+drop procedure test_resignal $$
+
+#########################################################
+
+# 3 tests:
+# {Signaled warning}
+# --> RESIGNAL SQLSTATE {warning, not found, error} SET ...
+
+create procedure test_resignal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01111";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "01222" SET
+ MESSAGE_TEXT = "RESIGNAL to warning",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "Raising a warning",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01111";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "02222" SET
+ MESSAGE_TEXT = "RESIGNAL to not found",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "Raising a warning",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE warn CONDITION FOR SQLSTATE "01111";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "33333" SET
+ MESSAGE_TEXT = "RESIGNAL to error",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL warn SET
+ MESSAGE_TEXT = "Raising a warning",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+# 3 tests:
+# {Signaled not found}
+# --> RESIGNAL SQLSTATE {warning, not found, error} SET ...
+
+create procedure test_resignal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "01222" SET
+ MESSAGE_TEXT = "RESIGNAL to warning",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "Raising a not found",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "02222" SET
+ MESSAGE_TEXT = "RESIGNAL to not found",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "Raising a not found",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE not_found CONDITION FOR SQLSTATE "02ABC";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "33333" SET
+ MESSAGE_TEXT = "RESIGNAL to error",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL not_found SET
+ MESSAGE_TEXT = "Raising a not found",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+# 3 tests:
+# {Signaled error}
+# --> RESIGNAL SQLSTATE {warning, not found, error} SET ...
+
+create procedure test_resignal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "AAAAA";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "01222" SET
+ MESSAGE_TEXT = "RESIGNAL to warning",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "Raising an error",
+ MYSQL_ERRNO = 1012;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "AAAAA";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "02222" SET
+ MESSAGE_TEXT = "RESIGNAL to not found",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "Raising an error",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE error CONDITION FOR SQLSTATE "AAAAA";
+ DECLARE CONTINUE HANDLER for 1012
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "33333" SET
+ MESSAGE_TEXT = "RESIGNAL to error",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ SIGNAL error SET
+ MESSAGE_TEXT = "Raising an error",
+ MYSQL_ERRNO = 1012;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+# 3 tests:
+# {warning}
+# --> RESIGNAL SQLSTATE {warning, not found, error} SET ...
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlwarning
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "01111" SET
+ MESSAGE_TEXT = "RESIGNAL to a warning",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ insert into t_warn set a= 9999999999999999;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlwarning
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "02444" SET
+ MESSAGE_TEXT = "RESIGNAL to a not found",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ insert into t_warn set a= 9999999999999999;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlwarning
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "44444" SET
+ MESSAGE_TEXT = "RESIGNAL to an error",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ insert into t_warn set a= 9999999999999999;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+# 3 tests:
+# {not found}
+# --> RESIGNAL SQLSTATE {warning, not found, error} SET ...
+
+create procedure test_resignal()
+begin
+ DECLARE x integer;
+ DECLARE c cursor for select * from t_cursor;
+ DECLARE CONTINUE HANDLER for not found
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "01111" SET
+ MESSAGE_TEXT = "RESIGNAL to a warning",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ open c;
+ fetch c into x;
+ close c;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE x integer;
+ DECLARE c cursor for select * from t_cursor;
+ DECLARE CONTINUE HANDLER for not found
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "02444" SET
+ MESSAGE_TEXT = "RESIGNAL to a not found",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ open c;
+ fetch c into x;
+ close c;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE x integer;
+ DECLARE c cursor for select * from t_cursor;
+ DECLARE CONTINUE HANDLER for not found
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "44444" SET
+ MESSAGE_TEXT = "RESIGNAL to an error",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ open c;
+ fetch c into x;
+ close c;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+# 3 tests:
+# {error}
+# --> RESIGNAL SQLSTATE {warning, not found, error} SET ...
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlexception
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "01111" SET
+ MESSAGE_TEXT = "RESIGNAL to a warning",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ drop table no_such_table;
+end $$
+
+call test_resignal() $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlexception
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "02444" SET
+ MESSAGE_TEXT = "RESIGNAL to a not found",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ drop table no_such_table;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+create procedure test_resignal()
+begin
+ DECLARE CONTINUE HANDLER for sqlexception
+ begin
+ select "before RESIGNAL";
+ RESIGNAL SQLSTATE "44444" SET
+ MESSAGE_TEXT = "RESIGNAL to an error",
+ MYSQL_ERRNO = 5555 ;
+ select "after RESIGNAL";
+ end;
+
+ drop table no_such_table;
+end $$
+
+--error 5555
+call test_resignal() $$
+show warnings $$
+drop procedure test_resignal $$
+
+--echo #
+--echo # More complex cases
+--echo #
+
+--disable_warnings
+drop procedure if exists peter_p1 $$
+drop procedure if exists peter_p2 $$
+--enable_warnings
+
+CREATE PROCEDURE peter_p1 ()
+BEGIN
+ DECLARE x CONDITION FOR 1231;
+ DECLARE EXIT HANDLER FOR x
+ BEGIN
+ SELECT '2';
+ RESIGNAL SET MYSQL_ERRNO = 9999;
+ END;
+
+ BEGIN
+ DECLARE EXIT HANDLER FOR x
+ BEGIN
+ SELECT '1';
+ RESIGNAL SET SCHEMA_NAME = 'test';
+ END;
+ SET @@sql_mode=NULL;
+ END;
+END
+$$
+
+CREATE PROCEDURE peter_p2 ()
+BEGIN
+ DECLARE x CONDITION for 9999;
+ DECLARE EXIT HANDLER FOR x
+ BEGIN
+ SELECT '3';
+ RESIGNAL SET MESSAGE_TEXT = 'Hi, I am a useless error message';
+ END;
+ CALL peter_p1();
+END
+$$
+
+#
+# Here, RESIGNAL only modifies the condition caught,
+# so there is only 1 condition at the end
+# The final SQLSTATE is 42000 (it comes from the error 1231),
+# since the condition attributes are preserved.
+#
+--error 9999
+CALL peter_p2() $$
+show warnings $$
+
+drop procedure peter_p1 $$
+drop procedure peter_p2 $$
+
+CREATE PROCEDURE peter_p1 ()
+BEGIN
+ DECLARE x CONDITION FOR SQLSTATE '42000';
+ DECLARE EXIT HANDLER FOR x
+ BEGIN
+ SELECT '2';
+ RESIGNAL x SET MYSQL_ERRNO = 9999;
+ END;
+
+ BEGIN
+ DECLARE EXIT HANDLER FOR x
+ BEGIN
+ SELECT '1';
+ RESIGNAL x SET
+ SCHEMA_NAME = 'test',
+ MYSQL_ERRNO= 1231;
+ END;
+ /* Raises ER_WRONG_VALUE_FOR_VAR : 1231, SQLSTATE 42000 */
+ SET @@sql_mode=NULL;
+ END;
+END
+$$
+
+CREATE PROCEDURE peter_p2 ()
+BEGIN
+ DECLARE x CONDITION for SQLSTATE '42000';
+ DECLARE EXIT HANDLER FOR x
+ BEGIN
+ SELECT '3';
+ RESIGNAL x SET
+ MESSAGE_TEXT = 'Hi, I am a useless error message',
+ MYSQL_ERRNO = 9999;
+ END;
+ CALL peter_p1();
+END
+$$
+
+#
+# Here, "RESIGNAL <condition>" create a new condition in the diagnostics
+# area, so that there are 4 conditions at the end.
+#
+--error 9999
+CALL peter_p2() $$
+show warnings $$
+
+drop procedure peter_p1 $$
+drop procedure peter_p2 $$
+
+#
+# Test the value of MESSAGE_TEXT in RESIGNAL when no SET MESSAGE_TEXT clause
+# is provided (the expected result is the text from the SIGNALed condition)
+#
+
+drop procedure if exists peter_p3 $$
+
+create procedure peter_p3()
+begin
+ declare continue handler for sqlexception
+ resignal sqlstate '99002' set mysql_errno = 2;
+
+ signal sqlstate '99001' set mysql_errno = 1, message_text = "Original";
+end $$
+
+--error 2
+call peter_p3() $$
+
+# Expecting 2 conditions, both with the text "Original"
+show warnings $$
+
+drop procedure peter_p3 $$
+
+delimiter ;$$
+
+drop table t_warn;
+drop table t_cursor;
+
+--echo #
+--echo # Miscelaneous test cases
+--echo #
+
+delimiter $$;
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 0x12; /* 18 */
+end $$
+
+-- error 18
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 0b00010010; /* 18 */
+end $$
+
+-- error 18
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = '65'; /* 65 */
+end $$
+
+-- error 65
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 'A'; /* illegal */
+end $$
+
+-- error ER_WRONG_VALUE_FOR_VAR
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = "65"; /* 65 */
+end $$
+
+-- error 65
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = "A"; /* illegal */
+end $$
+
+-- error ER_WRONG_VALUE_FOR_VAR
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = `65`; /* illegal */
+end $$
+
+-- error ER_BAD_FIELD_ERROR
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = `A`; /* illegal */
+end $$
+
+-- error ER_BAD_FIELD_ERROR
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 3.141592; /* 3 */
+end $$
+
+-- error 3
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 1000,
+ MESSAGE_TEXT= 0x41; /* A */
+end $$
+
+-- error 1000
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 1000,
+ MESSAGE_TEXT= 0b01000001; /* A */
+end $$
+
+-- error 1000
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 1000,
+ MESSAGE_TEXT = "Hello";
+end $$
+
+-- error 1000
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 1000,
+ MESSAGE_TEXT = 'Hello';
+end $$
+
+-- error 1000
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 1000,
+ MESSAGE_TEXT = `Hello`;
+end $$
+
+-- error ER_BAD_FIELD_ERROR
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL foo SET MYSQL_ERRNO = 1000,
+ MESSAGE_TEXT = 65.4321;
+end $$
+
+-- error 1000
+call test_signal $$
+drop procedure test_signal $$
+
+-- error ER_PARSE_ERROR
+create procedure test_signal()
+begin
+ DECLARE céèçà foo CONDITION FOR SQLSTATE '12345';
+ SIGNAL céèçà SET MYSQL_ERRNO = 1000;
+end $$
+
+-- error ER_PARSE_ERROR
+create procedure test_signal()
+begin
+ DECLARE "céèçà" CONDITION FOR SQLSTATE '12345';
+ SIGNAL "céèçà" SET MYSQL_ERRNO = 1000;
+end $$
+
+-- error ER_PARSE_ERROR
+create procedure test_signal()
+begin
+ DECLARE 'céèçà' CONDITION FOR SQLSTATE '12345';
+ SIGNAL 'céèçà' SET MYSQL_ERRNO = 1000;
+end $$
+
+create procedure test_signal()
+begin
+ DECLARE `céèçà` CONDITION FOR SQLSTATE '12345';
+ SIGNAL `céèçà` SET MYSQL_ERRNO = 1000;
+end $$
+
+-- error 1000
+call test_signal $$
+drop procedure test_signal $$
+
+create procedure test_signal()
+begin
+ SIGNAL SQLSTATE '77777' SET MYSQL_ERRNO = 1000, MESSAGE_TEXT='ÃÂÃÅÄ';
+end $$
+
+# Commented until WL#751 is implemented in this version
+# -- error 1000
+# call test_signal $$
+drop procedure test_signal $$
+
+delimiter ; $$
+
diff --git a/mysql-test/t/signal_code.test b/mysql-test/t/signal_code.test
new file mode 100644
index 00000000000..d2f65647c81
--- /dev/null
+++ b/mysql-test/t/signal_code.test
@@ -0,0 +1,57 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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
+
+# Tests for SIGNAL and RESIGNAL
+
+-- source include/have_debug.inc
+
+use test;
+
+--disable_warnings
+drop procedure if exists signal_proc;
+drop function if exists signal_func;
+--enable_warnings
+
+delimiter $$;
+
+create procedure signal_proc()
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+
+ SIGNAL foo;
+ SIGNAL foo SET MESSAGE_TEXT = "This is an error message";
+ RESIGNAL foo;
+ RESIGNAL foo SET MESSAGE_TEXT = "This is an error message";
+end $$
+
+create function signal_func() returns int
+begin
+ DECLARE foo CONDITION FOR SQLSTATE '12345';
+
+ SIGNAL foo;
+ SIGNAL foo SET MESSAGE_TEXT = "This is an error message";
+ RESIGNAL foo;
+ RESIGNAL foo SET MESSAGE_TEXT = "This is an error message";
+ return 0;
+end $$
+
+delimiter ;$$
+
+show procedure code signal_proc;
+drop procedure signal_proc;
+
+show function code signal_func;
+drop function signal_func;
+
diff --git a/mysql-test/t/signal_demo1.test b/mysql-test/t/signal_demo1.test
new file mode 100644
index 00000000000..5de847ba0ba
--- /dev/null
+++ b/mysql-test/t/signal_demo1.test
@@ -0,0 +1,345 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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
+
+#
+# Demonstrate how SIGNAL can be used to enforce integrity constraints.
+#
+
+# Naming:
+# - PO: Purchase Order
+# - AB: Address Book
+# - IN: Inventory
+
+# Simplified schema:
+#
+# Relation 1:
+# PO_ORDER (PK: po_id) 1:1 <---> 0:N (FK: po_id) PO_ORDER_LINE
+#
+# Relation 2:
+# IN_INVENTORY (PK: item_id) 1:1 <---> 0:N (FK: item_id) PO_ORDER_LINE
+#
+# Relation 3:
+# +--> 0:1 (PK: person_id) AB_PHYSICAL_PERSON
+# PO_ORDER (FK: cust_id) 1:1 <--|
+# +--> 0:1 (PK: company_id) AB_MORAL_PERSON
+# This is an 'arc' relationship :)
+#
+
+
+--disable_warnings
+drop database if exists demo;
+--enable_warnings
+
+create database demo;
+
+use demo;
+
+create table ab_physical_person (
+ person_id integer,
+ first_name VARCHAR(50),
+ middle_initial CHAR,
+ last_name VARCHAR(50),
+ primary key (person_id));
+
+create table ab_moral_person (
+ company_id integer,
+ name VARCHAR(100),
+ primary key (company_id));
+
+create table in_inventory (
+ item_id integer,
+ descr VARCHAR(50),
+ stock integer,
+ primary key (item_id));
+
+create table po_order (
+ po_id integer auto_increment,
+ cust_type char, /* arc relationship, see cust_id */
+ cust_id integer, /* FK to ab_physical_person *OR* ab_moral_person */
+ primary key (po_id));
+
+create table po_order_line (
+ po_id integer, /* FK to po_order.po_id */
+ line_no integer,
+ item_id integer, /* FK to in_inventory.item_id */
+ qty integer);
+
+delimiter $$;
+
+--echo #
+--echo # Schema integrity enforcement
+--echo #
+
+create procedure check_pk_person(in person_type char, in id integer)
+begin
+ declare x integer;
+ declare msg varchar(128);
+
+ /*
+ Test integrity constraints for an 'arc' relationship.
+ Based on 'person_type', 'id' points to either a
+ physical person, or a moral person.
+ */
+ case person_type
+ when 'P' then
+ begin
+ select count(person_id) from ab_physical_person
+ where ab_physical_person.person_id = id
+ into x;
+
+ if (x != 1)
+ then
+ set msg= concat('No such physical person, PK:', id);
+ SIGNAL SQLSTATE '45000' SET
+ MESSAGE_TEXT = msg,
+ MYSQL_ERRNO = 10000;
+ end if;
+ end;
+
+ when 'M' then
+ begin
+ select count(company_id) from ab_moral_person
+ where ab_moral_person.company_id = id
+ into x;
+
+ if (x != 1)
+ then
+ set msg= concat('No such moral person, PK:', id);
+ SIGNAL SQLSTATE '45000' SET
+ MESSAGE_TEXT = msg,
+ MYSQL_ERRNO = 10000;
+ end if;
+ end;
+
+ else
+ begin
+ set msg= concat('No such person type:', person_type);
+ SIGNAL SQLSTATE '45000' SET
+ MESSAGE_TEXT = msg,
+ MYSQL_ERRNO = 20000;
+ end;
+ end case;
+end
+$$
+
+create procedure check_pk_inventory(in id integer)
+begin
+ declare x integer;
+ declare msg varchar(128);
+
+ select count(item_id) from in_inventory
+ where in_inventory.item_id = id
+ into x;
+
+ if (x != 1)
+ then
+ set msg= concat('Failed integrity constraint, table in_inventory, PK:',
+ id);
+ SIGNAL SQLSTATE '45000' SET
+ MESSAGE_TEXT = msg,
+ MYSQL_ERRNO = 10000;
+ end if;
+end
+$$
+
+create procedure check_pk_order(in id integer)
+begin
+ declare x integer;
+ declare msg varchar(128);
+
+ select count(po_id) from po_order
+ where po_order.po_id = id
+ into x;
+
+ if (x != 1)
+ then
+ set msg= concat('Failed integrity constraint, table po_order, PK:', id);
+ SIGNAL SQLSTATE '45000' SET
+ MESSAGE_TEXT = msg,
+ MYSQL_ERRNO = 10000;
+ end if;
+end
+$$
+
+create trigger po_order_bi before insert on po_order
+for each row
+begin
+ call check_pk_person(NEW.cust_type, NEW.cust_id);
+end
+$$
+
+create trigger po_order_bu before update on po_order
+for each row
+begin
+ call check_pk_person(NEW.cust_type, NEW.cust_id);
+end
+$$
+
+create trigger po_order_line_bi before insert on po_order_line
+for each row
+begin
+ call check_pk_order(NEW.po_id);
+ call check_pk_inventory(NEW.item_id);
+end
+$$
+
+create trigger po_order_line_bu before update on po_order_line
+for each row
+begin
+ call check_pk_order(NEW.po_id);
+ call check_pk_inventory(NEW.item_id);
+end
+$$
+
+--echo #
+--echo # Application helpers
+--echo #
+
+create procedure po_create_order(
+ in p_cust_type char,
+ in p_cust_id integer,
+ out id integer)
+begin
+ insert into po_order set cust_type = p_cust_type, cust_id = p_cust_id;
+ set id = last_insert_id();
+end
+$$
+
+create procedure po_add_order_line(
+ in po integer,
+ in line integer,
+ in item integer,
+ in q integer)
+begin
+ insert into po_order_line set
+ po_id = po, line_no = line, item_id = item, qty = q;
+end
+$$
+
+delimiter ;$$
+
+--echo #
+--echo # Create sample data
+--echo #
+
+insert into ab_physical_person values
+ ( 1, "John", "A", "Doe"),
+ ( 2, "Marry", "B", "Smith")
+;
+
+insert into ab_moral_person values
+ ( 3, "ACME real estate, INC"),
+ ( 4, "Local school")
+;
+
+insert into in_inventory values
+ ( 100, "Table, dinner", 5),
+ ( 101, "Chair", 20),
+ ( 200, "Table, coffee", 3),
+ ( 300, "School table", 25),
+ ( 301, "School chairs", 50)
+;
+
+select * from ab_physical_person order by person_id;
+select * from ab_moral_person order by company_id;
+select * from in_inventory order by item_id;
+
+--echo #
+--echo # Entering an order
+--echo #
+
+set @my_po = 0;
+
+/* John Doe wants 1 table and 4 chairs */
+call po_create_order("P", 1, @my_po);
+
+call po_add_order_line (@my_po, 1, 100, 1);
+call po_add_order_line (@my_po, 2, 101, 4);
+
+/* Marry Smith wants a coffee table */
+call po_create_order("P", 2, @my_po);
+
+call po_add_order_line (@my_po, 1, 200, 1);
+
+--echo #
+--echo # Entering bad data in an order
+--echo #
+
+# There is no item 999 in in_inventory
+--error 10000
+call po_add_order_line (@my_po, 1, 999, 1);
+
+--echo #
+--echo # Entering bad data in an unknown order
+--echo #
+
+# There is no order 99 in po_order
+--error 10000
+call po_add_order_line (99, 1, 100, 1);
+
+--echo #
+--echo # Entering an order for an unknown company
+--echo #
+
+# There is no moral person of id 7
+--error 10000
+call po_create_order("M", 7, @my_po);
+
+--echo #
+--echo # Entering an order for an unknown person type
+--echo #
+
+# There is no person of type X
+--error 20000
+call po_create_order("X", 1, @my_po);
+
+/* The local school wants 10 class tables and 20 chairs */
+call po_create_order("M", 4, @my_po);
+
+call po_add_order_line (@my_po, 1, 300, 10);
+call po_add_order_line (@my_po, 2, 301, 20);
+
+# Raw data
+select * from po_order;
+select * from po_order_line;
+
+# Creative reporting ...
+
+select po_id as "PO#",
+ ( case cust_type
+ when "P" then concat (pp.first_name,
+ " ",
+ pp.middle_initial,
+ " ",
+ pp.last_name)
+ when "M" then mp.name
+ end ) as "Sold to"
+ from po_order po
+ left join ab_physical_person pp on po.cust_id = pp.person_id
+ left join ab_moral_person mp on po.cust_id = company_id
+;
+
+select po_id as "PO#",
+ ol.line_no as "Line",
+ ol.item_id as "Item",
+ inv.descr as "Description",
+ ol.qty as "Quantity"
+ from po_order_line ol, in_inventory inv
+ where inv.item_id = ol.item_id
+ order by ol.item_id, ol.line_no;
+
+drop database demo;
+
+
diff --git a/mysql-test/t/signal_demo2.test b/mysql-test/t/signal_demo2.test
new file mode 100644
index 00000000000..fc909cb926c
--- /dev/null
+++ b/mysql-test/t/signal_demo2.test
@@ -0,0 +1,207 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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
+
+#
+# Demonstrate how RESIGNAL can be used to 'catch' and 're-throw' an error
+#
+
+--disable_warnings
+drop database if exists demo;
+--enable_warnings
+
+create database demo;
+
+use demo;
+
+delimiter $$;
+
+create procedure proc_top_a(p1 integer)
+begin
+ ## DECLARE CONTINUE HANDLER for SQLEXCEPTION, NOT FOUND
+ begin
+ end;
+
+ select "Starting ...";
+ call proc_middle_a(p1);
+ select "The end";
+end
+$$
+
+create procedure proc_middle_a(p1 integer)
+begin
+ DECLARE l integer;
+ # without RESIGNAL:
+ # Should be: DECLARE EXIT HANDLER for SQLEXCEPTION, NOT FOUND
+ DECLARE EXIT HANDLER for 1 /* not sure how to handle exceptions */
+ begin
+ select "Oops ... now what ?";
+ end;
+
+ select "In prod_middle()";
+
+ create temporary table t1(a integer, b integer);
+ select GET_LOCK("user_mutex", 10) into l;
+
+ insert into t1 set a = p1, b = p1;
+
+ call proc_bottom_a(p1);
+
+ select RELEASE_LOCK("user_mutex") into l;
+ drop temporary table t1;
+end
+$$
+
+create procedure proc_bottom_a(p1 integer)
+begin
+ select "In proc_bottom()";
+
+ if (p1 = 1) then
+ begin
+ select "Doing something that works ...";
+ select * from t1;
+ end;
+ end if;
+
+ if (p1 = 2) then
+ begin
+ select "Doing something that fail (simulate an error) ...";
+ drop table no_such_table;
+ end;
+ end if;
+
+ if (p1 = 3) then
+ begin
+ select "Doing something that *SHOULD* works ...";
+ select * from t1;
+ end;
+ end if;
+
+end
+$$
+
+delimiter ;$$
+
+#
+# Code without RESIGNAL:
+# errors are apparent to the caller,
+# but there is no cleanup code,
+# so that the environment (get_lock(), temporary table) is polluted ...
+#
+call proc_top_a(1);
+
+# Expected
+--error ER_BAD_TABLE_ERROR
+call proc_top_a(2);
+
+# Dirty state
+--error ER_TABLE_EXISTS_ERROR
+call proc_top_a(3);
+
+# Dirty state
+--error ER_TABLE_EXISTS_ERROR
+call proc_top_a(1);
+
+drop temporary table if exists t1;
+
+delimiter $$;
+
+create procedure proc_top_b(p1 integer)
+begin
+ select "Starting ...";
+ call proc_middle_b(p1);
+ select "The end";
+end
+$$
+
+create procedure proc_middle_b(p1 integer)
+begin
+ DECLARE l integer;
+ DECLARE EXIT HANDLER for SQLEXCEPTION, NOT FOUND
+ begin
+ begin
+ DECLARE CONTINUE HANDLER for SQLEXCEPTION, NOT FOUND
+ begin
+ /* Ignore errors from the cleanup code */
+ end;
+
+ select "Doing cleanup !";
+ select RELEASE_LOCK("user_mutex") into l;
+ drop temporary table t1;
+ end;
+
+ RESIGNAL;
+ end;
+
+ select "In prod_middle()";
+
+ create temporary table t1(a integer, b integer);
+ select GET_LOCK("user_mutex", 10) into l;
+
+ insert into t1 set a = p1, b = p1;
+
+ call proc_bottom_b(p1);
+
+ select RELEASE_LOCK("user_mutex") into l;
+ drop temporary table t1;
+end
+$$
+
+create procedure proc_bottom_b(p1 integer)
+begin
+ select "In proc_bottom()";
+
+ if (p1 = 1) then
+ begin
+ select "Doing something that works ...";
+ select * from t1;
+ end;
+ end if;
+
+ if (p1 = 2) then
+ begin
+ select "Doing something that fail (simulate an error) ...";
+ drop table no_such_table;
+ end;
+ end if;
+
+ if (p1 = 3) then
+ begin
+ select "Doing something that *SHOULD* works ...";
+ select * from t1;
+ end;
+ end if;
+
+end
+$$
+
+delimiter ;$$
+
+#
+# Code with RESIGNAL:
+# errors are apparent to the caller,
+# the but cleanup code did get a chance to act ...
+#
+
+call proc_top_b(1);
+
+--error ER_BAD_TABLE_ERROR
+call proc_top_b(2);
+
+call proc_top_b(3);
+
+call proc_top_b(1);
+
+drop database demo;
+
diff --git a/mysql-test/t/signal_demo3.test b/mysql-test/t/signal_demo3.test
new file mode 100644
index 00000000000..347f1b75a79
--- /dev/null
+++ b/mysql-test/t/signal_demo3.test
@@ -0,0 +1,159 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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
+
+#
+# Demonstrate how RESIGNAL can be used to print a stack trace
+#
+
+# Save defaults
+
+SET @start_global_value = @@global.max_error_count;
+SELECT @start_global_value;
+SET @start_session_value = @@session.max_error_count;
+SELECT @start_session_value;
+
+--disable_warnings
+drop database if exists demo;
+--enable_warnings
+
+create database demo;
+
+use demo;
+
+delimiter $$;
+
+create procedure proc_1()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_1';
+
+ call proc_2();
+end
+$$
+
+create procedure proc_2()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_2';
+
+ call proc_3();
+end
+$$
+
+create procedure proc_3()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_3';
+
+ call proc_4();
+end
+$$
+
+create procedure proc_4()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_4';
+
+ call proc_5();
+end
+$$
+
+create procedure proc_5()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_5';
+
+ call proc_6();
+end
+$$
+
+create procedure proc_6()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_6';
+
+ call proc_7();
+end
+$$
+
+create procedure proc_7()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_7';
+
+ call proc_8();
+end
+$$
+
+create procedure proc_8()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_8';
+
+ call proc_9();
+end
+$$
+
+create procedure proc_9()
+begin
+ declare exit handler for sqlexception
+ resignal sqlstate '45000' set message_text='Oops in proc_9';
+
+ ## Do something that fails, to see how errors are reported
+ drop table oops_it_is_not_here;
+end
+$$
+
+delimiter ;$$
+
+-- error ER_SIGNAL_EXCEPTION
+call proc_1();
+
+# This is the interesting part:
+# the complete call stack from the origin of failure (proc_9)
+# to the top level caller (proc_1) is available ...
+
+show warnings;
+
+SET @@session.max_error_count = 5;
+SELECT @@session.max_error_count;
+
+-- error ER_SIGNAL_EXCEPTION
+call proc_1();
+show warnings;
+
+SET @@session.max_error_count = 7;
+SELECT @@session.max_error_count;
+
+-- error ER_SIGNAL_EXCEPTION
+call proc_1();
+show warnings;
+
+SET @@session.max_error_count = 9;
+SELECT @@session.max_error_count;
+
+-- error ER_SIGNAL_EXCEPTION
+call proc_1();
+show warnings;
+
+drop database demo;
+
+# Restore defaults
+
+SET @@global.max_error_count = @start_global_value;
+SELECT @@global.max_error_count;
+SET @@session.max_error_count = @start_session_value;
+SELECT @@session.max_error_count;
+
diff --git a/mysql-test/t/signal_sqlmode.test b/mysql-test/t/signal_sqlmode.test
new file mode 100644
index 00000000000..860c145a361
--- /dev/null
+++ b/mysql-test/t/signal_sqlmode.test
@@ -0,0 +1,123 @@
+# Copyright (C) 2008 Sun Microsystems, Inc
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# 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
+
+# Tests for SIGNAL, RESIGNAL and GET DIAGNOSTICS
+
+SET @save_sql_mode=@@sql_mode;
+
+SET sql_mode='';
+
+--disable_warnings
+drop procedure if exists p;
+drop procedure if exists p2;
+drop procedure if exists p3;
+--enable_warnings
+
+delimiter $$;
+
+create procedure p()
+begin
+ declare utf8_var VARCHAR(128) CHARACTER SET UTF8;
+ set utf8_var = concat(repeat('A', 128), 'X');
+ select length(utf8_var), utf8_var;
+end
+$$
+
+create procedure p2()
+begin
+ declare msg VARCHAR(129) CHARACTER SET UTF8;
+ set msg = concat(repeat('A', 128), 'X');
+ select length(msg), msg;
+
+ signal sqlstate '55555' set message_text = msg;
+end
+$$
+
+create procedure p3()
+begin
+ declare name VARCHAR(65) CHARACTER SET UTF8;
+ set name = concat(repeat('A', 64), 'X');
+ select length(name), name;
+
+ signal sqlstate '55555' set
+ message_text = 'Message',
+ table_name = name;
+end
+$$
+delimiter ;$$
+
+call p;
+
+--error ER_SIGNAL_EXCEPTION
+call p2;
+
+--error ER_SIGNAL_EXCEPTION
+call p3;
+
+drop procedure p;
+drop procedure p2;
+drop procedure p3;
+
+SET sql_mode='STRICT_ALL_TABLES';
+
+delimiter $$;
+
+create procedure p()
+begin
+ declare utf8_var VARCHAR(128) CHARACTER SET UTF8;
+ set utf8_var = concat(repeat('A', 128), 'X');
+ select length(utf8_var), utf8_var;
+end
+$$
+
+create procedure p2()
+begin
+ declare msg VARCHAR(129) CHARACTER SET UTF8;
+ set msg = concat(repeat('A', 128), 'X');
+ select length(msg), msg;
+
+ signal sqlstate '55555' set message_text = msg;
+end
+$$
+
+create procedure p3()
+begin
+ declare name VARCHAR(65) CHARACTER SET UTF8;
+ set name = concat(repeat('A', 64), 'X');
+ select length(name), name;
+
+ signal sqlstate '55555' set
+ message_text = 'Message',
+ table_name = name;
+end
+$$
+
+delimiter ;$$
+
+--error ER_DATA_TOO_LONG
+call p;
+
+--error ER_COND_ITEM_TOO_LONG
+call p2;
+
+--error ER_COND_ITEM_TOO_LONG
+call p3;
+
+drop procedure p;
+drop procedure p2;
+drop procedure p3;
+
+SET @@sql_mode=@save_sql_mode;
+
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 1580d7f36d7..e7d7d5ca16b 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -559,7 +559,7 @@ select @@lc_time_names;
--echo *** LC_TIME_NAMES: testing with string expressions
set lc_time_names=concat('de','_','DE');
select @@lc_time_names;
---error ER_UNKNOWN_ERROR
+--error ER_UNKNOWN_LOCALE
set lc_time_names=concat('de','+','DE');
select @@lc_time_names;
--echo LC_TIME_NAMES: testing with numeric expressions
@@ -572,15 +572,15 @@ set lc_time_names=en_US;
--echo LC_TIME_NAMES: testing NULL and a negative number:
--error ER_WRONG_VALUE_FOR_VAR
set lc_time_names=NULL;
---error ER_UNKNOWN_ERROR
+--error ER_UNKNOWN_LOCALE
set lc_time_names=-1;
select @@lc_time_names;
--echo LC_TIME_NAMES: testing locale with the last ID:
-set lc_time_names=108;
+set lc_time_names=109;
select @@lc_time_names;
--echo LC_TIME_NAMES: testing a number beyond the valid ID range:
---error ER_UNKNOWN_ERROR
-set lc_time_names=109;
+--error ER_UNKNOWN_LOCALE
+set lc_time_names=110;
select @@lc_time_names;
--echo LC_TIME_NAMES: testing that 0 is en_US:
set lc_time_names=0;
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 545278485d1..aa7523aea3f 100755
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -13,8 +13,6 @@
# 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_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
-
# Only the server link with this library, the client libraries and the client
# executables all link with recompiles of source found in the "mysys" directory.
# So we only need to create one version of this library, with the "static"
@@ -39,7 +37,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_
my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c
my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c
my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c
- my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c stacktrace.c
+ my_winerr.c my_winfile.c my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c stacktrace.c
rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c)
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 4b07cf89676..0c916166aab 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2000-2006 MySQL AB
+# Copyright (C) 2000-2006 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
@@ -25,7 +25,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
mf_path.c mf_loadpath.c my_file.c \
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c my_getpagesize.c \
- mf_keycache.c mf_keycaches.c my_crc32.c \
+ mf_keycaches.c my_crc32.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
@@ -53,10 +53,18 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
my_handler.c my_netware.c my_largepage.c \
my_memmem.c stacktrace.c \
my_windac.c my_access.c base64.c my_libwrap.c
+
+if NEED_THREAD
+# mf_keycache is used only in the server, so it is safe to leave the file
+# out of the non-threaded library.
+# In fact, it will currently not compile without thread support.
+libmysys_a_SOURCES += mf_keycache.c
+endif
+
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c \
CMakeLists.txt mf_soundex.c \
- my_conio.c my_wincond.c my_winthread.c
+ my_conio.c my_wincond.c my_winthread.c my_winerr.c my_winfile.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
# test_dir_DEPENDENCIES= $(LIBRARIES)
# testhash_DEPENDENCIES= $(LIBRARIES)
diff --git a/mysys/charset-def.c b/mysys/charset-def.c
index 63bbceef29b..bf2576621ce 100644
--- a/mysys/charset-def.c
+++ b/mysys/charset-def.c
@@ -42,6 +42,7 @@ 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_sinhala_uca_ci;
#endif
#ifdef HAVE_CHARSET_utf8
@@ -63,6 +64,7 @@ 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_sinhala_uca_ci;
#ifdef HAVE_UTF8_GENERAL_CS
extern CHARSET_INFO my_charset_utf8_general_cs;
#endif
@@ -152,6 +154,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
add_compiled_collation(&my_charset_ucs2_persian_uca_ci);
add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci);
add_compiled_collation(&my_charset_ucs2_hungarian_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_sinhala_uca_ci);
#endif
#endif
@@ -186,6 +189,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
add_compiled_collation(&my_charset_utf8_persian_uca_ci);
add_compiled_collation(&my_charset_utf8_esperanto_uca_ci);
add_compiled_collation(&my_charset_utf8_hungarian_uca_ci);
+ add_compiled_collation(&my_charset_utf8_sinhala_uca_ci);
#endif
#endif
diff --git a/mysys/charset.c b/mysys/charset.c
index b23ab084e90..214ca170757 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -248,6 +248,7 @@ static int add_collation(CHARSET_INFO *cs)
{
#if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS)
copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci);
+ newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII;
#endif
}
else if (!strcmp(cs->csname, "utf8"))
@@ -280,6 +281,8 @@ static int add_collation(CHARSET_INFO *cs)
if (my_charset_is_8bit_pure_ascii(all_charsets[cs->number]))
all_charsets[cs->number]->state|= MY_CS_PUREASCII;
+ if (!my_charset_is_ascii_compatible(cs))
+ all_charsets[cs->number]->state|= MY_CS_NONASCII;
}
}
else
diff --git a/mysys/default_modify.c b/mysys/default_modify.c
index 88df0122da2..b214a1df445 100644
--- a/mysys/default_modify.c
+++ b/mysys/default_modify.c
@@ -21,7 +21,7 @@
#define BUFF_SIZE 1024
#define RESERVE 1024 /* Extend buffer with this extent */
-#ifdef __WIN__
+#ifdef _WIN32
#define NEWLINE "\r\n"
#define NEWLINE_LEN 2
#else
@@ -78,7 +78,7 @@ int modify_defaults_file(const char *file_location, const char *option,
DBUG_RETURN(2);
/* my_fstat doesn't use the flag parameter */
- if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
+ if (my_fstat(my_fileno(cnf_file), &file_stat, MYF(0)))
goto malloc_err;
if (option && option_value)
@@ -213,7 +213,7 @@ int modify_defaults_file(const char *file_location, const char *option,
if (opt_applied)
{
/* Don't write the file if there are no changes to be made */
- if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
+ if (my_chsize(my_fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
MYF(MY_WME)) ||
my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
my_fwrite(cnf_file, (uchar*) file_buffer, (size_t) (dst_ptr - file_buffer),
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index b1dbb22c687..b9013811b34 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -52,20 +52,13 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
if (oldsize > newlength)
{
-#if defined(HAVE_SETFILEPOINTER)
- /* This is for the moment only true on windows */
- long is_success;
- HANDLE win_file= (HANDLE) _get_osfhandle(fd);
- long length_low, length_high;
- length_low= (long) (ulong) newlength;
- length_high= (long) ((ulonglong) newlength >> 32);
- is_success= SetFilePointer(win_file, length_low, &length_high, FILE_BEGIN);
- if (is_success == -1 && (my_errno= GetLastError()) != NO_ERROR)
+#ifdef _WIN32
+ if (my_win_chsize(fd, newlength))
+ {
+ my_errno= errno;
goto err;
- if (SetEndOfFile(win_file))
- DBUG_RETURN(0);
- my_errno= GetLastError();
- goto err;
+ }
+ DBUG_RETURN(0);
#elif defined(HAVE_FTRUNCATE)
if (ftruncate(fd, (off_t) newlength))
{
diff --git a/mysys/my_create.c b/mysys/my_create.c
index 5c9a1e027d2..d0436276d03 100644
--- a/mysys/my_create.c
+++ b/mysys/my_create.c
@@ -18,7 +18,7 @@
#include "mysys_err.h"
#include <errno.h>
#include <my_sys.h>
-#if defined(__WIN__)
+#if defined(_WIN32)
#include <share.h>
#endif
@@ -41,16 +41,12 @@ File my_create(const char *FileName, int CreateFlags, int access_flags,
FileName, CreateFlags, access_flags, MyFlags));
#if !defined(NO_OPEN_3)
- fd = open((char *) FileName, access_flags | O_CREAT,
+ fd= open((char *) FileName, access_flags | O_CREAT,
CreateFlags ? CreateFlags : my_umask);
-#elif defined(VMS)
- fd = open((char *) FileName, access_flags | O_CREAT, 0,
- "ctx=stm","ctx=bin");
-#elif defined(__WIN__)
- fd= my_sopen((char *) FileName, access_flags | O_CREAT | O_BINARY,
- SH_DENYNO, MY_S_IREAD | MY_S_IWRITE);
+#elif defined(_WIN32)
+ fd= my_win_open(FileName, access_flags | O_CREAT);
#else
- fd = open(FileName, access_flags);
+ fd= open(FileName, access_flags);
#endif
if ((MyFlags & MY_SYNC_DIR) && (fd >=0) &&
@@ -71,6 +67,7 @@ File my_create(const char *FileName, int CreateFlags, int access_flags,
if (unlikely(fd >= 0 && rc < 0))
{
int tmp= my_errno;
+ my_close(fd, MyFlags);
my_delete(FileName, MyFlags);
my_errno= tmp;
}
diff --git a/mysys/my_delete.c b/mysys/my_delete.c
index 22425ed95fd..3ab6ba399f9 100644
--- a/mysys/my_delete.c
+++ b/mysys/my_delete.c
@@ -36,7 +36,7 @@ int my_delete(const char *name, myf MyFlags)
DBUG_RETURN(err);
} /* my_delete */
-#if defined(__WIN__) && defined(__NT__)
+#if defined(__WIN__)
/*
Delete file which is possibly not closed.
diff --git a/mysys/my_dup.c b/mysys/my_dup.c
index 55f5e0c0099..5fdd6e9f364 100644
--- a/mysys/my_dup.c
+++ b/mysys/my_dup.c
@@ -29,7 +29,11 @@ File my_dup(File file, myf MyFlags)
const char *filename;
DBUG_ENTER("my_dup");
DBUG_PRINT("my",("file: %d MyFlags: %d", file, MyFlags));
- fd = dup(file);
+#ifdef _WIN32
+ fd= my_win_dup(file);
+#else
+ fd= dup(file);
+#endif
filename= (((uint) file < my_file_limit) ?
my_file_info[(int) file].name : "Unknown");
DBUG_RETURN(my_register_filename(fd, filename, FILE_BY_DUP,
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 2cf704d0089..e407e7706fc 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -22,7 +22,6 @@
/* Max length of a error message. Should be kept in sync with MYSQL_ERRMSG_SIZE. */
#define ERRMSGSIZE (512)
-
/* Define some external variables for error handling */
/*
@@ -67,12 +66,9 @@ static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs;
MyFlags Flags
... variable list
- RETURN
- What (*error_handler_hook)() returns:
- 0 OK
*/
-int my_error(int nr, myf MyFlags, ...)
+void my_error(int nr, myf MyFlags, ...)
{
const char *format;
struct my_err_head *meh_p;
@@ -96,7 +92,8 @@ int my_error(int nr, myf MyFlags, ...)
(void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
va_end(args);
}
- DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags));
+ (*error_handler_hook)(nr, ebuff, MyFlags);
+ DBUG_VOID_RETURN;
}
@@ -111,7 +108,7 @@ int my_error(int nr, myf MyFlags, ...)
... variable list
*/
-int my_printf_error(uint error, const char *format, myf MyFlags, ...)
+void my_printf_error(uint error, const char *format, myf MyFlags, ...)
{
va_list args;
char ebuff[ERRMSGSIZE];
@@ -122,7 +119,8 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...)
va_start(args,MyFlags);
(void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
va_end(args);
- DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags));
+ (*error_handler_hook)(error, ebuff, MyFlags);
+ DBUG_VOID_RETURN;
}
/*
@@ -135,9 +133,9 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...)
MyFlags Flags
*/
-int my_message(uint error, const char *str, register myf MyFlags)
+void my_message(uint error, const char *str, register myf MyFlags)
{
- return (*error_handler_hook)(error, str, MyFlags);
+ (*error_handler_hook)(error, str, MyFlags);
}
diff --git a/mysys/my_file.c b/mysys/my_file.c
index 44bacf55307..ec0c9c425ea 100644
--- a/mysys/my_file.c
+++ b/mysys/my_file.c
@@ -97,6 +97,7 @@ uint my_set_max_open_files(uint files)
DBUG_ENTER("my_set_max_open_files");
DBUG_PRINT("enter",("files: %u my_file_limit: %u", files, my_file_limit));
+ files+= MY_FILE_MIN;
files= set_max_open_files(min(files, OS_FILE_LIMIT));
if (files <= MY_NFILE)
DBUG_RETURN(files);
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index 44156da6ae3..879acac0111 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -41,24 +41,14 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags)
DBUG_ENTER("my_fopen");
DBUG_PRINT("my",("Name: '%s' flags: %d MyFlags: %d",
filename, flags, MyFlags));
- /*
- if we are not creating, then we need to use my_access to make sure
- the file exists since Windows doesn't handle files like "com1.sym"
- very well
- */
-#ifdef __WIN__
- if (check_if_legal_filename(filename))
- {
- errno= EACCES;
- fd= 0;
- }
- else
+
+ make_ftype(type,flags);
+
+#ifdef _WIN32
+ fd= my_win_fopen(filename, type);
+#else
+ fd= fopen(filename, type);
#endif
- {
- make_ftype(type,flags);
- fd = fopen(filename, type);
- }
-
if (fd != 0)
{
/*
@@ -66,18 +56,20 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags)
on some OS (SUNOS). Actually the filename save isn't that important
so we can ignore if this doesn't work.
*/
- if ((uint) fileno(fd) >= my_file_limit)
+
+ int filedesc= my_fileno(fd);
+ if ((uint)filedesc >= my_file_limit)
{
thread_safe_increment(my_stream_opened,&THR_LOCK_open);
DBUG_RETURN(fd); /* safeguard */
}
pthread_mutex_lock(&THR_LOCK_open);
- if ((my_file_info[fileno(fd)].name = (char*)
+ if ((my_file_info[filedesc].name= (char*)
my_strdup(filename,MyFlags)))
{
my_stream_opened++;
my_file_total_opened++;
- my_file_info[fileno(fd)].type = STREAM_BY_FOPEN;
+ my_file_info[filedesc].type= STREAM_BY_FOPEN;
pthread_mutex_unlock(&THR_LOCK_open);
DBUG_PRINT("exit",("stream: 0x%lx", (long) fd));
DBUG_RETURN(fd);
@@ -99,6 +91,7 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags)
/* Close a stream */
+/* Close a stream */
int my_fclose(FILE *fd, myf MyFlags)
{
int err,file;
@@ -106,8 +99,13 @@ int my_fclose(FILE *fd, myf MyFlags)
DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
- file=fileno(fd);
- if ((err = fclose(fd)) < 0)
+ file= my_fileno(fd);
+#ifndef _WIN32
+ err= fclose(fd);
+#else
+ err= my_win_fclose(fd);
+#endif
+ if(err < 0)
{
my_errno=errno;
if (MyFlags & (MY_FAE | MY_WME))
@@ -138,7 +136,12 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
Filedes, Flags, MyFlags));
make_ftype(type,Flags);
- if ((fd = fdopen(Filedes, type)) == 0)
+#ifdef _WIN32
+ fd= my_win_fdopen(Filedes, type);
+#else
+ fd= fdopen(Filedes, type);
+#endif
+ if (!fd)
{
my_errno=errno;
if (MyFlags & (MY_FAE | MY_WME))
diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c
index f3b5418b906..2059e1a9f18 100644
--- a/mysys/my_fstream.c
+++ b/mysys/my_fstream.c
@@ -56,11 +56,11 @@ size_t my_fread(FILE *stream, uchar *Buffer, size_t Count, myf MyFlags)
{
if (ferror(stream))
my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
- my_filename(fileno(stream)),errno);
+ my_filename(my_fileno(stream)),errno);
else
if (MyFlags & (MY_NABP | MY_FNABP))
my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
- my_filename(fileno(stream)),errno);
+ my_filename(my_fileno(stream)),errno);
}
my_errno=errno ? errno : -1;
if (ferror(stream) || MyFlags & (MY_NABP | MY_FNABP))
@@ -142,7 +142,7 @@ size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags)
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG),
- my_filename(fileno(stream)),errno);
+ my_filename(my_fileno(stream)),errno);
}
writtenbytes= (size_t) -1; /* Return that we got error */
break;
@@ -182,3 +182,14 @@ my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused)))
DBUG_PRINT("exit",("ftell: %lu",(ulong) pos));
DBUG_RETURN((my_off_t) pos);
} /* my_ftell */
+
+
+/* Get a File corresponding to the stream*/
+int my_fileno(FILE *f)
+{
+#ifdef _WIN32
+ return my_win_fileno(f);
+#else
+ return fileno(f);
+#endif
+}
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
index c7f138c7337..38fa0313c5d 100644
--- a/mysys/my_gethwaddr.c
+++ b/mysys/my_gethwaddr.c
@@ -101,7 +101,105 @@ err:
return res;
}
-#else /* FreeBSD elif linux */
+#elif defined(__WIN__)
+
+/* Workaround for BUG#32082 (Definition of VOID in my_global.h conflicts with
+windows headers) */
+#ifdef VOID
+#undef VOID
+#define VOID void
+#endif
+
+#include <iphlpapi.h>
+
+/*
+ The following typedef is for dynamically loading
+ iphlpapi.dll / GetAdaptersAddresses. Dynamic loading is
+ used because GetAdaptersAddresses is not available on Windows 2000
+ which MySQL still supports. Static linking would cause an unresolved export.
+*/
+typedef DWORD (WINAPI *pfnGetAdaptersAddresses)(IN ULONG Family,
+ IN DWORD Flags,IN PVOID Reserved,
+ OUT PIP_ADAPTER_ADDRESSES pAdapterAddresses,
+ IN OUT PULONG pOutBufLen);
+
+/*
+ my_gethwaddr - Windows version
+
+ @brief Retrieve MAC address from network hardware
+
+ @param[out] to MAC address exactly six bytes
+
+ @return Operation status
+ @retval 0 OK
+ @retval <>0 FAILED
+*/
+my_bool my_gethwaddr(uchar *to)
+{
+ PIP_ADAPTER_ADDRESSES pAdapterAddresses;
+ PIP_ADAPTER_ADDRESSES pCurrAddresses;
+ IP_ADAPTER_ADDRESSES adapterAddresses;
+ ULONG address_len;
+ my_bool return_val= 1;
+ static pfnGetAdaptersAddresses fnGetAdaptersAddresses=
+ (pfnGetAdaptersAddresses)-1;
+
+ if(fnGetAdaptersAddresses == (pfnGetAdaptersAddresses)-1)
+ {
+ /* Get the function from the DLL */
+ fnGetAdaptersAddresses= (pfnGetAdaptersAddresses)
+ GetProcAddress(LoadLibrary("iphlpapi.dll"),
+ "GetAdaptersAddresses");
+ }
+ if (!fnGetAdaptersAddresses)
+ return 1; /* failed to get function */
+ address_len= sizeof (IP_ADAPTER_ADDRESSES);
+
+ /* Get the required size for the address data. */
+ if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, &adapterAddresses, &address_len)
+ == ERROR_BUFFER_OVERFLOW)
+ {
+ pAdapterAddresses= my_malloc(address_len, 0);
+ if (!pAdapterAddresses)
+ return 1; /* error, alloc failed */
+ }
+ else
+ pAdapterAddresses= &adapterAddresses; /* one is enough don't alloc */
+
+ /* Get the hardware info. */
+ if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &address_len)
+ == NO_ERROR)
+ {
+ pCurrAddresses= pAdapterAddresses;
+
+ while (pCurrAddresses)
+ {
+ /* Look for ethernet cards. */
+ if (pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD)
+ {
+ /* check for a good address */
+ if (pCurrAddresses->PhysicalAddressLength < 6)
+ continue; /* bad address */
+
+ /* save 6 bytes of the address in the 'to' parameter */
+ memcpy(to, pCurrAddresses->PhysicalAddress, 6);
+
+ /* Network card found, we're done. */
+ return_val= 0;
+ break;
+ }
+ pCurrAddresses= pCurrAddresses->Next;
+ }
+ }
+
+ /* Clean up memory allocation. */
+ if (pAdapterAddresses != &adapterAddresses)
+ my_free(pAdapterAddresses, 0);
+
+ return return_val;
+}
+
+#else /* __FreeBSD__ || __linux__ || __WIN__ */
/* just fail */
my_bool my_gethwaddr(uchar *to __attribute__((unused)))
{
diff --git a/mysys/my_init.c b/mysys/my_init.c
index a60927be693..c4fda599481 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -27,6 +27,8 @@
#ifdef _MSC_VER
#include <locale.h>
#include <crtdbg.h>
+/* WSAStartup needs winsock library*/
+#pragma comment(lib, "ws2_32")
#endif
my_bool have_tcpip=0;
static void my_win_init(void);
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index c18d14fb549..033f8789b49 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -35,8 +35,7 @@
# if defined(HAVE_NDIR_H)
# include <ndir.h>
# endif
-# if defined(__WIN__)
-# include <dos.h>
+# if defined(_WIN32)
# ifdef __BORLANDC__
# include <dir.h>
# endif
@@ -92,7 +91,7 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b)
} /* comp_names */
-#if !defined(__WIN__)
+#if !defined(_WIN32)
MY_DIR *my_dir(const char *path, myf MyFlags)
{
@@ -507,19 +506,24 @@ error:
DBUG_RETURN((MY_DIR *) NULL);
} /* my_dir */
-#endif /* __WIN__ */
+#endif /* _WIN32 */
/****************************************************************************
** File status
** Note that MY_STAT is assumed to be same as struct stat
****************************************************************************/
-int my_fstat(int Filedes, MY_STAT *stat_area,
+
+int my_fstat(File Filedes, MY_STAT *stat_area,
myf MyFlags __attribute__((unused)))
{
DBUG_ENTER("my_fstat");
DBUG_PRINT("my",("fd: %d MyFlags: %d", Filedes, MyFlags));
+#ifdef _WIN32
+ DBUG_RETURN(my_win_fstat(Filedes, stat_area));
+#else
DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area));
+#endif
}
@@ -531,11 +535,15 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
(long) stat_area, my_flags));
if ((m_used= (stat_area == NULL)))
- if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
+ if (!(stat_area= (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
goto error;
- if (! stat((char *) path, (struct stat *) stat_area) )
- DBUG_RETURN(stat_area);
-
+#ifndef _WIN32
+ if (! stat((char *) path, (struct stat *) stat_area) )
+ DBUG_RETURN(stat_area);
+#else
+ if (! my_win_stat(path, stat_area) )
+ DBUG_RETURN(stat_area);
+#endif
DBUG_PRINT("error",("Got errno: %d from stat", errno));
my_errno= errno;
if (m_used) /* Free if new area */
diff --git a/mysys/my_lock.c b/mysys/my_lock.c
index c0522ee849d..62f39bd3b71 100644
--- a/mysys/my_lock.c
+++ b/mysys/my_lock.c
@@ -22,13 +22,113 @@
#undef NO_ALARM_LOOP
#endif
#include <my_alarm.h>
-#ifdef __WIN__
-#include <sys/locking.h>
-#endif
#ifdef __NETWARE__
#include <nks/fsio.h>
#endif
+#ifdef _WIN32
+#define WIN_LOCK_INFINITE -1
+#define WIN_LOCK_SLEEP_MILLIS 100
+
+static int win_lock(File fd, int locktype, my_off_t start, my_off_t length,
+ int timeout_sec)
+{
+ LARGE_INTEGER liOffset,liLength;
+ DWORD dwFlags;
+ OVERLAPPED ov= {0};
+ HANDLE hFile= (HANDLE)my_get_osfhandle(fd);
+ DWORD lastError= 0;
+ int i;
+ int timeout_millis= timeout_sec * 1000;
+
+ DBUG_ENTER("win_lock");
+
+ liOffset.QuadPart= start;
+ liLength.QuadPart= length;
+
+ ov.Offset= liOffset.LowPart;
+ ov.OffsetHigh= liOffset.HighPart;
+
+ if (locktype == F_UNLCK)
+ {
+ if (UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov))
+ DBUG_RETURN(0);
+ /*
+ For compatibility with fcntl implementation, ignore error,
+ if region was not locked
+ */
+ if (GetLastError() == ERROR_NOT_LOCKED)
+ {
+ SetLastError(0);
+ DBUG_RETURN(0);
+ }
+ goto error;
+ }
+ else if (locktype == F_RDLCK)
+ /* read lock is mapped to a shared lock. */
+ dwFlags= 0;
+ else
+ /* write lock is mapped to an exclusive lock. */
+ dwFlags= LOCKFILE_EXCLUSIVE_LOCK;
+
+ /*
+ Drop old lock first to avoid double locking.
+ During analyze of Bug#38133 (Myisamlog test fails on Windows)
+ I met the situation that the program myisamlog locked the file
+ exclusively, then additionally shared, then did one unlock, and
+ then blocked on an attempt to lock it exclusively again.
+ Unlocking before every lock fixed the problem.
+ Note that this introduces a race condition. When the application
+ wants to convert an exclusive lock into a shared one, it will now
+ first unlock the file and then lock it shared. A waiting exclusive
+ lock could step in here. For reasons described in Bug#38133 and
+ Bug#41124 (Server hangs on Windows with --external-locking after
+ INSERT...SELECT) and in the review thread at
+ http://lists.mysql.com/commits/60721 it seems to be the better
+ option than not to unlock here.
+ If one day someone notices a way how to do file lock type changes
+ on Windows without unlocking before taking the new lock, please
+ change this code accordingly to fix the race condition.
+ */
+ if (!UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov) &&
+ (GetLastError() != ERROR_NOT_LOCKED))
+ goto error;
+
+ if (timeout_sec == WIN_LOCK_INFINITE)
+ {
+ if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov))
+ DBUG_RETURN(0);
+ goto error;
+ }
+
+ dwFlags|= LOCKFILE_FAIL_IMMEDIATELY;
+ timeout_millis= timeout_sec * 1000;
+ /* Try lock in a loop, until the lock is acquired or timeout happens */
+ for(i= 0; ;i+= WIN_LOCK_SLEEP_MILLIS)
+ {
+ if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov))
+ DBUG_RETURN(0);
+
+ if (GetLastError() != ERROR_LOCK_VIOLATION)
+ goto error;
+
+ if (i >= timeout_millis)
+ break;
+ Sleep(WIN_LOCK_SLEEP_MILLIS);
+ }
+
+ /* timeout */
+ errno= EAGAIN;
+ DBUG_RETURN(-1);
+
+error:
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+}
+#endif
+
+
+
/*
Lock a part of a file
@@ -48,8 +148,9 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length,
#ifdef __NETWARE__
int nxErrno;
#endif
+
DBUG_ENTER("my_lock");
- DBUG_PRINT("my",("Fd: %d Op: %d start: %ld Length: %ld MyFlags: %d",
+ DBUG_PRINT("my",("fd: %d Op: %d start: %ld Length: %ld MyFlags: %d",
fd,locktype,(long) start,(long) length,MyFlags));
#ifdef VMS
DBUG_RETURN(0);
@@ -97,29 +198,16 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length,
DBUG_RETURN(0);
}
}
-#elif defined(HAVE_LOCKING)
- /* Windows */
+#elif defined(_WIN32)
{
- my_bool error= FALSE;
- pthread_mutex_lock(&my_file_info[fd].mutex);
- if (MyFlags & MY_SEEK_NOT_DONE)
- {
- if( my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE))
- == MY_FILEPOS_ERROR )
- {
- /*
- If my_seek fails my_errno will already contain an error code;
- just unlock and return error code.
- */
- DBUG_PRINT("error",("my_errno: %d (%d)",my_errno,errno));
- pthread_mutex_unlock(&my_file_info[fd].mutex);
- DBUG_RETURN(-1);
- }
- }
- error= locking(fd,locktype,(ulong) length) && errno != EINVAL;
- pthread_mutex_unlock(&my_file_info[fd].mutex);
- if (!error)
- DBUG_RETURN(0);
+ int timeout_sec;
+ if (MyFlags & MY_DONT_WAIT)
+ timeout_sec= 0;
+ else
+ timeout_sec= WIN_LOCK_INFINITE;
+
+ if(win_lock(fd, locktype, start, length, timeout_sec) == 0)
+ DBUG_RETURN(0);
}
#else
#if defined(HAVE_FCNTL)
diff --git a/mysys/my_messnc.c b/mysys/my_messnc.c
index e2431959b7a..e2dee3f6710 100644
--- a/mysys/my_messnc.c
+++ b/mysys/my_messnc.c
@@ -15,8 +15,8 @@
#include "mysys_priv.h"
-int my_message_no_curses(uint error __attribute__((unused)),
- const char *str, myf MyFlags)
+void my_message_no_curses(uint error __attribute__((unused)),
+ const char *str, myf MyFlags)
{
DBUG_ENTER("my_message_no_curses");
DBUG_PRINT("enter",("message: %s",str));
@@ -34,5 +34,5 @@ int my_message_no_curses(uint error __attribute__((unused)),
(void)fputs(str,stderr);
(void)fputc('\n',stderr);
(void)fflush(stderr);
- DBUG_RETURN(0);
+ DBUG_VOID_RETURN;
}
diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c
index 023a06fd896..303d8efaf30 100644
--- a/mysys/my_mmap.c
+++ b/mysys/my_mmap.c
@@ -27,17 +27,17 @@ int my_msync(int fd, void *addr, size_t len, int flags)
return my_sync(fd, MYF(0));
}
-#elif defined(__WIN__)
+#elif defined(_WIN32)
static SECURITY_ATTRIBUTES mmap_security_attributes=
{sizeof(SECURITY_ATTRIBUTES), 0, TRUE};
void *my_mmap(void *addr, size_t len, int prot,
- int flags, int fd, my_off_t offset)
+ int flags, File fd, my_off_t offset)
{
HANDLE hFileMap;
LPVOID ptr;
- HANDLE hFile= (HANDLE)_get_osfhandle(fd);
+ HANDLE hFile= (HANDLE)my_get_osfhandle(fd);
if (hFile == INVALID_HANDLE_VALUE)
return MAP_FAILED;
diff --git a/mysys/my_open.c b/mysys/my_open.c
index fe7f65c450b..79a4da242f9 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -17,9 +17,7 @@
#include "mysys_err.h"
#include <my_dir.h>
#include <errno.h>
-#if defined(__WIN__)
-#include <share.h>
-#endif
+
/*
Open a file
@@ -43,29 +41,8 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
DBUG_ENTER("my_open");
DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d",
FileName, Flags, MyFlags));
-#if defined(__WIN__)
- /*
- Check that we don't try to open or create a file name that may
- cause problems for us in the future (like PRN)
- */
- if (check_if_legal_filename(FileName))
- {
- errno= EACCES;
- DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN,
- EE_FILENOTFOUND, MyFlags));
- }
-#ifndef __WIN__
- if (Flags & O_SHARE)
- fd = sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
- MY_S_IREAD | MY_S_IWRITE);
- else
- fd = open((char *) FileName, Flags | O_BINARY,
- MY_S_IREAD | MY_S_IWRITE);
-#else
- fd= my_sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
- MY_S_IREAD | MY_S_IWRITE);
-#endif
-
+#if defined(_WIN32)
+ fd= my_win_open(FileName, Flags);
#elif !defined(NO_OPEN_3)
fd = open(FileName, Flags, my_umask); /* Normal unix */
#else
@@ -94,11 +71,14 @@ int my_close(File fd, myf MyFlags)
DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
+#ifndef _WIN32
do
{
err= close(fd);
} while (err == -1 && errno == EINTR);
-
+#else
+ err= my_win_close(fd);
+#endif
if (err)
{
DBUG_PRINT("error",("Got error %d on close",err));
@@ -109,7 +89,7 @@ int my_close(File fd, myf MyFlags)
if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN)
{
my_free(my_file_info[fd].name, MYF(0));
-#if defined(THREAD) && !defined(HAVE_PREAD)
+#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32)
pthread_mutex_destroy(&my_file_info[fd].mutex);
#endif
my_file_info[fd].type = UNOPEN;
@@ -141,11 +121,11 @@ File my_register_filename(File fd, const char *FileName, enum file_type
type_of_file, uint error_message_number, myf MyFlags)
{
DBUG_ENTER("my_register_filename");
- if ((int) fd >= 0)
+ if ((int) fd >= MY_FILE_MIN)
{
if ((uint) fd >= my_file_limit)
{
-#if defined(THREAD) && !defined(HAVE_PREAD)
+#if defined(THREAD) && !defined(HAVE_PREAD)
my_errno= EMFILE;
#else
thread_safe_increment(my_file_opened,&THR_LOCK_open);
@@ -160,7 +140,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type
my_file_opened++;
my_file_total_opened++;
my_file_info[fd].type = type_of_file;
-#if defined(THREAD) && !defined(HAVE_PREAD)
+#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32)
pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST);
#endif
pthread_mutex_unlock(&THR_LOCK_open);
@@ -187,188 +167,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type
DBUG_RETURN(-1);
}
-#ifdef __WIN__
-
-extern void __cdecl _dosmaperr(unsigned long);
-
-/*
- Open a file with sharing. Similar to _sopen() from libc, but allows managing
- share delete on win32
-
- SYNOPSIS
- my_sopen()
- path fully qualified file name
- oflag operation flags
- shflag share flag
- pmode permission flags
-
- RETURN VALUE
- File descriptor of opened file if success
- -1 and sets errno if fails.
-*/
-
-File my_sopen(const char *path, int oflag, int shflag, int pmode)
-{
- int fh; /* handle of opened file */
- int mask;
- HANDLE osfh; /* OS handle of opened file */
- DWORD fileaccess; /* OS file access (requested) */
- DWORD fileshare; /* OS file sharing mode */
- DWORD filecreate; /* OS method of opening/creating */
- DWORD fileattrib; /* OS file attribute flags */
- SECURITY_ATTRIBUTES SecurityAttributes;
-
- SecurityAttributes.nLength= sizeof(SecurityAttributes);
- SecurityAttributes.lpSecurityDescriptor= NULL;
- SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
-
- /*
- * decode the access flags
- */
- switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
- case _O_RDONLY: /* read access */
- fileaccess= GENERIC_READ;
- break;
- case _O_WRONLY: /* write access */
- fileaccess= GENERIC_WRITE;
- break;
- case _O_RDWR: /* read and write access */
- fileaccess= GENERIC_READ | GENERIC_WRITE;
- break;
- default: /* error, bad oflag */
- errno= EINVAL;
- _doserrno= 0L; /* not an OS error */
- return -1;
- }
-
- /*
- * decode sharing flags
- */
- switch (shflag) {
- case _SH_DENYRW: /* exclusive access except delete */
- fileshare= FILE_SHARE_DELETE;
- break;
- case _SH_DENYWR: /* share read and delete access */
- fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE;
- break;
- case _SH_DENYRD: /* share write and delete access */
- fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- break;
- case _SH_DENYNO: /* share read, write and delete access */
- fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- break;
- case _SH_DENYRWD: /* exclusive access */
- fileshare= 0L;
- break;
- case _SH_DENYWRD: /* share read access */
- fileshare= FILE_SHARE_READ;
- break;
- case _SH_DENYRDD: /* share write access */
- fileshare= FILE_SHARE_WRITE;
- break;
- case _SH_DENYDEL: /* share read and write access */
- fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE;
- break;
- default: /* error, bad shflag */
- errno= EINVAL;
- _doserrno= 0L; /* not an OS error */
- return -1;
- }
-
- /*
- * decode open/create method flags
- */
- switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
- case 0:
- case _O_EXCL: /* ignore EXCL w/o CREAT */
- filecreate= OPEN_EXISTING;
- break;
-
- case _O_CREAT:
- filecreate= OPEN_ALWAYS;
- break;
-
- case _O_CREAT | _O_EXCL:
- case _O_CREAT | _O_TRUNC | _O_EXCL:
- filecreate= CREATE_NEW;
- break;
-
- case _O_TRUNC:
- case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */
- filecreate= TRUNCATE_EXISTING;
- break;
-
- case _O_CREAT | _O_TRUNC:
- filecreate= CREATE_ALWAYS;
- break;
-
- default:
- /* this can't happen ... all cases are covered */
- errno= EINVAL;
- _doserrno= 0L;
- return -1;
- }
-
- /*
- * decode file attribute flags if _O_CREAT was specified
- */
- fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */
- if (oflag & _O_CREAT)
- {
- _umask((mask= _umask(0)));
-
- if (!((pmode & ~mask) & _S_IWRITE))
- fileattrib= FILE_ATTRIBUTE_READONLY;
- }
-
- /*
- * Set temporary file (delete-on-close) attribute if requested.
- */
- if (oflag & _O_TEMPORARY)
- {
- fileattrib|= FILE_FLAG_DELETE_ON_CLOSE;
- fileaccess|= DELETE;
- }
-
- /*
- * Set temporary file (delay-flush-to-disk) attribute if requested.
- */
- if (oflag & _O_SHORT_LIVED)
- fileattrib|= FILE_ATTRIBUTE_TEMPORARY;
-
- /*
- * Set sequential or random access attribute if requested.
- */
- if (oflag & _O_SEQUENTIAL)
- fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN;
- else if (oflag & _O_RANDOM)
- fileattrib|= FILE_FLAG_RANDOM_ACCESS;
-
- /*
- * try to open/create the file
- */
- if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
- filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
- {
- /*
- * OS call to open/create file failed! map the error, release
- * the lock, and return -1. note that it's not necessary to
- * call _free_osfhnd (it hasn't been used yet).
- */
- _dosmaperr(GetLastError()); /* map error */
- return -1; /* return error to caller */
- }
-
- if ((fh= _open_osfhandle((intptr_t)osfh,
- oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1)
- {
- _dosmaperr(GetLastError()); /* map error */
- CloseHandle(osfh);
- }
- return fh; /* return handle */
-}
-#endif /* __WIN__ */
#ifdef EXTRA_DEBUG
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index 3f62f150c91..eaabcb1b728 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -15,11 +15,15 @@
#include "mysys_priv.h"
#include "mysys_err.h"
+#include "my_base.h"
+#include <m_string.h>
#include <errno.h>
-#ifdef HAVE_PREAD
+#if defined (HAVE_PREAD) && !defined(_WIN32)
#include <unistd.h>
#endif
+
+
/*
Read a chunk of bytes from a file from a given position
@@ -46,27 +50,39 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
{
size_t readbytes;
int error= 0;
+#if !defined (HAVE_PREAD) && !defined (_WIN32)
+ int save_errno;
+#endif
DBUG_ENTER("my_pread");
- DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d",
- Filedes, (ulong) offset, (long) Buffer, (uint) Count,
- MyFlags));
+ DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %d",
+ Filedes, (ulonglong)offset, Buffer, (ulong)Count, MyFlags));
for (;;)
{
-#ifndef __WIN__
- errno=0; /* Linux doesn't reset this */
-#endif
-#ifndef HAVE_PREAD
+ errno= 0; /* Linux, Windows don't reset this on EOF/success */
+#if !defined (HAVE_PREAD) && !defined (_WIN32)
pthread_mutex_lock(&my_file_info[Filedes].mutex);
readbytes= (uint) -1;
error= (lseek(Filedes, offset, MY_SEEK_SET) == (my_off_t) -1 ||
- (readbytes= read(Filedes, Buffer, (uint) Count)) != Count);
+ (readbytes= read(Filedes, Buffer, Count)) != Count);
+ save_errno= errno;
pthread_mutex_unlock(&my_file_info[Filedes].mutex);
+ if (error)
+ errno= save_errno;
#else
- if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count)))
- my_errno= errno ? errno : -1;
+#if defined(_WIN32)
+ readbytes= my_win_pread(Filedes, Buffer, Count, offset);
+#else
+ readbytes= pread(Filedes, Buffer, Count, offset);
+#endif
+ error= (readbytes != Count);
#endif
- if (error || readbytes != Count)
+ if(error)
{
+ my_errno= errno ? errno : -1;
+ if (errno == 0 || (readbytes != (size_t) -1 &&
+ (MyFlags & (MY_NABP | MY_FNABP))))
+ my_errno= HA_ERR_FILE_TOO_SHORT;
+
DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
(int) readbytes, (uint) Count,Filedes,my_errno));
#ifdef THREAD
@@ -79,19 +95,19 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
#endif
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
- if (readbytes == (size_t) -1)
- my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
- my_filename(Filedes),my_errno);
- else if (MyFlags & (MY_NABP | MY_FNABP))
- my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
- my_filename(Filedes),my_errno);
+ if (readbytes == (size_t) -1)
+ my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
+ my_filename(Filedes),my_errno);
+ else if (MyFlags & (MY_NABP | MY_FNABP))
+ my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
+ my_filename(Filedes),my_errno);
}
if (readbytes == (size_t) -1 || (MyFlags & (MY_FNABP | MY_NABP)))
- DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
+ DBUG_RETURN(MY_FILE_ERROR); /* Return with error */
}
if (MyFlags & (MY_NABP | MY_FNABP))
- DBUG_RETURN(0); /* Read went ok; Return 0 */
- DBUG_RETURN(readbytes); /* purecov: inspected */
+ DBUG_RETURN(0); /* Read went ok; Return 0 */
+ DBUG_RETURN(readbytes); /* purecov: inspected */
}
} /* my_pread */
@@ -117,42 +133,45 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
# Number of bytes read
*/
-size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
+size_t my_pwrite(File Filedes, const uchar *Buffer, size_t Count,
my_off_t offset, myf MyFlags)
{
- size_t writenbytes, written;
+ size_t writtenbytes, written;
uint errors;
+
DBUG_ENTER("my_pwrite");
- DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d",
- Filedes, (ulong) offset, (long) Buffer, (uint) Count,
- MyFlags));
+ DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %d",
+ Filedes, offset, Buffer, (ulong)Count, MyFlags));
errors= 0;
written= 0;
for (;;)
{
-#ifndef HAVE_PREAD
+#if !defined (HAVE_PREAD) && !defined (_WIN32)
int error;
- writenbytes= (size_t) -1;
+ writtenbytes= (size_t) -1;
pthread_mutex_lock(&my_file_info[Filedes].mutex);
error= (lseek(Filedes, offset, MY_SEEK_SET) != (my_off_t) -1 &&
- (writenbytes = write(Filedes, Buffer, (uint) Count)) == Count);
+ (writtenbytes= write(Filedes, Buffer, Count)) == Count);
pthread_mutex_unlock(&my_file_info[Filedes].mutex);
if (error)
break;
+#elif defined (_WIN32)
+ writtenbytes= my_win_pwrite(Filedes, Buffer, Count, offset);
#else
- if ((writenbytes= pwrite(Filedes, Buffer, Count,offset)) == Count)
+ writtenbytes= pwrite(Filedes, Buffer, Count, offset);
+#endif
+ if(writtenbytes == Count)
break;
my_errno= errno;
-#endif
- if (writenbytes != (size_t) -1)
- { /* Safegueard */
- written+=writenbytes;
- Buffer+=writenbytes;
- Count-=writenbytes;
- offset+=writenbytes;
+ if (writtenbytes != (size_t) -1)
+ {
+ written+= writtenbytes;
+ Buffer+= writtenbytes;
+ Count-= writtenbytes;
+ offset+= writtenbytes;
}
- DBUG_PRINT("error",("Write only %u bytes", (uint) writenbytes));
+ DBUG_PRINT("error",("Write only %u bytes", (uint) writtenbytes));
#ifndef NO_BACKGROUND
#ifdef THREAD
if (my_thread_var->abort)
@@ -165,15 +184,15 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
errors++;
continue;
}
- if ((writenbytes && writenbytes != (size_t) -1) || my_errno == EINTR)
+ if ((writtenbytes && writtenbytes != (size_t) -1) || my_errno == EINTR)
continue; /* Retry */
#endif
if (MyFlags & (MY_NABP | MY_FNABP))
{
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
- my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG),
- my_filename(Filedes),my_errno);
+ my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG),
+ my_filename(Filedes),my_errno);
}
DBUG_RETURN(MY_FILE_ERROR); /* Error on read */
}
@@ -183,5 +202,5 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
DBUG_EXECUTE_IF("check", my_seek(Filedes, -1, SEEK_SET, MYF(0)););
if (MyFlags & (MY_NABP | MY_FNABP))
DBUG_RETURN(0); /* Want only errors */
- DBUG_RETURN(writenbytes+written); /* purecov: inspected */
+ DBUG_RETURN(writtenbytes+written); /* purecov: inspected */
} /* my_pwrite */
diff --git a/mysys/my_quick.c b/mysys/my_quick.c
index 0ba20a5bdee..b93e7e17224 100644
--- a/mysys/my_quick.c
+++ b/mysys/my_quick.c
@@ -19,11 +19,19 @@
#include "my_nosys.h"
+#ifdef _WIN32
+extern size_t my_win_read(File Filedes,uchar *Buffer,size_t Count);
+#endif
+
size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags)
{
size_t readbytes;
-
- if ((readbytes = read(Filedes, Buffer, (uint) Count)) != Count)
+#ifdef _WIN32
+ readbytes= my_win_read(Filedes, Buffer, Count);
+#else
+ readbytes= read(Filedes, Buffer, Count);
+#endif
+ if(readbytes != Count)
{
#ifndef DBUG_OFF
if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR)
@@ -40,8 +48,13 @@ size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags)
}
-size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count)
+
+size_t my_quick_write(File Filedes, const uchar *Buffer, size_t Count)
{
+#ifdef _WIN32
+ return my_win_write(Filedes, Buffer, Count);
+#else
+
#ifndef DBUG_OFF
size_t writtenbytes;
#endif
@@ -50,7 +63,7 @@ size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count)
#ifndef DBUG_OFF
writtenbytes =
#endif
- (size_t) write(Filedes,Buffer, (uint) Count)) != Count)
+ (size_t) write(Filedes,Buffer,Count)) != Count)
{
#ifndef DBUG_OFF
if ((writtenbytes == 0 || writtenbytes == (size_t) -1) && errno == EINTR)
@@ -64,4 +77,5 @@ size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count)
return (size_t) -1;
}
return 0;
+#endif
}
diff --git a/mysys/my_read.c b/mysys/my_read.c
index 0c302d5b227..75f9dd64f1d 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -15,9 +15,9 @@
#include "mysys_priv.h"
#include "mysys_err.h"
+#include <my_base.h>
#include <errno.h>
-
/*
Read a chunk of bytes from a file with retry's if needed
@@ -37,16 +37,25 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags)
{
size_t readbytes, save_count;
DBUG_ENTER("my_read");
- DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d",
- Filedes, (long) Buffer, (ulong) Count, MyFlags));
+ DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d",
+ Filedes, Buffer, (ulong) Count, MyFlags));
save_count= Count;
for (;;)
{
- errno= 0; /* Linux doesn't reset this */
- if ((readbytes= read(Filedes, Buffer, (uint) Count)) != Count)
+ errno= 0; /* Linux, Windows don't reset this on EOF/success */
+#ifdef _WIN32
+ readbytes= my_win_read(Filedes, Buffer, Count);
+#else
+ readbytes= read(Filedes, Buffer, Count);
+#endif
+
+ if (readbytes != Count)
{
- my_errno= errno ? errno : -1;
+ my_errno= errno;
+ if (errno == 0 || (readbytes != (size_t) -1 &&
+ (MyFlags & (MY_NABP | MY_FNABP))))
+ my_errno= HA_ERR_FILE_TOO_SHORT;
DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d",
(int) readbytes, (ulong) Count, Filedes,
my_errno));
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index 2c661baeff7..8502c259353 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -45,36 +45,30 @@
my_off_t my_seek(File fd, my_off_t pos, int whence,
myf MyFlags __attribute__((unused)))
{
- reg1 os_off_t newpos= -1;
+ os_off_t newpos= -1;
DBUG_ENTER("my_seek");
- DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d",
- fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos,
- whence, MyFlags));
+ DBUG_PRINT("my",("fd: %d Pos: %llu Whence: %d MyFlags: %d",
+ fd, (ulonglong) pos, whence, MyFlags));
DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */
/*
Make sure we are using a valid file descriptor!
*/
DBUG_ASSERT(fd != -1);
-#if defined(THREAD) && !defined(HAVE_PREAD)
- if (MyFlags & MY_THREADSAFE)
- {
- pthread_mutex_lock(&my_file_info[fd].mutex);
- newpos= lseek(fd, pos, whence);
- pthread_mutex_unlock(&my_file_info[fd].mutex);
- }
- else
+#if defined (_WIN32)
+ newpos= my_win_lseek(fd, pos, whence);
+#else
+ newpos= lseek(fd, pos, whence);
#endif
- newpos= lseek(fd, pos, whence);
if (newpos == (os_off_t) -1)
{
- my_errno=errno;
- DBUG_PRINT("error",("lseek: %lu errno: %d", (ulong) newpos,errno));
+ my_errno= errno;
+ DBUG_PRINT("error",("lseek: %llu errno: %d", (ulonglong) newpos,errno));
DBUG_RETURN(MY_FILEPOS_ERROR);
}
if ((my_off_t) newpos != pos)
{
- DBUG_PRINT("exit",("pos: %lu", (ulong) newpos));
+ DBUG_PRINT("exit",("pos: %llu", (ulonglong) newpos));
}
DBUG_RETURN((my_off_t) newpos);
} /* my_seek */
@@ -87,15 +81,15 @@ my_off_t my_tell(File fd, myf MyFlags __attribute__((unused)))
{
os_off_t pos;
DBUG_ENTER("my_tell");
- DBUG_PRINT("my",("Fd: %d MyFlags: %d",fd, MyFlags));
+ DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags));
DBUG_ASSERT(fd >= 0);
-#ifdef HAVE_TELL
- pos=tell(fd);
+#if defined (HAVE_TELL) && !defined (_WIN32)
+ pos= tell(fd);
#else
- pos=lseek(fd, 0L, MY_SEEK_CUR);
+ pos= my_seek(fd, 0L, MY_SEEK_CUR,0);
#endif
if (pos == (os_off_t) -1)
- my_errno=errno;
- DBUG_PRINT("exit",("pos: %lu", (ulong) pos));
+ my_errno= errno;
+ DBUG_PRINT("exit",("pos: %llu", (ulonglong) pos));
DBUG_RETURN((my_off_t) pos);
} /* my_tell */
diff --git a/mysys/my_static.c b/mysys/my_static.c
index d0c20da828a..14f04491430 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@ int NEAR my_umask=0664, NEAR my_umask_dir=0777;
#ifndef THREAD
int NEAR my_errno=0;
#endif
-struct st_my_file_info my_file_info_default[MY_NFILE]= {{0,UNOPEN}};
+struct st_my_file_info my_file_info_default[MY_NFILE];
uint my_file_limit= MY_NFILE;
struct st_my_file_info *my_file_info= my_file_info_default;
@@ -87,9 +87,9 @@ ulong my_time_to_wait_for_lock=2; /* In seconds */
char * NEAR globerrs[GLOBERRS]; /* my_error_messages is here */
#endif
void (*my_abort_hook)(int) = (void(*)(int)) exit;
-int (*error_handler_hook)(uint error,const char *str,myf MyFlags)=
+void (*error_handler_hook)(uint error,const char *str,myf MyFlags)=
my_message_no_curses;
-int (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)=
+void (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)=
my_message_no_curses;
#ifdef __WIN__
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index ba6964b00d6..7b2112fa032 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -62,8 +62,8 @@ int my_sync(File fd, myf my_flags)
res= fdatasync(fd);
#elif defined(HAVE_FSYNC)
res= fsync(fd);
-#elif defined(__WIN__)
- res= _commit(fd);
+#elif defined(_WIN32)
+ res= my_win_fsync(fd);
#else
#error Cannot find a way to sync a file, durability in danger
res= 0; /* No sync (strange OS) */
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 2278c467f32..c6057f19a82 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -23,11 +23,7 @@
#include <signal.h>
#ifdef THREAD
-#ifdef USE_TLS
pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
-#else
-pthread_key(struct st_my_thread_var, THR_KEY_mysys);
-#endif /* USE_TLS */
pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,
THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time;
@@ -46,7 +42,9 @@ pthread_mutexattr_t my_fast_mutexattr;
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
pthread_mutexattr_t my_errorcheck_mutexattr;
#endif
-
+#ifdef _MSC_VER
+static void install_sigabrt_handler();
+#endif
#ifdef TARGET_OS_LINUX
/*
@@ -149,15 +147,18 @@ my_bool my_thread_global_init(void)
pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
pthread_cond_init(&THR_COND_threads, NULL);
-#if defined( __WIN__) || defined(OS2)
- win_pthread_init();
-#endif
+
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
#endif
#ifndef HAVE_GETHOSTBYNAME_R
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
#endif
+
+#ifdef _MSC_VER
+ install_sigabrt_handler();
+#endif
+
if (my_thread_init())
{
my_thread_global_end(); /* Clean up */
@@ -258,7 +259,6 @@ my_bool my_thread_init(void)
(ulong) pthread_self());
#endif
-#if !defined(__WIN__) || defined(USE_TLS)
if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys))
{
#ifdef EXTRA_DEBUG_THREADS
@@ -267,26 +267,18 @@ my_bool my_thread_init(void)
#endif
goto end;
}
+
+#ifdef _MSC_VER
+ install_sigabrt_handler();
+#endif
+
if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
{
error= 1;
goto end;
}
pthread_setspecific(THR_KEY_mysys,tmp);
-
-#else /* defined(__WIN__) && !(defined(USE_TLS) */
- /*
- Skip initialization if the thread specific variable is already initialized
- */
- if (THR_KEY_mysys.id)
- goto end;
- tmp= &THR_KEY_mysys;
-#endif
-#if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
- tmp->pthread_self= (pthread_t) getpid();
-#else
tmp->pthread_self= pthread_self();
-#endif
pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
pthread_cond_init(&tmp->suspend, NULL);
tmp->init= 1;
@@ -342,11 +334,7 @@ void my_thread_end(void)
pthread_cond_destroy(&tmp->suspend);
#endif
pthread_mutex_destroy(&tmp->mutex);
-#if !defined(__WIN__) || defined(USE_TLS)
free(tmp);
-#else
- tmp->init= 0;
-#endif
/*
Decrement counter for number of running threads. We are using this
@@ -360,10 +348,7 @@ void my_thread_end(void)
pthread_cond_signal(&THR_COND_threads);
pthread_mutex_unlock(&THR_LOCK_threads);
}
- /* The following free has to be done, even if my_thread_var() is 0 */
-#if !defined(__WIN__) || defined(USE_TLS)
pthread_setspecific(THR_KEY_mysys,0);
-#endif
}
struct st_my_thread_var *_my_thread_var(void)
@@ -419,4 +404,30 @@ static uint get_thread_lib(void)
return THD_LIB_OTHER;
}
+#ifdef _WIN32
+/*
+ In Visual Studio 2005 and later, default SIGABRT handler will overwrite
+ any unhandled exception filter set by the application and will try to
+ call JIT debugger. This is not what we want, this we calling __debugbreak
+ to stop in debugger, if process is being debugged or to generate
+ EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.
+*/
+
+#if (_MSC_VER >= 1400)
+static void my_sigabrt_handler(int sig)
+{
+ __debugbreak();
+}
+#endif /*_MSC_VER >=1400 */
+
+static void install_sigabrt_handler(void)
+{
+#if (_MSC_VER >=1400)
+ /*abort() should not override our exception filter*/
+ _set_abort_behavior(0,_CALL_REPORTFAULT);
+ signal(SIGABRT,my_sigabrt_handler);
+#endif /* _MSC_VER >=1400 */
+}
+#endif
+
#endif /* THREAD */
diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c
index d1b07b61408..956d29a970b 100644
--- a/mysys/my_wincond.c
+++ b/mysys/my_wincond.c
@@ -16,12 +16,11 @@
/*****************************************************************************
** The following is a simple implementation of posix conditions
*****************************************************************************/
+#if defined(_WIN32)
#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */
#include "mysys_priv.h"
-#if defined(THREAD) && defined(__WIN__)
#include <m_string.h>
-#undef getpid
#include <process.h>
#include <sys/timeb.h>
diff --git a/mysys/my_winerr.c b/mysys/my_winerr.c
new file mode 100644
index 00000000000..534078b6737
--- /dev/null
+++ b/mysys/my_winerr.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2008 MySQL AB
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Convert Windows API error (GetLastError() to Posix equivalent (errno)
+ The exported function my_osmaperr() is modelled after and borrows
+ heavily from undocumented _dosmaperr()(found of the static Microsoft C runtime).
+*/
+
+#include <my_global.h>
+#include <my_sys.h>
+
+
+struct errentry
+{
+ unsigned long oscode; /* OS return value */
+ int sysv_errno; /* System V error code */
+};
+
+static struct errentry errtable[]= {
+ { ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */
+ { ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */
+ { ERROR_PATH_NOT_FOUND, ENOENT }, /* 3 */
+ { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, /* 4 */
+ { ERROR_ACCESS_DENIED, EACCES }, /* 5 */
+ { ERROR_INVALID_HANDLE, EBADF }, /* 6 */
+ { ERROR_ARENA_TRASHED, ENOMEM }, /* 7 */
+ { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, /* 8 */
+ { ERROR_INVALID_BLOCK, ENOMEM }, /* 9 */
+ { ERROR_BAD_ENVIRONMENT, E2BIG }, /* 10 */
+ { ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */
+ { ERROR_INVALID_ACCESS, EINVAL }, /* 12 */
+ { ERROR_INVALID_DATA, EINVAL }, /* 13 */
+ { ERROR_INVALID_DRIVE, ENOENT }, /* 15 */
+ { ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */
+ { ERROR_NOT_SAME_DEVICE, EXDEV }, /* 17 */
+ { ERROR_NO_MORE_FILES, ENOENT }, /* 18 */
+ { ERROR_LOCK_VIOLATION, EACCES }, /* 33 */
+ { ERROR_BAD_NETPATH, ENOENT }, /* 53 */
+ { ERROR_NETWORK_ACCESS_DENIED, EACCES }, /* 65 */
+ { ERROR_BAD_NET_NAME, ENOENT }, /* 67 */
+ { ERROR_FILE_EXISTS, EEXIST }, /* 80 */
+ { ERROR_CANNOT_MAKE, EACCES }, /* 82 */
+ { ERROR_FAIL_I24, EACCES }, /* 83 */
+ { ERROR_INVALID_PARAMETER, EINVAL }, /* 87 */
+ { ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */
+ { ERROR_DRIVE_LOCKED, EACCES }, /* 108 */
+ { ERROR_BROKEN_PIPE, EPIPE }, /* 109 */
+ { ERROR_DISK_FULL, ENOSPC }, /* 112 */
+ { ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */
+ { ERROR_INVALID_HANDLE, EINVAL }, /* 124 */
+ { ERROR_WAIT_NO_CHILDREN, ECHILD }, /* 128 */
+ { ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */
+ { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */
+ { ERROR_NEGATIVE_SEEK, EINVAL }, /* 131 */
+ { ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */
+ { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, /* 145 */
+ { ERROR_NOT_LOCKED, EACCES }, /* 158 */
+ { ERROR_BAD_PATHNAME, ENOENT }, /* 161 */
+ { ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */
+ { ERROR_LOCK_FAILED, EACCES }, /* 167 */
+ { ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */
+ { ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */
+ { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */
+ { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } /* 1816 */
+};
+
+/* size of the table */
+#define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0]))
+
+/* The following two constants must be the minimum and maximum
+values in the (contiguous) range of Exec Failure errors. */
+#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
+#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN
+
+/* These are the low and high value in the range of errors that are
+access violations */
+#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
+#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED
+
+
+static int get_errno_from_oserr(unsigned long oserrno)
+{
+ int i;
+
+ /* check the table for the OS error code */
+ for (i= 0; i < ERRTABLESIZE; ++i)
+ {
+ if (oserrno == errtable[i].oscode)
+ {
+ return errtable[i].sysv_errno;
+ }
+ }
+
+ /* The error code wasn't in the table. We check for a range of */
+ /* EACCES errors or exec failure errors (ENOEXEC). Otherwise */
+ /* EINVAL is returned. */
+
+ if (oserrno >= MIN_EACCES_RANGE && oserrno <= MAX_EACCES_RANGE)
+ return EACCES;
+ else if (oserrno >= MIN_EXEC_ERROR && oserrno <= MAX_EXEC_ERROR)
+ return ENOEXEC;
+ else
+ return EINVAL;
+}
+
+/* Set errno corresponsing to GetLastError() value */
+void my_osmaperr ( unsigned long oserrno)
+{
+ errno= get_errno_from_oserr(oserrno);
+}
diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c
new file mode 100644
index 00000000000..6a2cda5ba29
--- /dev/null
+++ b/mysys/my_winfile.c
@@ -0,0 +1,672 @@
+/* Copyright (C) 2008 MySQL AB
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ The purpose of this file is to provide implementation of file IO routines on
+ Windows that can be thought as drop-in replacement for corresponding C runtime
+ functionality.
+
+ Compared to Windows CRT, this one
+ - does not have the same file descriptor
+ limitation (default is 16384 and can be increased further, whereas CRT poses
+ a hard limit of 2048 file descriptors)
+ - the file operations are not serialized
+ - positional IO pread/pwrite is ported here.
+ - no text mode for files, all IO is "binary"
+
+ Naming convention:
+ All routines are prefixed with my_win_, e.g Posix open() is implemented with
+ my_win_open()
+
+ Implemented are
+ - POSIX routines(e.g open, read, lseek ...)
+ - Some ANSI C stream routines (fopen, fdopen, fileno, fclose)
+ - Windows CRT equvalients (my_get_osfhandle, open_osfhandle)
+
+ Worth to note:
+ - File descriptors used here are located in a range that is not compatible
+ with CRT on purpose. Attempt to use a file descriptor from Windows CRT library
+ range in my_win_* function will be punished with DBUG_ASSERT()
+
+ - File streams (FILE *) are actually from the C runtime. The routines provided
+ here are useful only in scernarios that use low-level IO with my_win_fileno()
+*/
+
+#ifdef _WIN32
+
+#include "mysys_priv.h"
+#include <share.h>
+#include <sys/stat.h>
+
+/* Associates a file descriptor with an existing operating-system file handle.*/
+File my_open_osfhandle(HANDLE handle, int oflag)
+{
+ int offset= -1;
+ uint i;
+ DBUG_ENTER("my_open_osfhandle");
+
+ pthread_mutex_lock(&THR_LOCK_open);
+ for(i= MY_FILE_MIN; i < my_file_limit;i++)
+ {
+ if(my_file_info[i].fhandle == 0)
+ {
+ struct st_my_file_info *finfo= &(my_file_info[i]);
+ finfo->type= FILE_BY_OPEN;
+ finfo->fhandle= handle;
+ finfo->oflag= oflag;
+ offset= i;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&THR_LOCK_open);
+ if(offset == -1)
+ errno= EMFILE; /* to many file handles open */
+ DBUG_RETURN(offset);
+}
+
+
+static void invalidate_fd(File fd)
+{
+ DBUG_ENTER("invalidate_fd");
+ DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
+ my_file_info[fd].fhandle= 0;
+ DBUG_VOID_RETURN;
+}
+
+
+/* Get Windows handle for a file descriptor */
+HANDLE my_get_osfhandle(File fd)
+{
+ DBUG_ENTER("my_get_osfhandle");
+ DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
+ DBUG_RETURN(my_file_info[fd].fhandle);
+}
+
+
+static int my_get_open_flags(File fd)
+{
+ DBUG_ENTER("my_get_osfhandle");
+ DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
+ DBUG_RETURN(my_file_info[fd].oflag);
+}
+
+
+/*
+ Open a file with sharing. Similar to _sopen() from libc, but allows managing
+ share delete on win32
+
+ SYNOPSIS
+ my_win_sopen()
+ path file name
+ oflag operation flags
+ shflag share flag
+ pmode permission flags
+
+ RETURN VALUE
+ File descriptor of opened file if success
+ -1 and sets errno if fails.
+*/
+
+File my_win_sopen(const char *path, int oflag, int shflag, int pmode)
+{
+ int fh; /* handle of opened file */
+ int mask;
+ HANDLE osfh; /* OS handle of opened file */
+ DWORD fileaccess; /* OS file access (requested) */
+ DWORD fileshare; /* OS file sharing mode */
+ DWORD filecreate; /* OS method of opening/creating */
+ DWORD fileattrib; /* OS file attribute flags */
+ SECURITY_ATTRIBUTES SecurityAttributes;
+
+ DBUG_ENTER("my_win_sopen");
+
+ if (check_if_legal_filename(path))
+ {
+ errno= EACCES;
+ DBUG_RETURN(-1);
+ }
+ SecurityAttributes.nLength= sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor= NULL;
+ SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
+
+ /* decode the access flags */
+ switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
+ case _O_RDONLY: /* read access */
+ fileaccess= GENERIC_READ;
+ break;
+ case _O_WRONLY: /* write access */
+ fileaccess= GENERIC_WRITE;
+ break;
+ case _O_RDWR: /* read and write access */
+ fileaccess= GENERIC_READ | GENERIC_WRITE;
+ break;
+ default: /* error, bad oflag */
+ errno= EINVAL;
+ DBUG_RETURN(-1);
+ }
+
+ /* decode sharing flags */
+ switch (shflag) {
+ case _SH_DENYRW: /* exclusive access except delete */
+ fileshare= FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYWR: /* share read and delete access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYRD: /* share write and delete access */
+ fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYNO: /* share read, write and delete access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYRWD: /* exclusive access */
+ fileshare= 0L;
+ break;
+ case _SH_DENYWRD: /* share read access */
+ fileshare= FILE_SHARE_READ;
+ break;
+ case _SH_DENYRDD: /* share write access */
+ fileshare= FILE_SHARE_WRITE;
+ break;
+ case _SH_DENYDEL: /* share read and write access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
+ default: /* error, bad shflag */
+ errno= EINVAL;
+ DBUG_RETURN(-1);
+ }
+
+ /* decode open/create method flags */
+ switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
+ case 0:
+ case _O_EXCL: /* ignore EXCL w/o CREAT */
+ filecreate= OPEN_EXISTING;
+ break;
+
+ case _O_CREAT:
+ filecreate= OPEN_ALWAYS;
+ break;
+
+ case _O_CREAT | _O_EXCL:
+ case _O_CREAT | _O_TRUNC | _O_EXCL:
+ filecreate= CREATE_NEW;
+ break;
+
+ case _O_TRUNC:
+ case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */
+ filecreate= TRUNCATE_EXISTING;
+ break;
+
+ case _O_CREAT | _O_TRUNC:
+ filecreate= CREATE_ALWAYS;
+ break;
+
+ default:
+ /* this can't happen ... all cases are covered */
+ errno= EINVAL;
+ DBUG_RETURN(-1);
+ }
+
+ /* decode file attribute flags if _O_CREAT was specified */
+ fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */
+ if (oflag & _O_CREAT)
+ {
+ _umask((mask= _umask(0)));
+
+ if (!((pmode & ~mask) & _S_IWRITE))
+ fileattrib= FILE_ATTRIBUTE_READONLY;
+ }
+
+ /* Set temporary file (delete-on-close) attribute if requested. */
+ if (oflag & _O_TEMPORARY)
+ {
+ fileattrib|= FILE_FLAG_DELETE_ON_CLOSE;
+ fileaccess|= DELETE;
+ }
+
+ /* Set temporary file (delay-flush-to-disk) attribute if requested.*/
+ if (oflag & _O_SHORT_LIVED)
+ fileattrib|= FILE_ATTRIBUTE_TEMPORARY;
+
+ /* Set sequential or random access attribute if requested. */
+ if (oflag & _O_SEQUENTIAL)
+ fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN;
+ else if (oflag & _O_RANDOM)
+ fileattrib|= FILE_FLAG_RANDOM_ACCESS;
+
+ /* try to open/create the file */
+ if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
+ filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
+ {
+ /*
+ OS call to open/create file failed! map the error, release
+ the lock, and return -1. note that it's not necessary to
+ call _free_osfhnd (it hasn't been used yet).
+ */
+ my_osmaperr(GetLastError()); /* map error */
+ DBUG_RETURN(-1); /* return error to caller */
+ }
+
+ if ((fh= my_open_osfhandle(osfh,
+ oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1)
+ {
+ CloseHandle(osfh);
+ }
+
+ DBUG_RETURN(fh); /* return handle */
+}
+
+
+File my_win_open(const char *path, int flags)
+{
+ DBUG_ENTER("my_win_open");
+ DBUG_RETURN(my_win_sopen((char *) path, flags | _O_BINARY, _SH_DENYNO,
+ _S_IREAD | S_IWRITE));
+}
+
+
+int my_win_close(File fd)
+{
+ DBUG_ENTER("my_win_close");
+ if(CloseHandle(my_get_osfhandle(fd)))
+ {
+ invalidate_fd(fd);
+ DBUG_RETURN(0);
+ }
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+}
+
+
+size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset)
+{
+ DWORD nBytesRead;
+ HANDLE hFile;
+ OVERLAPPED ov= {0};
+ LARGE_INTEGER li;
+
+ DBUG_ENTER("my_win_pread");
+
+ if(!Count)
+ DBUG_RETURN(0);
+#ifdef _WIN64
+ if(Count > UINT_MAX)
+ Count= UINT_MAX;
+#endif
+
+ hFile= (HANDLE)my_get_osfhandle(Filedes);
+ li.QuadPart= offset;
+ ov.Offset= li.LowPart;
+ ov.OffsetHigh= li.HighPart;
+
+ if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, &ov))
+ {
+ DWORD lastError= GetLastError();
+ /*
+ ERROR_BROKEN_PIPE is returned when no more data coming
+ through e.g. a command pipe in windows : see MSDN on ReadFile.
+ */
+ if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
+ DBUG_RETURN(0); /*return 0 at EOF*/
+ my_osmaperr(lastError);
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(nBytesRead);
+}
+
+
+size_t my_win_read(File Filedes, uchar *Buffer, size_t Count)
+{
+ DWORD nBytesRead;
+ HANDLE hFile;
+
+ DBUG_ENTER("my_win_read");
+ if(!Count)
+ DBUG_RETURN(0);
+#ifdef _WIN64
+ if(Count > UINT_MAX)
+ Count= UINT_MAX;
+#endif
+
+ hFile= (HANDLE)my_get_osfhandle(Filedes);
+
+ if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, NULL))
+ {
+ DWORD lastError= GetLastError();
+ /*
+ ERROR_BROKEN_PIPE is returned when no more data coming
+ through e.g. a command pipe in windows : see MSDN on ReadFile.
+ */
+ if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
+ DBUG_RETURN(0); /*return 0 at EOF*/
+ my_osmaperr(lastError);
+ DBUG_RETURN(-1);
+ }
+ DBUG_RETURN(nBytesRead);
+}
+
+
+size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count,
+ my_off_t offset)
+{
+ DWORD nBytesWritten;
+ HANDLE hFile;
+ OVERLAPPED ov= {0};
+ LARGE_INTEGER li;
+
+ DBUG_ENTER("my_win_pwrite");
+ DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count: %llu, offset: %llu",
+ Filedes, Buffer, (ulonglong)Count, (ulonglong)offset));
+
+ if(!Count)
+ DBUG_RETURN(0);
+
+#ifdef _WIN64
+ if(Count > UINT_MAX)
+ Count= UINT_MAX;
+#endif
+
+ hFile= (HANDLE)my_get_osfhandle(Filedes);
+ li.QuadPart= offset;
+ ov.Offset= li.LowPart;
+ ov.OffsetHigh= li.HighPart;
+
+ if(!WriteFile(hFile, Buffer, (DWORD)Count, &nBytesWritten, &ov))
+ {
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+ }
+ else
+ DBUG_RETURN(nBytesWritten);
+}
+
+
+my_off_t my_win_lseek(File fd, my_off_t pos, int whence)
+{
+ LARGE_INTEGER offset;
+ LARGE_INTEGER newpos;
+
+ DBUG_ENTER("my_win_lseek");
+
+ /* Check compatibility of Windows and Posix seek constants */
+ compile_time_assert(FILE_BEGIN == SEEK_SET && FILE_CURRENT == SEEK_CUR
+ && FILE_END == SEEK_END);
+
+ offset.QuadPart= pos;
+ if(!SetFilePointerEx(my_get_osfhandle(fd), offset, &newpos, whence))
+ {
+ my_osmaperr(GetLastError());
+ newpos.QuadPart= -1;
+ }
+ DBUG_RETURN(newpos.QuadPart);
+}
+
+
+#ifndef FILE_WRITE_TO_END_OF_FILE
+#define FILE_WRITE_TO_END_OF_FILE 0xffffffff
+#endif
+size_t my_win_write(File fd, const uchar *Buffer, size_t Count)
+{
+ DWORD nWritten;
+ OVERLAPPED ov;
+ OVERLAPPED *pov= NULL;
+ HANDLE hFile;
+
+ DBUG_ENTER("my_win_write");
+ DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer,
+ (ulonglong)Count));
+ if(my_get_open_flags(fd) & _O_APPEND)
+ {
+ /*
+ Atomic append to the end of file is is done by special initialization of
+ the OVERLAPPED structure. See MSDN WriteFile documentation for more info.
+ */
+ memset(&ov, 0, sizeof(ov));
+ ov.Offset= FILE_WRITE_TO_END_OF_FILE;
+ ov.OffsetHigh= -1;
+ pov= &ov;
+ }
+
+ hFile= my_get_osfhandle(fd);
+ if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov))
+ {
+ nWritten= (size_t)-1;
+ my_osmaperr(GetLastError());
+ }
+ DBUG_RETURN((size_t)nWritten);
+}
+
+
+int my_win_chsize(File fd, my_off_t newlength)
+{
+ HANDLE hFile;
+ LARGE_INTEGER length;
+ DBUG_ENTER("my_win_chsize");
+
+ hFile= (HANDLE) my_get_osfhandle(fd);
+ length.QuadPart= newlength;
+ if (!SetFilePointerEx(hFile, length , NULL , FILE_BEGIN))
+ goto err;
+ if (!SetEndOfFile(hFile))
+ goto err;
+ DBUG_RETURN(0);
+err:
+ my_osmaperr(GetLastError());
+ my_errno= errno;
+ DBUG_RETURN(-1);
+}
+
+
+/* Get the file descriptor for stdin,stdout or stderr */
+static File my_get_stdfile_descriptor(FILE *stream)
+{
+ HANDLE hFile;
+ DWORD nStdHandle;
+ DBUG_ENTER("my_get_stdfile_descriptor");
+
+ if(stream == stdin)
+ nStdHandle= STD_INPUT_HANDLE;
+ else if(stream == stdout)
+ nStdHandle= STD_OUTPUT_HANDLE;
+ else if(stream == stderr)
+ nStdHandle= STD_ERROR_HANDLE;
+ else
+ DBUG_RETURN(-1);
+
+ hFile= GetStdHandle(nStdHandle);
+ if(hFile != INVALID_HANDLE_VALUE)
+ DBUG_RETURN(my_open_osfhandle(hFile, 0));
+ DBUG_RETURN(-1);
+}
+
+
+File my_win_fileno(FILE *file)
+{
+ HANDLE hFile= (HANDLE)_get_osfhandle(fileno(file));
+ int retval= -1;
+ uint i;
+
+ DBUG_ENTER("my_win_fileno");
+
+ for(i= MY_FILE_MIN; i < my_file_limit; i++)
+ {
+ if(my_file_info[i].fhandle == hFile)
+ {
+ retval= i;
+ break;
+ }
+ }
+ if(retval == -1)
+ /* try std stream */
+ DBUG_RETURN(my_get_stdfile_descriptor(file));
+ DBUG_RETURN(retval);
+}
+
+
+FILE *my_win_fopen(const char *filename, const char *type)
+{
+ FILE *file;
+ int flags= 0;
+ DBUG_ENTER("my_win_open");
+
+ /*
+ If we are not creating, then we need to use my_access to make sure
+ the file exists since Windows doesn't handle files like "com1.sym"
+ very well
+ */
+ if (check_if_legal_filename(filename))
+ {
+ errno= EACCES;
+ DBUG_RETURN(NULL);
+ }
+
+ file= fopen(filename, type);
+ if(!file)
+ DBUG_RETURN(NULL);
+
+ if(strchr(type,'a') != NULL)
+ flags= O_APPEND;
+
+ /*
+ Register file handle in my_table_info.
+ Necessary for my_fileno()
+ */
+ if(my_open_osfhandle((HANDLE)_get_osfhandle(fileno(file)), flags) < 0)
+ {
+ fclose(file);
+ DBUG_RETURN(NULL);
+ }
+ DBUG_RETURN(file);
+}
+
+
+FILE * my_win_fdopen(File fd, const char *type)
+{
+ FILE *file;
+ int crt_fd;
+ int flags= 0;
+
+ DBUG_ENTER("my_win_fdopen");
+
+ if(strchr(type,'a') != NULL)
+ flags= O_APPEND;
+ /* Convert OS file handle to CRT file descriptor and then call fdopen*/
+ crt_fd= _open_osfhandle((intptr_t)my_get_osfhandle(fd), flags);
+ if(crt_fd < 0)
+ file= NULL;
+ else
+ file= fdopen(crt_fd, type);
+ DBUG_RETURN(file);
+}
+
+
+int my_win_fclose(FILE *file)
+{
+ File fd;
+
+ DBUG_ENTER("my_win_close");
+ fd= my_fileno(file);
+ if(fd < 0)
+ DBUG_RETURN(-1);
+ if(fclose(file) < 0)
+ DBUG_RETURN(-1);
+ invalidate_fd(fd);
+ DBUG_RETURN(0);
+}
+
+
+
+/*
+ Quick and dirty my_fstat() implementation for Windows.
+ Use CRT fstat on temporarily allocated file descriptor.
+ Patch file size, because size that fstat returns is not
+ reliable (may be outdated)
+*/
+int my_win_fstat(File fd, struct _stati64 *buf)
+{
+ int crt_fd;
+ int retval;
+ HANDLE hFile, hDup;
+
+ DBUG_ENTER("my_win_fstat");
+
+ hFile= my_get_osfhandle(fd);
+ if(!DuplicateHandle( GetCurrentProcess(), hFile, GetCurrentProcess(),
+ &hDup ,0,FALSE,DUPLICATE_SAME_ACCESS))
+ {
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+ }
+ if ((crt_fd= _open_osfhandle((intptr_t)hDup,0)) < 0)
+ DBUG_RETURN(-1);
+
+ retval= _fstati64(crt_fd, buf);
+ if(retval == 0)
+ {
+ /* File size returned by stat is not accurate (may be outdated), fix it*/
+ GetFileSizeEx(hDup, (PLARGE_INTEGER) (&(buf->st_size)));
+ }
+ _close(crt_fd);
+ DBUG_RETURN(retval);
+}
+
+
+
+int my_win_stat( const char *path, struct _stati64 *buf)
+{
+ DBUG_ENTER("my_win_stat");
+ if(_stati64( path, buf) == 0)
+ {
+ /* File size returned by stat is not accurate (may be outdated), fix it*/
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ if (GetFileAttributesEx(path, GetFileExInfoStandard, &data))
+ {
+ LARGE_INTEGER li;
+ li.LowPart= data.nFileSizeLow;
+ li.HighPart= data.nFileSizeHigh;
+ buf->st_size= li.QuadPart;
+ }
+ DBUG_RETURN(0);
+ }
+ DBUG_RETURN(-1);
+}
+
+
+
+int my_win_fsync(File fd)
+{
+ DBUG_ENTER("my_win_fsync");
+ if(FlushFileBuffers(my_get_osfhandle(fd)))
+ DBUG_RETURN(0);
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+}
+
+
+
+int my_win_dup(File fd)
+{
+ HANDLE hDup;
+ DBUG_ENTER("my_win_dup");
+ if (DuplicateHandle(GetCurrentProcess(), my_get_osfhandle(fd),
+ GetCurrentProcess(), &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ DBUG_RETURN(my_open_osfhandle(hDup, my_get_open_flags(fd)));
+ }
+ my_osmaperr(GetLastError());
+ DBUG_RETURN(-1);
+}
+
+#endif /*_WIN32*/
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c
index e94369bec32..9e8458b0799 100644
--- a/mysys/my_winthread.c
+++ b/mysys/my_winthread.c
@@ -14,33 +14,23 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*****************************************************************************
-** Simulation of posix threads calls for WIN95 and NT
+** Simulation of posix threads calls for Windows
*****************************************************************************/
-
+#if defined (_WIN32)
/* SAFE_MUTEX will not work until the thread structure is up to date */
#undef SAFE_MUTEX
-
#include "mysys_priv.h"
-#if defined(THREAD) && defined(__WIN__)
-#include <m_string.h>
-#undef getpid
#include <process.h>
+#include <signal.h>
-static pthread_mutex_t THR_LOCK_thread;
+static void install_sigabrt_handler(void);
-struct pthread_map
+struct thread_start_parameter
{
- HANDLE pthreadself;
pthread_handler func;
- void *param;
+ void *arg;
};
-void win_pthread_init(void)
-{
- pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST);
-}
-
-
/**
Adapter to @c pthread_mutex_trylock()
@@ -62,79 +52,81 @@ win_pthread_mutex_trylock(pthread_mutex_t *mutex)
return EBUSY;
}
-
-/*
-** We have tried to use '_beginthreadex' instead of '_beginthread' here
-** but in this case the program leaks about 512 characters for each
-** created thread !
-** As we want to save the created thread handler for other threads to
-** use and to be returned by pthread_self() (instead of the Win32 pseudo
-** handler), we have to go trough pthread_start() to catch the returned handler
-** in the new thread.
-*/
-
-pthread_handler_t pthread_start(void *param)
+static unsigned int __stdcall pthread_start(void *p)
{
- pthread_handler func=((struct pthread_map *) param)->func;
- void *func_param=((struct pthread_map *) param)->param;
- my_thread_init(); /* Will always succeed in windows */
- pthread_mutex_lock(&THR_LOCK_thread); /* Wait for beginthread to return */
- win_pthread_self=((struct pthread_map *) param)->pthreadself;
- pthread_mutex_unlock(&THR_LOCK_thread);
- free((char*) param); /* Free param from create */
- pthread_exit((void*) (*func)(func_param));
- return 0; /* Safety */
+ struct thread_start_parameter *par= (struct thread_start_parameter *)p;
+ pthread_handler func= par->func;
+ void *arg= par->arg;
+ free(p);
+ (*func)(arg);
+ return 0;
}
int pthread_create(pthread_t *thread_id, pthread_attr_t *attr,
- pthread_handler func, void *param)
+ pthread_handler func, void *param)
{
- HANDLE hThread;
- struct pthread_map *map;
+ uintptr_t handle;
+ struct thread_start_parameter *par;
+ unsigned int stack_size;
DBUG_ENTER("pthread_create");
- if (!(map=malloc(sizeof(*map))))
- DBUG_RETURN(-1);
- map->func=func;
- map->param=param;
- pthread_mutex_lock(&THR_LOCK_thread);
-#ifdef __BORLANDC__
- hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start,
- attr->dwStackSize ? attr->dwStackSize :
- 65535, (void*) map);
-#else
- hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,
- attr->dwStackSize ? attr->dwStackSize :
- 65535, (void*) map);
-#endif
- DBUG_PRINT("info", ("hThread=%lu",(long) hThread));
- *thread_id=map->pthreadself=hThread;
- pthread_mutex_unlock(&THR_LOCK_thread);
+ par= (struct thread_start_parameter *)malloc(sizeof(*par));
+ if (!par)
+ goto error_return;
- if (hThread == (HANDLE) -1)
- {
- int error=errno;
- DBUG_PRINT("error",
- ("Can't create thread to handle request (error %d)",error));
- DBUG_RETURN(error ? error : -1);
- }
- VOID(SetThreadPriority(hThread, attr->priority)) ;
+ par->func= func;
+ par->arg= param;
+ stack_size= attr?attr->dwStackSize:0;
+
+ handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id);
+ if (!handle)
+ goto error_return;
+ DBUG_PRINT("info", ("thread id=%u",*thread_id));
+
+ /* Do not need thread handle, close it */
+ CloseHandle((HANDLE)handle);
DBUG_RETURN(0);
+
+error_return:
+ DBUG_PRINT("error",
+ ("Can't create thread to handle request (error %d)",errno));
+ DBUG_RETURN(-1);
}
void pthread_exit(void *a)
{
- _endthread();
+ _endthreadex(0);
}
-/* This is neaded to get the macro pthread_setspecific to work */
-
-int win_pthread_setspecific(void *a,void *b,uint length)
+int pthread_join(pthread_t thread, void **value_ptr)
{
- memcpy(a,b,length);
+ DWORD ret;
+ HANDLE handle;
+
+ handle= OpenThread(SYNCHRONIZE, FALSE, thread);
+ if (!handle)
+ {
+ errno= EINVAL;
+ goto error_return;
+ }
+
+ ret= WaitForSingleObject(handle, INFINITE);
+
+ if(ret != WAIT_OBJECT_0)
+ {
+ errno= EINVAL;
+ goto error_return;
+ }
+
+ CloseHandle(handle);
return 0;
+
+error_return:
+ if(handle)
+ CloseHandle(handle);
+ return -1;
}
#endif
diff --git a/mysys/my_write.c b/mysys/my_write.c
index d7eb390bdd2..3eac1364f46 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -20,14 +20,14 @@
/* Write a chunk of bytes to a file */
-size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
+size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
{
- size_t writenbytes, written;
+ size_t writtenbytes, written;
uint errors;
DBUG_ENTER("my_write");
- DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d",
- Filedes, (long) Buffer, (ulong) Count, MyFlags));
- errors=0; written=0;
+ DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d",
+ Filedes, Buffer, (ulong) Count, MyFlags));
+ errors= 0; written= 0;
/* The behavior of write(fd, buf, 0) is not portable */
if (unlikely(!Count))
@@ -35,17 +35,22 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
for (;;)
{
- if ((writenbytes= write(Filedes, Buffer, Count)) == Count)
+#ifdef _WIN32
+ writtenbytes= my_win_write(Filedes, Buffer, Count);
+#else
+ writtenbytes= write(Filedes, Buffer, Count);
+#endif
+ if (writtenbytes == Count)
break;
- if (writenbytes != (size_t) -1)
+ if (writtenbytes != (size_t) -1)
{ /* Safeguard */
- written+=writenbytes;
- Buffer+=writenbytes;
- Count-=writenbytes;
+ written+= writtenbytes;
+ Buffer+= writtenbytes;
+ Count-= writtenbytes;
}
- my_errno=errno;
+ my_errno= errno;
DBUG_PRINT("error",("Write only %ld bytes, error: %d",
- (long) writenbytes, my_errno));
+ (long) writtenbytes, my_errno));
#ifndef NO_BACKGROUND
#ifdef THREAD
if (my_thread_var->abort)
@@ -59,19 +64,19 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
continue;
}
- if ((writenbytes == 0 || writenbytes == (size_t) -1))
+ if ((writtenbytes == 0 || writtenbytes == (size_t) -1))
{
if (my_errno == EINTR)
{
DBUG_PRINT("debug", ("my_write() was interrupted and returned %ld",
- (long) writenbytes));
+ (long) writtenbytes));
continue; /* Interrupted */
}
- if (!writenbytes && !errors++) /* Retry once */
+ if (!writtenbytes && !errors++) /* Retry once */
{
/* We may come here if the file quota is exeeded */
- errno=EFBIG; /* Assume this is the error */
+ errno= EFBIG; /* Assume this is the error */
continue;
}
}
@@ -92,5 +97,5 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
}
if (MyFlags & (MY_NABP | MY_FNABP))
DBUG_RETURN(0); /* Want only errors */
- DBUG_RETURN(writenbytes+written);
+ DBUG_RETURN(writtenbytes+written);
} /* my_write */
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 6e0959ae08c..4c4d6ea3598 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -42,3 +42,27 @@ extern pthread_mutex_t THR_LOCK_charset, THR_LOCK_time;
#endif
void my_error_unregister_all(void);
+
+#ifdef _WIN32
+/* my_winfile.c exports, should not be used outside mysys */
+extern File my_win_open(const char *path, int oflag);
+extern int my_win_close(File fd);
+extern size_t my_win_read(File fd, uchar *buffer, size_t count);
+extern size_t my_win_write(File fd, const uchar *buffer, size_t count);
+extern size_t my_win_pread(File fd, uchar *buffer, size_t count,
+ my_off_t offset);
+extern size_t my_win_pwrite(File fd, const uchar *buffer, size_t count,
+ my_off_t offset);
+extern my_off_t my_win_lseek(File fd, my_off_t pos, int whence);
+extern int my_win_chsize(File fd, my_off_t newlength);
+extern FILE* my_win_fopen(const char *filename, const char *type);
+extern File my_win_fclose(FILE *file);
+extern File my_win_fileno(FILE *file);
+extern FILE* my_win_fdopen(File Filedes, const char *type);
+extern int my_win_stat(const char *path, struct _stat64 *buf);
+extern int my_win_fstat(File fd, struct _stat64 *buf);
+extern int my_win_fsync(File fd);
+extern File my_win_dup(File fd);
+extern File my_win_sopen(const char *path, int oflag, int shflag, int perm);
+extern File my_open_osfhandle(HANDLE handle, int oflag);
+#endif
diff --git a/netware/BUILD/compile-netware-START b/netware/BUILD/compile-netware-START
index 8f828f34bd1..414d577130e 100755
--- a/netware/BUILD/compile-netware-START
+++ b/netware/BUILD/compile-netware-START
@@ -22,6 +22,5 @@ base_configs=" \
--enable-local-infile \
--with-extra-charsets=all \
--prefix=N:/mysql \
- --without-mysqlmanager \
--without-man \
"
diff --git a/regex/CMakeLists.txt b/regex/CMakeLists.txt
index a3088c00357..a2974b45b06 100755
--- a/regex/CMakeLists.txt
+++ b/regex/CMakeLists.txt
@@ -13,8 +13,6 @@
# 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} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
-SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index f0db25be79a..25cdae2b522 100755
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -24,7 +24,7 @@ ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_SOURCE_DIR}/scripts/mysql_fix_privilege_tabl
# Build comp_sql - used for embedding SQL in C or C++ programs
ADD_EXECUTABLE(comp_sql comp_sql.c)
-TARGET_LINK_LIBRARIES(comp_sql debug dbug mysys strings)
+TARGET_LINK_LIBRARIES(comp_sql dbug mysys strings)
# Use comp_sql to build mysql_fix_privilege_tables_sql.c
GET_TARGET_PROPERTY(COMP_SQL_EXE comp_sql LOCATION)
diff --git a/server-tools/CMakeLists.txt b/server-tools/CMakeLists.txt
deleted file mode 100644
index 3f02ba88f1d..00000000000
--- a/server-tools/CMakeLists.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-# 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")
-
-ADD_DEFINITIONS(-DMYSQL_SERVER -DMYSQL_INSTANCE_MANAGER)
-INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/sql
- ${PROJECT_SOURCE_DIR}/extra/yassl/include)
-
-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
- mysqlmanager.cc options.cc parse.cc parse_output.cc priv.cc protocol.cc
- thread_registry.cc user_map.cc imservice.cpp windowsservice.cpp
- 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)
-
-ADD_DEPENDENCIES(mysqlmanager GenError)
-TARGET_LINK_LIBRARIES(mysqlmanager dbug mysys strings taocrypt vio yassl zlib wsock32)
diff --git a/server-tools/Makefile.am b/server-tools/Makefile.am
deleted file mode 100644
index 96e9d5a946e..00000000000
--- a/server-tools/Makefile.am
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (C) 2003, 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
-
-SUBDIRS = . instance-manager
-DIST_SUBDIRS = . instance-manager
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/server-tools/instance-manager/CMakeLists.txt b/server-tools/instance-manager/CMakeLists.txt
deleted file mode 100755
index 2b9bce56ff7..00000000000
--- a/server-tools/instance-manager/CMakeLists.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-# 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("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
-
-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 -DMYSQL_INSTANCE_MANAGER)
-INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/sql
- ${PROJECT_SOURCE_DIR}/extra/yassl/include)
-
-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
- mysqlmanager.cc options.cc parse.cc parse_output.cc priv.cc protocol.cc
- thread_registry.cc user_map.cc IMService.cpp WindowsService.cpp
- 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)
-
-ADD_DEPENDENCIES(mysqlmanager GenError)
-TARGET_LINK_LIBRARIES(mysqlmanager debug dbug mysys strings taocrypt vio yassl zlib wsock32)
-
-IF(EMBED_MANIFESTS)
- MYSQL_EMBED_MANIFEST("mysqlmanager" "asInvoker")
-ENDIF(EMBED_MANIFESTS)
diff --git a/server-tools/instance-manager/IMService.cpp b/server-tools/instance-manager/IMService.cpp
deleted file mode 100644
index feccaadbecc..00000000000
--- a/server-tools/instance-manager/IMService.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/* Copyright (C) 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include <winsock2.h>
-#include <signal.h>
-
-#include "IMService.h"
-
-#include "log.h"
-#include "manager.h"
-#include "options.h"
-
-static const char * const IM_SVC_USERNAME= NULL;
-static const char * const IM_SVC_PASSWORD= NULL;
-
-IMService::IMService(void)
- :WindowsService("MySqlManager", "MySQL Manager")
-{
-}
-
-IMService::~IMService(void)
-{
-}
-
-void IMService::Stop()
-{
- ReportStatus(SERVICE_STOP_PENDING);
-
- /* stop the IM work */
- raise(SIGTERM);
-}
-
-void IMService::Run(DWORD argc, LPTSTR *argv)
-{
- /* report to the SCM that we're about to start */
- ReportStatus((DWORD)SERVICE_START_PENDING);
-
- Options::load(argc, argv);
-
- /* init goes here */
- ReportStatus((DWORD)SERVICE_RUNNING);
-
- /* wait for main loop to terminate */
- (void) Manager::main();
- Options::cleanup();
-}
-
-void IMService::Log(const char *msg)
-{
- log_info(msg);
-}
-
-int IMService::main()
-{
- IMService winService;
-
- if (Options::Service::install_as_service)
- {
- if (winService.IsInstalled())
- {
- log_info("Service is already installed.");
- return 1;
- }
-
- if (winService.Install(IM_SVC_USERNAME, IM_SVC_PASSWORD))
- {
- log_info("Service installed successfully.");
- return 0;
- }
- else
- {
- log_error("Service failed to install.");
- return 1;
- }
- }
-
- if (Options::Service::remove_service)
- {
- if (!winService.IsInstalled())
- {
- log_info("Service is not installed.");
- return 1;
- }
-
- if (winService.Remove())
- {
- log_info("Service removed successfully.");
- return 0;
- }
- else
- {
- log_error("Service failed to remove.");
- return 1;
- }
- }
-
- log_info("Initializing Instance Manager service...");
-
- if (!winService.Init())
- {
- log_error("Service failed to initialize.");
-
- fprintf(stderr,
- "The service should be started by Windows Service Manager.\n"
- "The MySQL Manager should be started with '--standalone'\n"
- "to run from command line.");
-
- return 1;
- }
-
- return 0;
-}
diff --git a/server-tools/instance-manager/IMService.h b/server-tools/instance-manager/IMService.h
deleted file mode 100644
index aceafb2fca6..00000000000
--- a/server-tools/instance-manager/IMService.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#pragma once
-#include "WindowsService.h"
-
-class IMService: public WindowsService
-{
-public:
- static int main();
-
-private:
- IMService(void);
- ~IMService(void);
-
-protected:
- void Log(const char *msg);
- void Stop();
- void Run(DWORD argc, LPTSTR *argv);
-};
diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am
deleted file mode 100644
index 19c4ac8de19..00000000000
--- a/server-tools/instance-manager/Makefile.am
+++ /dev/null
@@ -1,103 +0,0 @@
-# Copyright (C) 2004 MySQL AB
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; 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
-
-INCLUDES= @ZLIB_INCLUDES@ -I$(top_srcdir)/include \
- @openssl_includes@ -I$(top_builddir)/include
-
-DEFS= -DMYSQL_INSTANCE_MANAGER -DMYSQL_SERVER
-
-# As all autoconf variables depend from ${prefix} and being resolved only when
-# make is run, we can not put these defines to a header file (e.g. to
-# default_options.h, generated from default_options.h.in)
-# See automake/autoconf docs for details
-
-noinst_LTLIBRARIES= liboptions.la
-noinst_LIBRARIES= libnet.a
-
-liboptions_la_CXXFLAGS= $(CXXFLAGS) \
- -DDEFAULT_PID_FILE_NAME="$(localstatedir)/mysqlmanager.pid" \
- -DDEFAULT_LOG_FILE_NAME="$(localstatedir)/mysqlmanager.log" \
- -DDEFAULT_SOCKET_FILE_NAME="/tmp/mysqlmanager.sock" \
- -DDEFAULT_PASSWORD_FILE_NAME="/etc/mysqlmanager.passwd" \
- -DDEFAULT_MYSQLD_PATH="$(libexecdir)/mysqld$(EXEEXT)" \
- -DDEFAULT_CONFIG_FILE="my.cnf" \
- -DPROTOCOL_VERSION=@PROTOCOL_VERSION@
-
-liboptions_la_SOURCES= options.h options.cc priv.h priv.cc
-liboptions_la_LIBADD= $(top_builddir)/libmysql/get_password.lo
-
-# MySQL sometimes uses symlinks to reuse code
-# All symlinked files are grouped in libnet.a
-
-nodist_libnet_a_SOURCES= net_serv.cc client_settings.h
-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)
-
-CLEANFILES= net_serv.cc client_settings.h
-
-net_serv.cc:
- rm -f net_serv.cc
- @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc net_serv.cc
-
-client_settings.h:
- rm -f client_settings.h
- @LN_CP_F@ $(top_srcdir)/sql/client_settings.h client_settings.h
-
-libexec_PROGRAMS= mysqlmanager
-
-mysqlmanager_CXXFLAGS=
-
-mysqlmanager_SOURCES= command.cc command.h mysqlmanager.cc \
- manager.h manager.cc log.h log.cc \
- thread_registry.h thread_registry.cc \
- listener.h listener.cc protocol.h protocol.cc \
- mysql_connection.h mysql_connection.cc \
- user_map.h user_map.cc \
- messages.h messages.cc \
- commands.h commands.cc \
- instance.h instance.cc \
- instance_map.h instance_map.cc\
- instance_options.h instance_options.cc \
- buffer.h buffer.cc parse.cc parse.h \
- guardian.cc guardian.h \
- parse_output.cc parse_output.h \
- mysql_manager_error.h \
- portability.h \
- exit_codes.h \
- user_management_commands.h \
- user_management_commands.cc \
- angel.h \
- angel.cc
-
-mysqlmanager_LDADD= @CLIENT_EXTRA_LDFLAGS@ \
- liboptions.la \
- libnet.a \
- $(top_builddir)/vio/libvio.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a \
- $(top_builddir)/dbug/libdbug.a \
- @openssl_libs@ @yassl_libs@ @ZLIB_LIBS@
-
-EXTRA_DIST = WindowsService.cpp WindowsService.h IMService.cpp \
- IMService.h CMakeLists.txt
-
-tags:
- ctags -R *.h *.cc
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/server-tools/instance-manager/README b/server-tools/instance-manager/README
deleted file mode 100644
index ac799775003..00000000000
--- a/server-tools/instance-manager/README
+++ /dev/null
@@ -1,11 +0,0 @@
-Instance Manager - manage MySQL instances locally and remotely.
-
-File description:
- mysqlmanager.cc - entry point to the manager, main,
- options.{h,cc} - handle startup options
- manager.{h,cc} - manager process
- mysql_connection.{h,cc} - handle one connection with mysql client.
-
-See also instance manager architecture description in mysqlmanager.cc.
-
-
diff --git a/server-tools/instance-manager/WindowsService.cpp b/server-tools/instance-manager/WindowsService.cpp
deleted file mode 100644
index 14795e2225a..00000000000
--- a/server-tools/instance-manager/WindowsService.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-/* Copyright (C) 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#include "my_global.h"
-#include <windows.h>
-#include "WindowsService.h"
-
-static WindowsService *gService;
-
-WindowsService::WindowsService(const char *p_serviceName,
- const char *p_displayName) :
- statusCheckpoint(0),
- serviceName(p_serviceName),
- displayName(p_displayName),
- inited(FALSE),
- dwAcceptedControls(SERVICE_ACCEPT_STOP),
- debugging(FALSE)
-{
- DBUG_ASSERT(serviceName != NULL);
-
- /* TODO: shouldn't we check displayName too (can it really be NULL)? */
-
- /* WindowsService is assumed to be singleton. Let's assure this. */
- DBUG_ASSERT(gService == NULL);
-
- gService= this;
-
- status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
- status.dwServiceSpecificExitCode= 0;
-}
-
-WindowsService::~WindowsService(void)
-{
-}
-
-BOOL WindowsService::Install(const char *username, const char *password)
-{
- bool ret_val= FALSE;
- SC_HANDLE newService;
- SC_HANDLE scm;
-
- if (IsInstalled())
- return TRUE;
-
- // determine the name of the currently executing file
- char szFilePath[_MAX_PATH];
- GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
-
- // open a connection to the SCM
- if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
- return FALSE;
-
- newService= CreateService(scm, serviceName, displayName,
- SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
- SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
- szFilePath, NULL, NULL, NULL, username,
- password);
-
- if (newService)
- {
- CloseServiceHandle(newService);
- ret_val= TRUE;
- }
-
- CloseServiceHandle(scm);
- return ret_val;
-}
-
-BOOL WindowsService::Init()
-{
- DBUG_ASSERT(serviceName != NULL);
-
- if (inited)
- return TRUE;
-
- SERVICE_TABLE_ENTRY stb[] =
- {
- { (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
- { NULL, NULL }
- };
- inited= TRUE;
- return StartServiceCtrlDispatcher(stb); //register with the Service Manager
-}
-
-BOOL WindowsService::Remove()
-{
- bool ret_val= FALSE;
-
- if (!IsInstalled())
- return TRUE;
-
- // open a connection to the SCM
- SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
- if (!scm)
- return FALSE;
-
- SC_HANDLE service= OpenService(scm, serviceName, DELETE);
- if (service)
- {
- if (DeleteService(service))
- ret_val= TRUE;
- DWORD dw= ::GetLastError();
- CloseServiceHandle(service);
- }
-
- CloseServiceHandle(scm);
- return ret_val;
-}
-
-BOOL WindowsService::IsInstalled()
-{
- BOOL ret_val= FALSE;
-
- SC_HANDLE scm= ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
- SC_HANDLE serv_handle= ::OpenService(scm, serviceName, SERVICE_QUERY_STATUS);
-
- ret_val= serv_handle != NULL;
-
- ::CloseServiceHandle(serv_handle);
- ::CloseServiceHandle(scm);
-
- return ret_val;
-}
-
-void WindowsService::SetAcceptedControls(DWORD acceptedControls)
-{
- dwAcceptedControls= acceptedControls;
-}
-
-
-BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint,
- DWORD dwError)
-{
- if (debugging)
- return TRUE;
-
- if(currentState == SERVICE_START_PENDING)
- status.dwControlsAccepted= 0;
- else
- status.dwControlsAccepted= dwAcceptedControls;
-
- status.dwCurrentState= currentState;
- status.dwWin32ExitCode= dwError != 0 ?
- ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR;
- status.dwWaitHint= waitHint;
- status.dwServiceSpecificExitCode= dwError;
-
- if(currentState == SERVICE_RUNNING || currentState == SERVICE_STOPPED)
- {
- status.dwCheckPoint= 0;
- statusCheckpoint= 0;
- }
- else
- status.dwCheckPoint= ++statusCheckpoint;
-
- // Report the status of the service to the service control manager.
- BOOL result= SetServiceStatus(statusHandle, &status);
- if (!result)
- Log("ReportStatus failed");
-
- return result;
-}
-
-void WindowsService::RegisterAndRun(DWORD argc, LPTSTR *argv)
-{
- statusHandle= ::RegisterServiceCtrlHandler(serviceName, ControlHandler);
- if (statusHandle && ReportStatus(SERVICE_START_PENDING))
- Run(argc, argv);
- ReportStatus(SERVICE_STOPPED);
-}
-
-void WindowsService::HandleControlCode(DWORD opcode)
-{
- // Handle the requested control code.
- switch(opcode) {
- case SERVICE_CONTROL_STOP:
- // Stop the service.
- status.dwCurrentState= SERVICE_STOP_PENDING;
- Stop();
- break;
-
- case SERVICE_CONTROL_PAUSE:
- status.dwCurrentState= SERVICE_PAUSE_PENDING;
- Pause();
- break;
-
- case SERVICE_CONTROL_CONTINUE:
- status.dwCurrentState= SERVICE_CONTINUE_PENDING;
- Continue();
- break;
-
- case SERVICE_CONTROL_SHUTDOWN:
- Shutdown();
- break;
-
- case SERVICE_CONTROL_INTERROGATE:
- ReportStatus(status.dwCurrentState);
- break;
-
- default:
- // invalid control code
- break;
- }
-}
-
-void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
-{
- DBUG_ASSERT(gService != NULL);
-
- // register our service control handler:
- gService->RegisterAndRun(argc, argv);
-}
-
-void WINAPI WindowsService::ControlHandler(DWORD opcode)
-{
- DBUG_ASSERT(gService != NULL);
-
- return gService->HandleControlCode(opcode);
-}
diff --git a/server-tools/instance-manager/WindowsService.h b/server-tools/instance-manager/WindowsService.h
deleted file mode 100644
index 02a499e5f0c..00000000000
--- a/server-tools/instance-manager/WindowsService.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (C) 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#pragma once
-
-class WindowsService
-{
-protected:
- bool inited;
- const char *serviceName;
- const char *displayName;
- SERVICE_STATUS_HANDLE statusHandle;
- DWORD statusCheckpoint;
- SERVICE_STATUS status;
- DWORD dwAcceptedControls;
- bool debugging;
-
-public:
- WindowsService(const char *p_serviceName, const char *p_displayName);
- ~WindowsService(void);
-
- BOOL Install(const char *username, const char *password);
- BOOL Remove();
- BOOL Init();
- BOOL IsInstalled();
- void SetAcceptedControls(DWORD acceptedControls);
- void Debug(bool debugFlag) { debugging= debugFlag; }
-
-public:
- static void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
- static void WINAPI ControlHandler(DWORD CtrlType);
-
-protected:
- virtual void Run(DWORD argc, LPTSTR *argv)= 0;
- virtual void Stop() {}
- virtual void Shutdown() {}
- virtual void Pause() {}
- virtual void Continue() {}
- virtual void Log(const char *msg) {}
-
- BOOL ReportStatus(DWORD currentStatus, DWORD waitHint= 3000, DWORD dwError=0);
- void HandleControlCode(DWORD opcode);
- void RegisterAndRun(DWORD argc, LPTSTR *argv);
-};
diff --git a/server-tools/instance-manager/angel.cc b/server-tools/instance-manager/angel.cc
deleted file mode 100644
index 64515c8498c..00000000000
--- a/server-tools/instance-manager/angel.cc
+++ /dev/null
@@ -1,407 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#ifndef __WIN__
-
-#include "angel.h"
-
-#include <sys/wait.h>
-/*
- sys/wait.h is needed for waitpid(). Unfortunately, there is no MySQL
- include file, that can serve for this. Include it before MySQL system
- headers so that we can change system defines if needed.
-*/
-
-#include "my_global.h"
-#include "my_alarm.h"
-#include "my_dir.h"
-#include "my_sys.h"
-
-/* Include other IM files. */
-
-#include "log.h"
-#include "manager.h"
-#include "options.h"
-#include "priv.h"
-
-/************************************************************************/
-
-enum { CHILD_OK= 0, CHILD_NEED_RESPAWN, CHILD_EXIT_ANGEL };
-
-static int log_fd;
-
-static volatile sig_atomic_t child_status= CHILD_OK;
-static volatile sig_atomic_t child_exit_code= 0;
-static volatile sig_atomic_t shutdown_request_signo= 0;
-
-
-/************************************************************************/
-/**
- Open log file.
-
- @return
- TRUE on error;
- FALSE on success.
-*************************************************************************/
-
-static bool open_log_file()
-{
- log_info("Angel: opening log file '%s'...",
- (const char *) Options::Daemon::log_file_name);
-
- log_fd= open(Options::Daemon::log_file_name,
- O_WRONLY | O_CREAT | O_APPEND | O_NOCTTY,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
-
- if (log_fd < 0)
- {
- log_error("Can not open log file '%s': %s.",
- (const char *) Options::Daemon::log_file_name,
- (const char *) strerror(errno));
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/************************************************************************/
-/**
- Detach the process from controlling tty.
-
- @return
- TRUE on error;
- FALSE on success.
-*************************************************************************/
-
-static bool detach_process()
-{
- /*
- Become a session leader (the goal is not to have a controlling tty).
-
- setsid() must succeed because child is guaranteed not to be a process
- group leader (it belongs to the process group of the parent).
-
- NOTE: if we now don't have a controlling tty we will not receive
- tty-related signals - no need to ignore them.
- */
-
- if (setsid() < 0)
- {
- log_error("setsid() failed: %s.", (const char *) strerror(errno));
- return -1;
- }
-
- /* Close STDIN. */
-
- log_info("Angel: preparing standard streams.");
-
- if (close(STDIN_FILENO) < 0)
- {
- log_error("Warning: can not close stdin (%s)."
- "Trying to continue...",
- (const char *) strerror(errno));
- }
-
- /* Dup STDOUT and STDERR to the log file. */
-
- if (dup2(log_fd, STDOUT_FILENO) < 0 ||
- dup2(log_fd, STDERR_FILENO) < 0)
- {
- log_error("Can not redirect stdout and stderr to the log file: %s.",
- (const char *) strerror(errno));
-
- return TRUE;
- }
-
- if (log_fd != STDOUT_FILENO && log_fd != STDERR_FILENO)
- {
- if (close(log_fd) < 0)
- {
- log_error("Can not close original log file handler (%d): %s. "
- "Trying to continue...",
- (int) log_fd,
- (const char *) strerror(errno));
- }
- }
-
- return FALSE;
-}
-
-
-/************************************************************************/
-/**
- Create PID file.
-
- @return
- TRUE on error;
- FALSE on success.
-*************************************************************************/
-
-static bool create_pid_file()
-{
- if (create_pid_file(Options::Daemon::angel_pid_file_name, getpid()))
- {
- log_error("Angel: can not create pid file (%s).",
- (const char *) Options::Daemon::angel_pid_file_name);
-
- return TRUE;
- }
-
- log_info("Angel: pid file (%s) created.",
- (const char *) Options::Daemon::angel_pid_file_name);
-
- return FALSE;
-}
-
-
-/************************************************************************/
-/**
- SIGCHLD handler.
-
- Reap child, analyze child exit code, and set child_status
- appropriately.
-*************************************************************************/
-
-extern "C" void reap_child(int);
-
-void reap_child(int __attribute__((unused)) signo)
-{
- /* NOTE: As we have only one child, no need to cycle waitpid(). */
-
- int exit_code;
-
- if (waitpid(0, &exit_code, WNOHANG) > 0)
- {
- child_exit_code= exit_code;
- child_status= exit_code ? CHILD_NEED_RESPAWN : CHILD_EXIT_ANGEL;
- }
-}
-
-
-/************************************************************************/
-/**
- SIGTERM, SIGHUP, SIGINT handler.
-
- Set termination status and return.
-*************************************************************************/
-
-extern "C" void terminate(int signo);
-void terminate(int signo)
-{
- shutdown_request_signo= signo;
-}
-
-
-/************************************************************************/
-/**
- Angel main loop.
-
- @return
- The function returns exit status for global main():
- 0 -- program completed successfully;
- !0 -- error occurred.
-*************************************************************************/
-
-static int angel_main_loop()
-{
- /*
- Install signal handlers.
-
- NOTE: Although signal handlers are needed only for parent process
- (IM-angel), we should install them before fork() in order to avoid race
- condition (i.e. to be sure, that IM-angel will receive SIGCHLD in any
- case).
- */
-
- sigset_t wait_for_signals_mask;
-
- struct sigaction sa_chld;
- struct sigaction sa_term;
- struct sigaction sa_chld_orig;
- struct sigaction sa_term_orig;
- struct sigaction sa_int_orig;
- struct sigaction sa_hup_orig;
-
- log_info("Angel: setting necessary signal actions...");
-
- sigemptyset(&wait_for_signals_mask);
-
- sigemptyset(&sa_chld.sa_mask);
- sa_chld.sa_handler= reap_child;
- sa_chld.sa_flags= SA_NOCLDSTOP;
-
- sigemptyset(&sa_term.sa_mask);
- sa_term.sa_handler= terminate;
- sa_term.sa_flags= 0;
-
- /* NOTE: sigaction() fails only if arguments are wrong. */
-
- sigaction(SIGCHLD, &sa_chld, &sa_chld_orig);
- sigaction(SIGTERM, &sa_term, &sa_term_orig);
- sigaction(SIGINT, &sa_term, &sa_int_orig);
- sigaction(SIGHUP, &sa_term, &sa_hup_orig);
-
- /* The main Angel loop. */
-
- while (true)
- {
- /* Spawn a new Manager. */
-
- log_info("Angel: forking Manager process...");
-
- switch (fork()) {
- case -1:
- log_error("Angel: can not fork IM-main: %s.",
- (const char *) strerror(errno));
-
- return -1;
-
- case 0:
- /*
- We are in child process, which will be IM-main:
- - Restore default signal actions to let the IM-main work with
- signals as he wishes;
- - Call Manager::main();
- */
-
- log_info("Angel: Manager process created successfully.");
-
- /* NOTE: sigaction() fails only if arguments are wrong. */
-
- sigaction(SIGCHLD, &sa_chld_orig, NULL);
- sigaction(SIGTERM, &sa_term_orig, NULL);
- sigaction(SIGINT, &sa_int_orig, NULL);
- sigaction(SIGHUP, &sa_hup_orig, NULL);
-
- log_info("Angel: executing Manager...");
-
- return Manager::main();
- }
-
- /* Wait for signals. */
-
- log_info("Angel: waiting for signals...");
-
- while (child_status == CHILD_OK && shutdown_request_signo == 0)
- sigsuspend(&wait_for_signals_mask);
-
- /* Exit if one of shutdown signals has been caught. */
-
- if (shutdown_request_signo)
- {
- log_info("Angel: received shutdown signal (%d). Exiting...",
- (int) shutdown_request_signo);
-
- return 0;
- }
-
- /* Manager process died. Respawn it if it was a failure. */
-
- if (child_status == CHILD_NEED_RESPAWN)
- {
- child_status= CHILD_OK;
-
- log_error("Angel: Manager exited abnormally (exit code: %d).",
- (int) child_exit_code);
-
- log_info("Angel: sleeping 1 second...");
-
- sleep(1); /* don't respawn too fast */
-
- log_info("Angel: respawning Manager...");
-
- continue;
- }
-
- /* Delete IM-angel PID file. */
-
- my_delete(Options::Daemon::angel_pid_file_name, MYF(0));
-
- /* IM-angel finished. */
-
- log_info("Angel: Manager exited normally. Exiting...");
-
- return 0;
- }
-}
-
-
-/************************************************************************/
-/**
- Angel main function.
-
- @return
- The function returns exit status for global main():
- 0 -- program completed successfully;
- !0 -- error occurred.
-*************************************************************************/
-
-int Angel::main()
-{
- log_info("Angel: started.");
-
- /* Open log file. */
-
- if (open_log_file())
- return -1;
-
- /* Fork a new process. */
-
- log_info("Angel: daemonizing...");
-
- switch (fork()) {
- case -1:
- /*
- This is the main Instance Manager process, fork() failed.
- Log an error and bail out with error code.
- */
-
- log_error("fork() failed: %s.", (const char *) strerror(errno));
- return -1;
-
- case 0:
- /* We are in child process. Continue Angel::main() execution. */
-
- break;
-
- default:
- /*
- We are in the parent process. Return 0 so that parent exits
- successfully.
- */
-
- log_info("Angel: exiting from the original process...");
-
- return 0;
- }
-
- /* Detach child from controlling tty. */
-
- if (detach_process())
- return -1;
-
- /* Create PID file. */
-
- if (create_pid_file())
- return -1;
-
- /* Start Angel main loop. */
-
- return angel_main_loop();
-}
-
-#endif // __WIN__
diff --git a/server-tools/instance-manager/angel.h b/server-tools/instance-manager/angel.h
deleted file mode 100644
index db21c250972..00000000000
--- a/server-tools/instance-manager/angel.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#ifndef INCLUDES_MYSQL_ANGEL_H
-#define INCLUDES_MYSQL_ANGEL_H
-
-#ifndef __WIN__
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-#include <my_global.h>
-
-class Angel
-{
-public:
- static int main();
-};
-
-#endif // INCLUDES_MYSQL_ANGEL_H
-#endif // __WIN__
diff --git a/server-tools/instance-manager/buffer.cc b/server-tools/instance-manager/buffer.cc
deleted file mode 100644
index f197f42d009..00000000000
--- a/server-tools/instance-manager/buffer.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "buffer.h"
-#include <m_string.h>
-
-const uint Buffer::BUFFER_INITIAL_SIZE= 4096;
-const uint Buffer::MAX_BUFFER_SIZE= 16777216;
-
-/*
- Puts the given string to the buffer.
-
- SYNOPSIS
- append()
- position start position in the buffer
- string string to be put in the buffer
- len_arg the length of the string. This way we can avoid some
- strlens.
-
- DESCRIPTION
-
- The method puts a string into the buffer, starting from position .
- In the case when the buffer is too small it reallocs the buffer. The
- total size of the buffer is restricted with 16.
-
- RETURN
- 0 - ok
- 1 - got an error in reserve()
-*/
-
-int Buffer::append(size_t position, const char *string, size_t len_arg)
-{
- if (reserve(position, len_arg))
- return 1;
-
- strnmov((char*) buffer + position, string, len_arg);
- return 0;
-}
-
-
-/*
- Checks whether the current buffer size is ok to put a string of the length
- "len_arg" starting from "position" and reallocs it if no.
-
- SYNOPSIS
- reserve()
- position the number starting byte on the buffer to store a buffer
- len_arg the length of the string.
-
- DESCRIPTION
-
- The method checks whether it is possible to put a string of the "len_arg"
- length into the buffer, starting from "position" byte. In the case when the
- buffer is too small it reallocs the buffer. The total size of the buffer is
- restricted with 16 Mb.
-
- RETURN
- 0 - ok
- 1 - realloc error or we have come to the 16Mb barrier
-*/
-
-int Buffer::reserve(size_t position, size_t len_arg)
-{
- if (position + len_arg >= MAX_BUFFER_SIZE)
- goto err;
-
- if (position + len_arg >= buffer_size)
- {
- buffer= (uchar*) my_realloc(buffer,
- min(MAX_BUFFER_SIZE,
- max((uint) (buffer_size*1.5),
- position + len_arg)), MYF(0));
- if (!(buffer))
- goto err;
- buffer_size= (size_t) (buffer_size*1.5);
- }
- return 0;
-
-err:
- error= 1;
- return 1;
-}
-
-
-int Buffer::get_size()
-{
- return (uint) buffer_size;
-}
-
-
-int Buffer::is_error()
-{
- return error;
-}
diff --git a/server-tools/instance-manager/buffer.h b/server-tools/instance-manager/buffer.h
deleted file mode 100644
index 3bd7a714437..00000000000
--- a/server-tools/instance-manager/buffer.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_BUFFER_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_BUFFER_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 <my_sys.h>
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-/*
- This class is a simple implementation of the buffer of varying size.
- It is used to store MySQL client-server protocol packets. This is why
- the maximum buffer size if 16Mb. (See internals manual section
- 7. MySQL Client/Server Protocol)
-*/
-
-class Buffer
-{
-private:
- static const uint BUFFER_INITIAL_SIZE;
- /* maximum buffer size is 16Mb */
- static const uint MAX_BUFFER_SIZE;
- size_t buffer_size;
- /* Error flag. Triggered if we get an error of some kind */
- int error;
-public:
- Buffer(size_t buffer_size_arg= BUFFER_INITIAL_SIZE)
- :buffer_size(buffer_size_arg), error(0)
- {
- /*
- As append() will invokes realloc() anyway, it's ok if malloc returns 0
- */
- if (!(buffer= (uchar*) my_malloc(buffer_size, MYF(0))))
- buffer_size= 0;
- }
-
- ~Buffer()
- {
- my_free(buffer, MYF(0));
- }
-
-public:
- uchar *buffer;
- int get_size();
- int is_error();
- int append(size_t position, const char *string, size_t len_arg);
- int reserve(size_t position, size_t len_arg);
-};
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_BUFFER_H */
diff --git a/server-tools/instance-manager/command.cc b/server-tools/instance-manager/command.cc
deleted file mode 100644
index ba84285ead2..00000000000
--- a/server-tools/instance-manager/command.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "manager.h"
-#include "command.h"
-
-Command::Command()
- :guardian(Manager::get_guardian()),
- instance_map(Manager::get_instance_map())
-{}
-
-Command::~Command()
-{}
-
diff --git a/server-tools/instance-manager/command.h b/server-tools/instance-manager/command.h
deleted file mode 100644
index 25d8c9849e8..00000000000
--- a/server-tools/instance-manager/command.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_COMMAND_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_COMMAND_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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>
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-/* Class responsible for allocation of IM commands. */
-
-class Guardian;
-class Instance_map;
-
-struct st_net;
-
-/*
- Command - entry point for any command.
- GangOf4: 'Command' design pattern
-*/
-
-class Command
-{
-public:
- Command();
- virtual ~Command();
-
- /*
- This operation incapsulates behaviour of the command.
-
- SYNOPSIS
- net The network connection to the client.
- connection_id Client connection ID
-
- RETURN
- 0 On success
- non 0 On error. Client error code is returned.
- */
- virtual int execute(st_net *net, ulong connection_id) = 0;
-
-protected:
- Guardian *guardian;
- Instance_map *instance_map;
-};
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMAND_H */
diff --git a/server-tools/instance-manager/commands.cc b/server-tools/instance-manager/commands.cc
deleted file mode 100644
index 56bd720b3e9..00000000000
--- a/server-tools/instance-manager/commands.cc
+++ /dev/null
@@ -1,1752 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "commands.h"
-
-#include <my_global.h>
-#include <m_ctype.h>
-#include <mysql.h>
-#include <my_dir.h>
-
-#include "buffer.h"
-#include "guardian.h"
-#include "instance_map.h"
-#include "log.h"
-#include "manager.h"
-#include "messages.h"
-#include "mysqld_error.h"
-#include "mysql_manager_error.h"
-#include "options.h"
-#include "priv.h"
-#include "protocol.h"
-
-/**************************************************************************
- {{{ Static functions.
-**************************************************************************/
-
-/**
- modify_defaults_to_im_error -- a map of error codes of
- mysys::modify_defaults_file() into Instance Manager error codes.
-*/
-
-static const int modify_defaults_to_im_error[]= { 0, ER_OUT_OF_RESOURCES,
- ER_ACCESS_OPTION_FILE };
-
-
-/**
- Parse version number from the version string.
-
- SYNOPSIS
- parse_version_number()
- version_str
- version
- version_size
-
- DESCRIPTION
- TODO
-
- TODO: Move this function to Instance_options and parse version number
- only once.
-
- NOTE: This function is used only in SHOW INSTANCE STATUS statement at the
- moment.
-*/
-
-static int parse_version_number(const char *version_str, char *version,
- uint version_size)
-{
- const char *start= version_str;
- const char *end;
-
- // skip garbage
- while (!my_isdigit(default_charset_info, *start))
- start++;
-
- end= start;
- // skip digits and dots
- while (my_isdigit(default_charset_info, *end) || *end == '.')
- end++;
-
- if ((uint)(end - start) >= version_size)
- return -1;
-
- strncpy(version, start, end-start);
- version[end-start]= '\0';
-
- return 0;
-}
-
-/**************************************************************************
- }}}
-**************************************************************************/
-
-/**************************************************************************
- Implementation of Instance_name.
-**************************************************************************/
-
-Instance_name::Instance_name(const LEX_STRING *name)
-{
- str.str= str_buffer;
- str.length= name->length;
-
- if (str.length > MAX_INSTANCE_NAME_SIZE - 1)
- str.length= MAX_INSTANCE_NAME_SIZE - 1;
-
- strmake(str.str, name->str, str.length);
-}
-
-/**************************************************************************
- Implementation of Show_instances.
-**************************************************************************/
-
-/**
- Implementation of SHOW INSTANCES statement.
-
- Possible error codes:
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Show_instances::execute(st_net *net, ulong /* connection_id */)
-{
- int err_code;
-
- if ((err_code= write_header(net)) ||
- (err_code= write_data(net)))
- return err_code;
-
- if (send_eof(net) || net_flush(net))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-int Show_instances::write_header(st_net *net)
-{
- LIST name, state;
- LEX_STRING name_field, state_field;
- LIST *field_list;
-
- name_field.str= (char *) "instance_name";
- name_field.length= DEFAULT_FIELD_LENGTH;
- name.data= &name_field;
-
- state_field.str= (char *) "state";
- state_field.length= DEFAULT_FIELD_LENGTH;
- state.data= &state_field;
-
- field_list= list_add(NULL, &state);
- field_list= list_add(field_list, &name);
-
- return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
-}
-
-
-int Show_instances::write_data(st_net *net)
-{
- my_bool err_status= FALSE;
-
- Instance *instance;
- Instance_map::Iterator iterator(instance_map);
-
- instance_map->lock();
-
- while ((instance= iterator.next()))
- {
- Buffer send_buf; /* buffer for packets */
- size_t pos= 0;
-
- instance->lock();
-
- const char *instance_name= instance->options.instance_name.str;
- const char *state_name= instance->get_state_name();
-
- if (store_to_protocol_packet(&send_buf, instance_name, &pos) ||
- store_to_protocol_packet(&send_buf, state_name, &pos) ||
- my_net_write(net, send_buf.buffer, pos))
- {
- err_status= TRUE;
- }
-
- instance->unlock();
-
- if (err_status)
- break;
- }
-
- instance_map->unlock();
-
- return err_status ? ER_OUT_OF_RESOURCES : 0;
-}
-
-
-/**************************************************************************
- Implementation of Flush_instances.
-**************************************************************************/
-
-/**
- Implementation of FLUSH INSTANCES statement.
-
- Possible error codes:
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
- ER_THERE_IS_ACTIVE_INSTACE If there is an active instance
-*/
-
-int Flush_instances::execute(st_net *net, ulong connection_id)
-{
- int err_status= Manager::flush_instances();
-
- if (err_status)
- return err_status;
-
- return net_send_ok(net, connection_id, NULL) ? ER_OUT_OF_RESOURCES : 0;
-}
-
-
-/**************************************************************************
- Implementation of Instance_cmd.
-**************************************************************************/
-
-Instance_cmd::Instance_cmd(const LEX_STRING *instance_name_arg):
- instance_name(instance_name_arg)
-{
- /*
- MT-NOTE: we can not make a search for Instance object here,
- because it can dissappear after releasing the lock.
- */
-}
-
-
-/**************************************************************************
- Implementation of Abstract_instance_cmd.
-**************************************************************************/
-
-Abstract_instance_cmd::Abstract_instance_cmd(
- const LEX_STRING *instance_name_arg)
- :Instance_cmd(instance_name_arg)
-{
-}
-
-
-int Abstract_instance_cmd::execute(st_net *net, ulong connection_id)
-{
- int err_code;
- Instance *instance;
-
- instance_map->lock();
-
- instance= instance_map->find(get_instance_name());
-
- if (!instance)
- {
- instance_map->unlock();
- return ER_BAD_INSTANCE_NAME;
- }
-
- instance->lock();
- instance_map->unlock();
-
- err_code= execute_impl(net, instance);
-
- instance->unlock();
-
- if (!err_code)
- err_code= send_ok_response(net, connection_id);
-
- return err_code;
-}
-
-
-/**************************************************************************
- Implementation of Show_instance_status.
-**************************************************************************/
-
-Show_instance_status::Show_instance_status(const LEX_STRING *instance_name_arg)
- :Abstract_instance_cmd(instance_name_arg)
-{
-}
-
-
-/**
- Implementation of SHOW INSTANCE STATUS statement.
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance with the given name does not exist
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Show_instance_status::execute_impl(st_net *net, Instance *instance)
-{
- int err_code;
-
- if ((err_code= write_header(net)) ||
- (err_code= write_data(net, instance)))
- return err_code;
-
- return 0;
-}
-
-
-int Show_instance_status::send_ok_response(st_net *net,
- ulong /* connection_id */)
-{
- if (send_eof(net) || net_flush(net))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-int Show_instance_status::write_header(st_net *net)
-{
- LIST name, state, version, version_number, mysqld_compatible;
- LIST *field_list;
- LEX_STRING name_field, state_field, version_field,
- version_number_field, mysqld_compatible_field;
-
- /* Create list of the fileds to be passed to send_fields(). */
-
- name_field.str= (char *) "instance_name";
- name_field.length= DEFAULT_FIELD_LENGTH;
- name.data= &name_field;
-
- state_field.str= (char *) "state";
- state_field.length= DEFAULT_FIELD_LENGTH;
- state.data= &state_field;
-
- version_field.str= (char *) "version";
- version_field.length= MAX_VERSION_LENGTH;
- version.data= &version_field;
-
- version_number_field.str= (char *) "version_number";
- version_number_field.length= MAX_VERSION_LENGTH;
- version_number.data= &version_number_field;
-
- mysqld_compatible_field.str= (char *) "mysqld_compatible";
- mysqld_compatible_field.length= DEFAULT_FIELD_LENGTH;
- mysqld_compatible.data= &mysqld_compatible_field;
-
- field_list= list_add(NULL, &mysqld_compatible);
- field_list= list_add(field_list, &version);
- field_list= list_add(field_list, &version_number);
- field_list= list_add(field_list, &state);
- field_list= list_add(field_list, &name);
-
- return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
-}
-
-
-int Show_instance_status::write_data(st_net *net, Instance *instance)
-{
- Buffer send_buf; /* buffer for packets */
- char version_num_buf[MAX_VERSION_LENGTH];
- size_t pos= 0;
-
- const char *state_name= instance->get_state_name();
- const char *version_tag= "unknown";
- const char *version_num= "unknown";
- const char *mysqld_compatible_status=
- instance->is_mysqld_compatible() ? "yes" : "no";
-
- if (instance->options.mysqld_version)
- {
- if (parse_version_number(instance->options.mysqld_version, version_num_buf,
- sizeof(version_num_buf)))
- return ER_OUT_OF_RESOURCES;
-
- version_num= version_num_buf;
- version_tag= instance->options.mysqld_version;
- }
-
- if (store_to_protocol_packet(&send_buf, get_instance_name()->str, &pos) ||
- store_to_protocol_packet(&send_buf, state_name, &pos) ||
- store_to_protocol_packet(&send_buf, version_num, &pos) ||
- store_to_protocol_packet(&send_buf, version_tag, &pos) ||
- store_to_protocol_packet(&send_buf, mysqld_compatible_status, &pos) ||
- my_net_write(net, send_buf.buffer, pos))
- {
- return ER_OUT_OF_RESOURCES;
- }
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation of Show_instance_options.
-**************************************************************************/
-
-Show_instance_options::Show_instance_options(
- const LEX_STRING *instance_name_arg)
- :Abstract_instance_cmd(instance_name_arg)
-{
-}
-
-
-/**
- Implementation of SHOW INSTANCE OPTIONS statement.
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance with the given name does not exist
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Show_instance_options::execute_impl(st_net *net, Instance *instance)
-{
- int err_code;
-
- if ((err_code= write_header(net)) ||
- (err_code= write_data(net, instance)))
- return err_code;
-
- return 0;
-}
-
-
-int Show_instance_options::send_ok_response(st_net *net,
- ulong /* connection_id */)
-{
- if (send_eof(net) || net_flush(net))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-int Show_instance_options::write_header(st_net *net)
-{
- LIST name, option;
- LIST *field_list;
- LEX_STRING name_field, option_field;
-
- /* Create list of the fileds to be passed to send_fields(). */
-
- name_field.str= (char *) "option_name";
- name_field.length= DEFAULT_FIELD_LENGTH;
- name.data= &name_field;
-
- option_field.str= (char *) "value";
- option_field.length= DEFAULT_FIELD_LENGTH;
- option.data= &option_field;
-
- field_list= list_add(NULL, &option);
- field_list= list_add(field_list, &name);
-
- return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
-}
-
-
-int Show_instance_options::write_data(st_net *net, Instance *instance)
-{
- Buffer send_buff; /* buffer for packets */
- size_t pos= 0;
-
- if (store_to_protocol_packet(&send_buff, "instance_name", &pos) ||
- store_to_protocol_packet(&send_buff, get_instance_name()->str, &pos) ||
- my_net_write(net, send_buff.buffer, pos))
- {
- return ER_OUT_OF_RESOURCES;
- }
-
- /* Loop through the options. */
-
- for (int i= 0; i < instance->options.get_num_options(); i++)
- {
- Named_value option= instance->options.get_option(i);
- const char *option_value= option.get_value()[0] ? option.get_value() : "";
-
- pos= 0;
-
- if (store_to_protocol_packet(&send_buff, option.get_name(), &pos) ||
- store_to_protocol_packet(&send_buff, option_value, &pos) ||
- my_net_write(net, send_buff.buffer, pos))
- {
- return ER_OUT_OF_RESOURCES;
- }
- }
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation of Start_instance.
-**************************************************************************/
-
-Start_instance::Start_instance(const LEX_STRING *instance_name_arg)
- :Abstract_instance_cmd(instance_name_arg)
-{
-}
-
-
-/**
- Implementation of START INSTANCE statement.
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance with the given name does not exist
- ER_INSTANCE_MISCONFIGURED The instance configuration is invalid
- ER_INSTANCE_ALREADY_STARTED The instance is already started
- ER_CANNOT_START_INSTANCE The instance could not have been started
-
- TODO: as soon as this method operates only with Instance, we probably
- should introduce a new method (execute_stop_instance()) in Instance and
- just call it from here.
-*/
-
-int Start_instance::execute_impl(st_net * /* net */, Instance *instance)
-{
- if (!instance->is_configured())
- return ER_INSTANCE_MISCONFIGURED;
-
- if (instance->is_active())
- return ER_INSTANCE_ALREADY_STARTED;
-
- if (instance->start_mysqld())
- return ER_CANNOT_START_INSTANCE;
-
- instance->reset_stat();
- instance->set_state(Instance::NOT_STARTED);
-
- return 0;
-}
-
-
-int Start_instance::send_ok_response(st_net *net, ulong connection_id)
-{
- if (net_send_ok(net, connection_id, "Instance started"))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation of Stop_instance.
-**************************************************************************/
-
-Stop_instance::Stop_instance(const LEX_STRING *instance_name_arg)
- :Abstract_instance_cmd(instance_name_arg)
-{
-}
-
-
-/**
- Implementation of STOP INSTANCE statement.
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance with the given name does not exist
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-
- TODO: as soon as this method operates only with Instance, we probably
- should introduce a new method (execute_stop_instance()) in Instance and
- just call it from here.
-*/
-
-int Stop_instance::execute_impl(st_net * /* net */, Instance *instance)
-{
- if (!instance->is_active())
- return ER_INSTANCE_IS_NOT_STARTED;
-
- instance->set_state(Instance::STOPPED);
-
- return instance->stop_mysqld() ? ER_STOP_INSTANCE : 0;
-}
-
-
-int Stop_instance::send_ok_response(st_net *net, ulong connection_id)
-{
- if (net_send_ok(net, connection_id, NULL))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation for Create_instance.
-**************************************************************************/
-
-Create_instance::Create_instance(const LEX_STRING *instance_name_arg)
- :Instance_cmd(instance_name_arg)
-{
-}
-
-
-/**
- This operation initializes Create_instance object.
-
- SYNOPSIS
- text [IN/OUT] a pointer to the text containing instance options.
-
- RETURN
- FALSE On success.
- TRUE On error.
-*/
-
-bool Create_instance::init(const char **text)
-{
- return options.init() || parse_args(text);
-}
-
-
-/**
- This operation parses CREATE INSTANCE options.
-
- SYNOPSIS
- text [IN/OUT] a pointer to the text containing instance options.
-
- RETURN
- FALSE On success.
- TRUE On syntax error.
-*/
-
-bool Create_instance::parse_args(const char **text)
-{
- size_t len;
-
- /* Check if we have something (and trim leading spaces). */
-
- get_word(text, &len, NONSPACE);
-
- if (len == 0)
- return FALSE; /* OK: no option. */
-
- /* Main parsing loop. */
-
- while (TRUE)
- {
- LEX_STRING option_name;
- char *option_name_str;
- char *option_value_str= NULL;
-
- /* Looking for option name. */
-
- get_word(text, &option_name.length, OPTION_NAME);
-
- if (option_name.length == 0)
- return TRUE; /* Syntax error: option name expected. */
-
- option_name.str= (char *) *text;
- *text+= option_name.length;
-
- /* Looking for equal sign. */
-
- skip_spaces(text);
-
- if (**text == '=')
- {
- ++(*text); /* Skip an equal sign. */
-
- /* Looking for option value. */
-
- skip_spaces(text);
-
- if (!**text)
- return TRUE; /* Syntax error: EOS when option value expected. */
-
- if (**text != '\'' && **text != '"')
- {
- /* Option value is a simple token. */
-
- LEX_STRING option_value;
-
- get_word(text, &option_value.length, ALPHANUM);
-
- if (option_value.length == 0)
- return TRUE; /* internal parser error. */
-
- option_value.str= (char *) *text;
- *text+= option_value.length;
-
- if (!(option_value_str= Named_value::alloc_str(&option_value)))
- return TRUE; /* out of memory during parsing. */
- }
- else
- {
- /* Option value is a string. */
-
- if (parse_option_value(*text, &len, &option_value_str))
- return TRUE; /* Syntax error: invalid string specification. */
-
- *text+= len;
- }
- }
-
- if (!option_value_str)
- {
- LEX_STRING empty_str= { C_STRING_WITH_LEN("") };
-
- if (!(option_value_str= Named_value::alloc_str(&empty_str)))
- return TRUE; /* out of memory during parsing. */
- }
-
- if (!(option_name_str= Named_value::alloc_str(&option_name)))
- {
- Named_value::free_str(&option_value_str);
- return TRUE; /* out of memory during parsing. */
- }
-
- {
- Named_value option(option_name_str, option_value_str);
-
- if (options.add_element(&option))
- {
- option.free();
- return TRUE; /* out of memory during parsing. */
- }
- }
-
- skip_spaces(text);
-
- if (!**text)
- return FALSE; /* OK: end of options. */
-
- if (**text != ',')
- return TRUE; /* Syntax error: comma expected. */
-
- ++(*text);
- }
-}
-
-
-/**
- Implementation of CREATE INSTANCE statement.
-
- Possible error codes:
- ER_MALFORMED_INSTANCE_NAME Instance name is malformed
- ER_CREATE_EXISTING_INSTANCE There is an instance with the given name
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Create_instance::execute(st_net *net, ulong connection_id)
-{
- int err_code;
- Instance *instance;
-
- /* Check that the name is valid and there is no instance with such name. */
-
- if (!Instance::is_name_valid(get_instance_name()))
- return ER_MALFORMED_INSTANCE_NAME;
-
- /*
- NOTE: In order to prevent race condition, we should perform all operations
- on under acquired lock.
- */
-
- instance_map->lock();
-
- if (instance_map->find(get_instance_name()))
- {
- instance_map->unlock();
- return ER_CREATE_EXISTING_INSTANCE;
- }
-
- if ((err_code= instance_map->create_instance(get_instance_name(), &options)))
- {
- instance_map->unlock();
- return err_code;
- }
-
- instance= instance_map->find(get_instance_name());
- DBUG_ASSERT(instance);
-
- if ((err_code= create_instance_in_file(get_instance_name(), &options)))
- {
- instance_map->remove_instance(instance); /* instance is deleted here. */
-
- instance_map->unlock();
- return err_code;
- }
-
- /*
- CREATE INSTANCE must not lead to start instance, even if it guarded.
-
- TODO: The problem however is that if Instance Manager restarts after
- creating instance, the instance will be restarted (see also BUG#19718).
- */
-
- instance->set_state(Instance::STOPPED);
-
- /* That's all. */
-
- instance_map->unlock();
-
- /* Send the result. */
-
- if (net_send_ok(net, connection_id, NULL))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation for Drop_instance.
-**************************************************************************/
-
-Drop_instance::Drop_instance(const LEX_STRING *instance_name_arg)
- :Instance_cmd(instance_name_arg)
-{
-}
-
-
-/**
- Implementation of DROP INSTANCE statement.
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance with the given name does not exist
- ER_DROP_ACTIVE_INSTANCE The specified instance is active
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Drop_instance::execute(st_net *net, ulong connection_id)
-{
- int err_code;
- Instance *instance;
-
- /* Lock Guardian, then Instance_map. */
-
- instance_map->lock();
-
- /* Find an instance. */
-
- instance= instance_map->find(get_instance_name());
-
- if (!instance)
- {
- instance_map->unlock();
- return ER_BAD_INSTANCE_NAME;
- }
-
- instance->lock();
-
- /* Check that the instance is offline. */
-
- if (instance->is_active())
- {
- instance->unlock();
- instance_map->unlock();
-
- return ER_DROP_ACTIVE_INSTANCE;
- }
-
- /* Try to remove instance from the file. */
-
- err_code= modify_defaults_file(Options::Main::config_file, NULL, NULL,
- get_instance_name()->str, MY_REMOVE_SECTION);
- DBUG_ASSERT(err_code >= 0 && err_code <= 2);
-
- if (err_code)
- {
- log_error("Can not remove instance '%s' from defaults file (%s). "
- "Original error code: %d.",
- (const char *) get_instance_name()->str,
- (const char *) Options::Main::config_file,
- (int) err_code);
-
- instance->unlock();
- instance_map->unlock();
-
- return modify_defaults_to_im_error[err_code];
- }
-
- /* Unlock the instance before destroy. */
-
- instance->unlock();
-
- /*
- Remove instance from the instance map
- (the instance will be also destroyed here).
- */
-
- instance_map->remove_instance(instance);
-
- /* Unlock the instance map. */
-
- instance_map->unlock();
-
- /* That's all: send ok. */
-
- if (net_send_ok(net, connection_id, "Instance dropped"))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation for Show_instance_log.
-**************************************************************************/
-
-Show_instance_log::Show_instance_log(const LEX_STRING *instance_name_arg,
- Log_type log_type_arg,
- uint size_arg, uint offset_arg)
- :Abstract_instance_cmd(instance_name_arg),
- log_type(log_type_arg),
- size(size_arg),
- offset(offset_arg)
-{
-}
-
-
-/**
- Implementation of SHOW INSTANCE LOG statement.
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance with the given name does not exist
- ER_OFFSET_ERROR We were requested to read negative number of
- bytes from the log
- ER_NO_SUCH_LOG The specified type of log is not available for
- the given instance
- ER_GUESS_LOGFILE IM wasn't able to figure out the log
- placement, while it is enabled. Probably user
- should specify the path to the logfile
- explicitly.
- ER_OPEN_LOGFILE Cannot open the logfile
- ER_READ_FILE Cannot read the logfile
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Show_instance_log::execute_impl(st_net *net, Instance *instance)
-{
- int err_code;
-
- if ((err_code= check_params(instance)))
- return err_code;
-
- if ((err_code= write_header(net)) ||
- (err_code= write_data(net, instance)))
- return err_code;
-
- return 0;
-}
-
-
-int Show_instance_log::send_ok_response(st_net *net,
- ulong /* connection_id */)
-{
- if (send_eof(net) || net_flush(net))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-int Show_instance_log::check_params(Instance *instance)
-{
- const char *logpath= instance->options.logs[log_type];
-
- /* Cannot read negative number of bytes. */
-
- if (offset > size)
- return ER_OFFSET_ERROR;
-
- /* Instance has no such log. */
-
- if (logpath == NULL)
- return ER_NO_SUCH_LOG;
-
- if (*logpath == '\0')
- return ER_GUESS_LOGFILE;
-
- return 0;
-}
-
-
-int Show_instance_log::write_header(st_net *net)
-{
- LIST name;
- LIST *field_list;
- LEX_STRING name_field;
-
- /* Create list of the fields to be passed to send_fields(). */
-
- name_field.str= (char *) "Log";
- name_field.length= DEFAULT_FIELD_LENGTH;
-
- name.data= &name_field;
-
- field_list= list_add(NULL, &name);
-
- return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
-}
-
-
-int Show_instance_log::write_data(st_net *net, Instance *instance)
-{
- Buffer send_buff; /* buffer for packets */
- size_t pos= 0;
-
- const char *logpath= instance->options.logs[log_type];
- File fd;
-
- size_t buff_size;
- size_t read_len;
-
- MY_STAT file_stat;
- Buffer read_buff;
-
- if ((fd= my_open(logpath, O_RDONLY | O_BINARY, MYF(MY_WME))) <= 0)
- return ER_OPEN_LOGFILE;
-
- /* my_fstat doesn't use the flag parameter */
- if (my_fstat(fd, &file_stat, MYF(0)))
- {
- close(fd);
- return ER_OUT_OF_RESOURCES;
- }
-
- /* calculate buffer size */
- buff_size= (size - offset);
-
- read_buff.reserve(0, buff_size);
-
- /* read in one chunk */
- read_len= (int)my_seek(fd, file_stat.st_size - size, MY_SEEK_SET, MYF(0));
-
- if ((read_len= my_read(fd, read_buff.buffer, buff_size, MYF(0))) ==
- MY_FILE_ERROR)
- {
- close(fd);
- return ER_READ_FILE;
- }
-
- close(fd);
-
- if (store_to_protocol_packet(&send_buff, (char*) read_buff.buffer, &pos,
- read_len) ||
- my_net_write(net, send_buff.buffer, pos))
- {
- return ER_OUT_OF_RESOURCES;
- }
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation of Show_instance_log_files.
-**************************************************************************/
-
-Show_instance_log_files::Show_instance_log_files
- (const LEX_STRING *instance_name_arg)
- :Abstract_instance_cmd(instance_name_arg)
-{
-}
-
-
-/**
- Implementation of SHOW INSTANCE LOG FILES statement.
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance with the given name does not exist
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Show_instance_log_files::execute_impl(st_net *net, Instance *instance)
-{
- int err_code;
-
- if ((err_code= write_header(net)) ||
- (err_code= write_data(net, instance)))
- return err_code;
-
- return 0;
-}
-
-
-int Show_instance_log_files::send_ok_response(st_net *net,
- ulong /* connection_id */)
-{
- if (send_eof(net) || net_flush(net))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-int Show_instance_log_files::write_header(st_net *net)
-{
- LIST name, path, size;
- LIST *field_list;
- LEX_STRING name_field, path_field, size_field;
-
- /* Create list of the fileds to be passed to send_fields(). */
-
- name_field.str= (char *) "Logfile";
- name_field.length= DEFAULT_FIELD_LENGTH;
- name.data= &name_field;
-
- path_field.str= (char *) "Path";
- path_field.length= DEFAULT_FIELD_LENGTH;
- path.data= &path_field;
-
- size_field.str= (char *) "File size";
- size_field.length= DEFAULT_FIELD_LENGTH;
- size.data= &size_field;
-
- field_list= list_add(NULL, &size);
- field_list= list_add(field_list, &path);
- field_list= list_add(field_list, &name);
-
- return send_fields(net, field_list) ? ER_OUT_OF_RESOURCES : 0;
-}
-
-
-int Show_instance_log_files::write_data(st_net *net, Instance *instance)
-{
- Buffer send_buff; /* buffer for packets */
-
- /*
- We have alike structure in instance_options.cc. We use such to be able
- to loop through the options, which we need to handle in some common way.
- */
- struct log_files_st
- {
- const char *name;
- const char *value;
- } logs[]=
- {
- {"ERROR LOG", instance->options.logs[IM_LOG_ERROR]},
- {"GENERAL LOG", instance->options.logs[IM_LOG_GENERAL]},
- {"SLOW LOG", instance->options.logs[IM_LOG_SLOW]},
- {NULL, NULL}
- };
- struct log_files_st *log_files;
-
- for (log_files= logs; log_files->name; log_files++)
- {
- if (!log_files->value)
- continue;
-
- struct stat file_stat;
- /*
- Save some more space for the log file names. In fact all
- we need is strlen("GENERAL_LOG") + 1
- */
- enum { LOG_NAME_BUFFER_SIZE= 20 };
- char buff[LOG_NAME_BUFFER_SIZE];
-
- size_t pos= 0;
-
- const char *log_path= "";
- const char *log_size= "0";
-
- if (!stat(log_files->value, &file_stat) &&
- MY_S_ISREG(file_stat.st_mode))
- {
- int10_to_str(file_stat.st_size, buff, 10);
-
- log_path= log_files->value;
- log_size= buff;
- }
-
- if (store_to_protocol_packet(&send_buff, log_files->name, &pos) ||
- store_to_protocol_packet(&send_buff, log_path, &pos) ||
- store_to_protocol_packet(&send_buff, log_size, &pos) ||
- my_net_write(net, send_buff.buffer, pos))
- return ER_OUT_OF_RESOURCES;
- }
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation of Abstract_option_cmd.
-**************************************************************************/
-
-/**
- Instance_options_list -- a data class representing a list of options for
- some instance.
-*/
-
-class Instance_options_list
-{
-public:
- Instance_options_list(const LEX_STRING *instance_name_arg);
-
-public:
- bool init();
-
- const LEX_STRING *get_instance_name() const
- {
- return instance_name.get_str();
- }
-
-public:
- /*
- This member is set and used only in Abstract_option_cmd::execute_impl().
- Normally it is not used (and should not).
-
- The problem is that construction and execution of commands are made not
- in one transaction (not under one lock session). So, we can not initialize
- instance in constructor and use it in execution.
- */
- Instance *instance;
-
- Named_value_arr options;
-
-private:
- Instance_name instance_name;
-};
-
-
-/**************************************************************************/
-
-Instance_options_list::Instance_options_list(
- const LEX_STRING *instance_name_arg)
- :instance(NULL),
- instance_name(instance_name_arg)
-{
-}
-
-
-bool Instance_options_list::init()
-{
- return options.init();
-}
-
-
-/**************************************************************************/
-
-C_MODE_START
-
-static uchar* get_item_key(const uchar* item, size_t* len,
- my_bool __attribute__((unused)) t)
-{
- const Instance_options_list *lst= (const Instance_options_list *) item;
- *len= lst->get_instance_name()->length;
- return (uchar *) lst->get_instance_name()->str;
-}
-
-static void delete_item(void *item)
-{
- delete (Instance_options_list *) item;
-}
-
-C_MODE_END
-
-
-/**************************************************************************/
-
-Abstract_option_cmd::Abstract_option_cmd()
- :initialized(FALSE)
-{
-}
-
-
-Abstract_option_cmd::~Abstract_option_cmd()
-{
- if (initialized)
- hash_free(&instance_options_map);
-}
-
-
-bool Abstract_option_cmd::add_option(const LEX_STRING *instance_name,
- Named_value *option)
-{
- Instance_options_list *lst= get_instance_options_list(instance_name);
-
- if (!lst)
- return TRUE;
-
- lst->options.add_element(option);
-
- return FALSE;
-}
-
-
-bool Abstract_option_cmd::init(const char **text)
-{
- static const int INITIAL_HASH_SIZE= 16;
-
- if (hash_init(&instance_options_map, default_charset_info,
- INITIAL_HASH_SIZE, 0, 0, get_item_key, delete_item, 0))
- return TRUE;
-
- if (parse_args(text))
- return TRUE;
-
- initialized= TRUE;
-
- return FALSE;
-}
-
-
-/**
- Correct the option file. The "skip" option is used to remove the found
- option.
-
- SYNOPSIS
- Abstract_option_cmd::correct_file()
- skip Skip the option, being searched while writing the result file.
- That is, to delete it.
-
- RETURN
- 0 Success
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
- ER_ACCESS_OPTION_FILE Cannot access the option file
-*/
-
-int Abstract_option_cmd::correct_file(Instance *instance, Named_value *option,
- bool skip)
-{
- int err_code= modify_defaults_file(Options::Main::config_file,
- option->get_name(),
- option->get_value(),
- instance->get_name()->str,
- skip);
-
- DBUG_ASSERT(err_code >= 0 && err_code <= 2);
-
- if (err_code)
- {
- log_error("Can not modify option (%s) in defaults file (%s). "
- "Original error code: %d.",
- (const char *) option->get_name(),
- (const char *) Options::Main::config_file,
- (int) err_code);
- }
-
- return modify_defaults_to_im_error[err_code];
-}
-
-
-/**
- Lock Instance Map and call execute_impl().
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance with the given name does not exist
- ER_INCOMPATIBLE_OPTION The specified option can not be set for
- mysqld-compatible instance
- ER_INSTANCE_IS_ACTIVE The specified instance is active
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Abstract_option_cmd::execute(st_net *net, ulong connection_id)
-{
- int err_code;
-
- instance_map->lock();
-
- err_code= execute_impl(net, connection_id);
-
- instance_map->unlock();
-
- return err_code;
-}
-
-
-Instance_options_list *
-Abstract_option_cmd::get_instance_options_list(const LEX_STRING *instance_name)
-{
- Instance_options_list *lst=
- (Instance_options_list *) hash_search(&instance_options_map,
- (uchar *) instance_name->str,
- instance_name->length);
-
- if (!lst)
- {
- lst= new Instance_options_list(instance_name);
-
- if (!lst)
- return NULL;
-
- if (lst->init() || my_hash_insert(&instance_options_map, (uchar *) lst))
- {
- delete lst;
- return NULL;
- }
- }
-
- return lst;
-}
-
-
-/**
- Skeleton implementation of option-management command.
-
- MT-NOTE: Instance Map is locked before calling this operation.
-*/
-int Abstract_option_cmd::execute_impl(st_net *net, ulong connection_id)
-{
- int err_code= 0;
-
- /* Check that all the specified instances exist and are offline. */
-
- for (uint i= 0; i < instance_options_map.records; ++i)
- {
- Instance_options_list *lst=
- (Instance_options_list *) hash_element(&instance_options_map, i);
-
- bool instance_is_active;
-
- lst->instance= instance_map->find(lst->get_instance_name());
-
- if (!lst->instance)
- return ER_BAD_INSTANCE_NAME;
-
- lst->instance->lock();
- instance_is_active= lst->instance->is_active();
- lst->instance->unlock();
-
- if (instance_is_active)
- return ER_INSTANCE_IS_ACTIVE;
- }
-
- /* Perform command-specific (SET/UNSET) actions. */
-
- for (uint i= 0; i < instance_options_map.records; ++i)
- {
- Instance_options_list *lst=
- (Instance_options_list *) hash_element(&instance_options_map, i);
-
- lst->instance->lock();
-
- for (int j= 0; j < lst->options.get_size(); ++j)
- {
- Named_value option= lst->options.get_element(j);
- err_code= process_option(lst->instance, &option);
-
- if (err_code)
- break;
- }
-
- lst->instance->unlock();
-
- if (err_code)
- break;
- }
-
- if (err_code == 0)
- net_send_ok(net, connection_id, NULL);
-
- return err_code;
-}
-
-
-/**************************************************************************
- Implementation of Set_option.
-**************************************************************************/
-
-/**
- This operation parses SET options.
-
- SYNOPSIS
- text [IN/OUT] a pointer to the text containing options.
-
- RETURN
- FALSE On success.
- TRUE On syntax error.
-*/
-
-bool Set_option::parse_args(const char **text)
-{
- size_t len;
-
- /* Check if we have something (and trim leading spaces). */
-
- get_word(text, &len, NONSPACE);
-
- if (len == 0)
- return TRUE; /* Syntax error: no option. */
-
- /* Main parsing loop. */
-
- while (TRUE)
- {
- LEX_STRING instance_name;
- LEX_STRING option_name;
- char *option_name_str;
- char *option_value_str= NULL;
-
- /* Looking for instance name. */
-
- get_word(text, &instance_name.length, ALPHANUM);
-
- if (instance_name.length == 0)
- return TRUE; /* Syntax error: instance name expected. */
-
- instance_name.str= (char *) *text;
- *text+= instance_name.length;
-
- skip_spaces(text);
-
- /* Check the the delimiter is a dot. */
-
- if (**text != '.')
- return TRUE; /* Syntax error: dot expected. */
-
- ++(*text);
-
- /* Looking for option name. */
-
- get_word(text, &option_name.length, OPTION_NAME);
-
- if (option_name.length == 0)
- return TRUE; /* Syntax error: option name expected. */
-
- option_name.str= (char *) *text;
- *text+= option_name.length;
-
- /* Looking for equal sign. */
-
- skip_spaces(text);
-
- if (**text == '=')
- {
- ++(*text); /* Skip an equal sign. */
-
- /* Looking for option value. */
-
- skip_spaces(text);
-
- if (!**text)
- return TRUE; /* Syntax error: EOS when option value expected. */
-
- if (**text != '\'' && **text != '"')
- {
- /* Option value is a simple token. */
-
- LEX_STRING option_value;
-
- get_word(text, &option_value.length, ALPHANUM);
-
- if (option_value.length == 0)
- return TRUE; /* internal parser error. */
-
- option_value.str= (char *) *text;
- *text+= option_value.length;
-
- if (!(option_value_str= Named_value::alloc_str(&option_value)))
- return TRUE; /* out of memory during parsing. */
- }
- else
- {
- /* Option value is a string. */
-
- if (parse_option_value(*text, &len, &option_value_str))
- return TRUE; /* Syntax error: invalid string specification. */
-
- *text+= len;
- }
- }
-
- if (!option_value_str)
- {
- LEX_STRING empty_str= { C_STRING_WITH_LEN("") };
-
- if (!(option_value_str= Named_value::alloc_str(&empty_str)))
- return TRUE; /* out of memory during parsing. */
- }
-
- if (!(option_name_str= Named_value::alloc_str(&option_name)))
- {
- Named_value::free_str(&option_name_str);
- return TRUE; /* out of memory during parsing. */
- }
-
- {
- Named_value option(option_name_str, option_value_str);
-
- if (add_option(&instance_name, &option))
- {
- option.free();
- return TRUE; /* out of memory during parsing. */
- }
- }
-
- skip_spaces(text);
-
- if (!**text)
- return FALSE; /* OK: end of options. */
-
- if (**text != ',')
- return TRUE; /* Syntax error: comma expected. */
-
- ++(*text); /* Skip a comma. */
- }
-}
-
-
-int Set_option::process_option(Instance *instance, Named_value *option)
-{
- /* Check that the option is valid. */
-
- if (instance->is_mysqld_compatible() &&
- Instance_options::is_option_im_specific(option->get_name()))
- {
- log_error("IM-option (%s) can not be used "
- "in the configuration of mysqld-compatible instance (%s).",
- (const char *) option->get_name(),
- (const char *) instance->get_name()->str);
- return ER_INCOMPATIBLE_OPTION;
- }
-
- /* Update the configuration file. */
-
- int err_code= correct_file(instance, option, FALSE);
-
- if (err_code)
- return err_code;
-
- /* Update the internal cache. */
-
- if (instance->options.set_option(option))
- return ER_OUT_OF_RESOURCES;
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation of Unset_option.
-**************************************************************************/
-
-/**
- This operation parses UNSET options.
-
- SYNOPSIS
- text [IN/OUT] a pointer to the text containing options.
-
- RETURN
- FALSE On success.
- TRUE On syntax error.
-*/
-
-bool Unset_option::parse_args(const char **text)
-{
- size_t len;
-
- /* Check if we have something (and trim leading spaces). */
-
- get_word(text, &len, NONSPACE);
-
- if (len == 0)
- return TRUE; /* Syntax error: no option. */
-
- /* Main parsing loop. */
-
- while (TRUE)
- {
- LEX_STRING instance_name;
- LEX_STRING option_name;
- char *option_name_str;
- char *option_value_str;
-
- /* Looking for instance name. */
-
- get_word(text, &instance_name.length, ALPHANUM);
-
- if (instance_name.length == 0)
- return TRUE; /* Syntax error: instance name expected. */
-
- instance_name.str= (char *) *text;
- *text+= instance_name.length;
-
- skip_spaces(text);
-
- /* Check the the delimiter is a dot. */
-
- if (**text != '.')
- return TRUE; /* Syntax error: dot expected. */
-
- ++(*text); /* Skip a dot. */
-
- /* Looking for option name. */
-
- get_word(text, &option_name.length, OPTION_NAME);
-
- if (option_name.length == 0)
- return TRUE; /* Syntax error: option name expected. */
-
- option_name.str= (char *) *text;
- *text+= option_name.length;
-
- if (!(option_name_str= Named_value::alloc_str(&option_name)))
- return TRUE; /* out of memory during parsing. */
-
- {
- LEX_STRING empty_str= { C_STRING_WITH_LEN("") };
-
- if (!(option_value_str= Named_value::alloc_str(&empty_str)))
- {
- Named_value::free_str(&option_name_str);
- return TRUE;
- }
- }
-
- {
- Named_value option(option_name_str, option_value_str);
-
- if (add_option(&instance_name, &option))
- {
- option.free();
- return TRUE; /* out of memory during parsing. */
- }
- }
-
- skip_spaces(text);
-
- if (!**text)
- return FALSE; /* OK: end of options. */
-
- if (**text != ',')
- return TRUE; /* Syntax error: comma expected. */
-
- ++(*text); /* Skip a comma. */
- }
-}
-
-
-/**
- Implementation of UNSET statement.
-
- Possible error codes:
- ER_BAD_INSTANCE_NAME The instance name specified is not valid
- ER_INSTANCE_IS_ACTIVE The specified instance is active
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
-*/
-
-int Unset_option::process_option(Instance *instance, Named_value *option)
-{
- /* Update the configuration file. */
-
- int err_code= correct_file(instance, option, TRUE);
-
- if (err_code)
- return err_code;
-
- /* Update the internal cache. */
-
- instance->options.unset_option(option->get_name());
-
- return 0;
-}
-
-
-/**************************************************************************
- Implementation of Syntax_error.
-**************************************************************************/
-
-int Syntax_error::execute(st_net * /* net */, ulong /* connection_id */)
-{
- return ER_SYNTAX_ERROR;
-}
diff --git a/server-tools/instance-manager/commands.h b/server-tools/instance-manager/commands.h
deleted file mode 100644
index 5c2b2f9bbb7..00000000000
--- a/server-tools/instance-manager/commands.h
+++ /dev/null
@@ -1,393 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 <my_sys.h>
-#include <m_string.h>
-#include <hash.h>
-
-#include "command.h"
-#include "instance.h"
-#include "parse.h"
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-
-/**
- Print all instances of this instance manager.
- Grammar: SHOW INSTANCES
-*/
-
-class Show_instances: public Command
-{
-public:
- Show_instances()
- { }
-
-public:
- int execute(st_net *net, ulong connection_id);
-
-private:
- int write_header(st_net *net);
- int write_data(st_net *net);
-};
-
-
-/**
- Reread configuration file and refresh internal cache.
- Grammar: FLUSH INSTANCES
-*/
-
-class Flush_instances: public Command
-{
-public:
- Flush_instances()
- { }
-
-public:
- int execute(st_net *net, ulong connection_id);
-};
-
-
-/**
- Base class for Instance-specific commands
- (commands that operate on one instance).
-
- Instance_cmd extends Command class by:
- - an attribute for storing instance name;
- - code to initialize instance name in constructor;
- - an accessor to get instance name.
-*/
-
-class Instance_cmd : public Command
-{
-public:
- Instance_cmd(const LEX_STRING *instance_name_arg);
-
-protected:
- inline const LEX_STRING *get_instance_name() const
- {
- return instance_name.get_str();
- }
-
-private:
- Instance_name instance_name;
-};
-
-
-/**
- Abstract class for Instance-specific commands.
-
- Abstract_instance_cmd extends Instance_cmd by providing a common
- framework for writing command-implementations. Basically, the class
- implements Command::execute() pure virtual function in the following
- way:
- - Lock Instance_map;
- - Get an instance by name. Return an error, if there is no such
- instance;
- - Lock the instance;
- - Unlock Instance_map;
- - Call execute_impl(), which should be implemented in derived class;
- - Unlock the instance;
- - Send response to the client and return error status.
-*/
-
-class Abstract_instance_cmd: public Instance_cmd
-{
-public:
- Abstract_instance_cmd(const LEX_STRING *instance_name_arg);
-
-public:
- virtual int execute(st_net *net, ulong connection_id);
-
-protected:
- /**
- This operation is intended to contain command-specific implementation.
-
- MT-NOTE: this operation is called under acquired Instance's lock.
- */
- virtual int execute_impl(st_net *net, Instance *instance) = 0;
-
- /**
- This operation is invoked on successful return of execute_impl() and is
- intended to send closing data.
-
- MT-NOTE: this operation is called under released Instance's lock.
- */
- virtual int send_ok_response(st_net *net, ulong connection_id) = 0;
-};
-
-
-/**
- Print status of an instance.
- Grammar: SHOW INSTANCE STATUS <instance_name>
-*/
-
-class Show_instance_status: public Abstract_instance_cmd
-{
-public:
- Show_instance_status(const LEX_STRING *instance_name_arg);
-
-protected:
- virtual int execute_impl(st_net *net, Instance *instance);
- virtual int send_ok_response(st_net *net, ulong connection_id);
-
-private:
- int write_header(st_net *net);
- int write_data(st_net *net, Instance *instance);
-};
-
-
-/**
- Print options of chosen instance.
- Grammar: SHOW INSTANCE OPTIONS <instance_name>
-*/
-
-class Show_instance_options: public Abstract_instance_cmd
-{
-public:
- Show_instance_options(const LEX_STRING *instance_name_arg);
-
-protected:
- virtual int execute_impl(st_net *net, Instance *instance);
- virtual int send_ok_response(st_net *net, ulong connection_id);
-
-private:
- int write_header(st_net *net);
- int write_data(st_net *net, Instance *instance);
-};
-
-
-/**
- Start an instance.
- Grammar: START INSTANCE <instance_name>
-*/
-
-class Start_instance: public Abstract_instance_cmd
-{
-public:
- Start_instance(const LEX_STRING *instance_name_arg);
-
-protected:
- virtual int execute_impl(st_net *net, Instance *instance);
- virtual int send_ok_response(st_net *net, ulong connection_id);
-};
-
-
-/**
- Stop an instance.
- Grammar: STOP INSTANCE <instance_name>
-*/
-
-class Stop_instance: public Abstract_instance_cmd
-{
-public:
- Stop_instance(const LEX_STRING *instance_name_arg);
-
-protected:
- virtual int execute_impl(st_net *net, Instance *instance);
- virtual int send_ok_response(st_net *net, ulong connection_id);
-};
-
-
-/**
- Create an instance.
- Grammar: CREATE INSTANCE <instance_name> [<options>]
-*/
-
-class Create_instance: public Instance_cmd
-{
-public:
- Create_instance(const LEX_STRING *instance_name_arg);
-
-public:
- bool init(const char **text);
-
-protected:
- virtual int execute(st_net *net, ulong connection_id);
-
-private:
- bool parse_args(const char **text);
-
-private:
- Named_value_arr options;
-};
-
-
-/**
- Drop an instance.
- Grammar: DROP INSTANCE <instance_name>
-
- Operation is permitted only if the instance is stopped. On successful
- completion the instance section is removed from config file and the instance
- is removed from the instance map.
-*/
-
-class Drop_instance: public Instance_cmd
-{
-public:
- Drop_instance(const LEX_STRING *instance_name_arg);
-
-protected:
- virtual int execute(st_net *net, ulong connection_id);
-};
-
-
-/**
- Print requested part of the log.
- Grammar:
- SHOW <instance_name> LOG {ERROR | SLOW | GENERAL} size[, offset_from_end]
-*/
-
-class Show_instance_log: public Abstract_instance_cmd
-{
-public:
- Show_instance_log(const LEX_STRING *instance_name_arg,
- Log_type log_type_arg, uint size_arg, uint offset_arg);
-
-protected:
- virtual int execute_impl(st_net *net, Instance *instance);
- virtual int send_ok_response(st_net *net, ulong connection_id);
-
-private:
- int check_params(Instance *instance);
- int write_header(st_net *net);
- int write_data(st_net *net, Instance *instance);
-
-private:
- Log_type log_type;
- uint size;
- uint offset;
-};
-
-
-/**
- Shows the list of the log files, used by an instance.
- Grammar: SHOW <instance_name> LOG FILES
-*/
-
-class Show_instance_log_files: public Abstract_instance_cmd
-{
-public:
- Show_instance_log_files(const LEX_STRING *instance_name_arg);
-
-protected:
- virtual int execute_impl(st_net *net, Instance *instance);
- virtual int send_ok_response(st_net *net, ulong connection_id);
-
-private:
- int write_header(st_net *net);
- int write_data(st_net *net, Instance *instance);
-};
-
-
-/**
- Abstract class for option-management commands.
-*/
-
-class Instance_options_list;
-
-class Abstract_option_cmd: public Command
-{
-public:
- ~Abstract_option_cmd();
-
-public:
- bool add_option(const LEX_STRING *instance_name, Named_value *option);
-
-public:
- bool init(const char **text);
-
- virtual int execute(st_net *net, ulong connection_id);
-
-protected:
- Abstract_option_cmd();
-
- int correct_file(Instance *instance, Named_value *option, bool skip);
-
-protected:
- virtual bool parse_args(const char **text) = 0;
- virtual int process_option(Instance *instance, Named_value *option) = 0;
-
-private:
- Instance_options_list *
- get_instance_options_list(const LEX_STRING *instance_name);
-
- int execute_impl(st_net *net, ulong connection_id);
-
-private:
- HASH instance_options_map;
- bool initialized;
-};
-
-
-/**
- Set an option for the instance.
- Grammar: SET instance_name.option[=option_value][, ...]
-*/
-
-class Set_option: public Abstract_option_cmd
-{
-public:
- Set_option()
- { }
-
-protected:
- virtual bool parse_args(const char **text);
- virtual int process_option(Instance *instance, Named_value *option);
-};
-
-
-/**
- Remove option of the instance.
- Grammar: UNSET instance_name.option[, ...]
-*/
-
-class Unset_option: public Abstract_option_cmd
-{
-public:
- Unset_option()
- { }
-
-protected:
- virtual bool parse_args(const char **text);
- virtual int process_option(Instance *instance, Named_value *option);
-};
-
-
-/**
- Syntax error command.
-
- This command is issued if parser reported a syntax error. We need it to
- distinguish between syntax error and internal parser error. E.g. parsing
- failed because we hadn't had enought memory. In the latter case the parser
- just returns NULL.
-*/
-
-class Syntax_error: public Command
-{
-public:
- Syntax_error()
- { }
-
-public:
- int execute(st_net *net, ulong connection_id);
-};
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_COMMANDS_H */
diff --git a/server-tools/instance-manager/exit_codes.h b/server-tools/instance-manager/exit_codes.h
deleted file mode 100644
index 1609debd8f9..00000000000
--- a/server-tools/instance-manager/exit_codes.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H
-
-/*
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-/*
- This file contains a list of exit codes, which are used when Instance
- Manager is working in user-management mode.
-*/
-
-const int ERR_OK = 0;
-
-const int ERR_OUT_OF_MEMORY = 1;
-const int ERR_INVALID_USAGE = 2;
-const int ERR_INTERNAL_ERROR = 3;
-const int ERR_IO_ERROR = 4;
-const int ERR_PASSWORD_FILE_CORRUPTED = 5;
-const int ERR_PASSWORD_FILE_DOES_NOT_EXIST = 6;
-
-const int ERR_CAN_NOT_READ_USER_NAME = 10;
-const int ERR_CAN_NOT_READ_PASSWORD = 11;
-const int ERR_USER_ALREADY_EXISTS = 12;
-const int ERR_USER_NOT_FOUND = 13;
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_EXIT_CODES_H
diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc
deleted file mode 100644
index b49b0ec0a00..00000000000
--- a/server-tools/instance-manager/guardian.cc
+++ /dev/null
@@ -1,496 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 */
-
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "guardian.h"
-#include <string.h>
-#include <sys/types.h>
-#include <signal.h>
-
-#include "instance.h"
-#include "instance_map.h"
-#include "log.h"
-#include "mysql_manager_error.h"
-#include "options.h"
-
-
-/*************************************************************************
- {{{ Constructor & destructor.
-*************************************************************************/
-
-/**
- Guardian constructor.
-
- SYNOPSIS
- Guardian()
- thread_registry_arg
- instance_map_arg
-
- DESCRIPTION
- Nominal contructor intended for assigning references and initialize
- trivial objects. Real initialization is made by init() method.
-*/
-
-Guardian::Guardian(Thread_registry *thread_registry_arg,
- Instance_map *instance_map_arg)
- :shutdown_requested(FALSE),
- stopped(FALSE),
- thread_registry(thread_registry_arg),
- instance_map(instance_map_arg)
-{
- pthread_mutex_init(&LOCK_guardian, 0);
- pthread_cond_init(&COND_guardian, 0);
-}
-
-
-Guardian::~Guardian()
-{
- /*
- NOTE: it's necessary to synchronize here, because Guiardian thread can be
- still alive an hold the mutex (because it is detached and we have no
- control over it).
- */
-
- lock();
- unlock();
-
- pthread_mutex_destroy(&LOCK_guardian);
- pthread_cond_destroy(&COND_guardian);
-}
-
-/*************************************************************************
- }}}
-*************************************************************************/
-
-
-/**
- Send request to stop Guardian.
-
- SYNOPSIS
- request_shutdown()
-*/
-
-void Guardian::request_shutdown()
-{
- stop_instances();
-
- lock();
- shutdown_requested= TRUE;
- unlock();
-
- ping();
-}
-
-
-/**
- Process an instance.
-
- SYNOPSIS
- process_instance()
- instance a pointer to the instance for processing
-
- MT-NOTE:
- - the given instance must be locked before calling this operation;
- - Guardian must be locked before calling this operation.
-*/
-
-void Guardian::process_instance(Instance *instance)
-{
- int restart_retry= 100;
- time_t current_time= time(NULL);
-
- if (instance->get_state() == Instance::STOPPING)
- {
- /* This brach is executed during shutdown. */
-
- /* This returns TRUE if and only if an instance was stopped for sure. */
- if (instance->is_crashed())
- {
- log_info("Guardian: '%s' stopped.",
- (const char *) instance->get_name()->str);
-
- instance->set_state(Instance::STOPPED);
- }
- else if ((uint) (current_time - instance->last_checked) >=
- instance->options.get_shutdown_delay())
- {
- log_info("Guardian: '%s' hasn't stopped within %d secs.",
- (const char *) instance->get_name()->str,
- (int) instance->options.get_shutdown_delay());
-
- instance->kill_mysqld(SIGKILL);
-
- log_info("Guardian: pretend that '%s' is killed.",
- (const char *) instance->get_name()->str);
-
- instance->set_state(Instance::STOPPED);
- }
- else
- {
- log_info("Guardian: waiting for '%s' to stop (%d secs left).",
- (const char *) instance->get_name()->str,
- (int) (instance->options.get_shutdown_delay() -
- current_time + instance->last_checked));
- }
-
- return;
- }
-
- if (instance->is_mysqld_running())
- {
- /* The instance can be contacted on it's port */
-
- /* If STARTING also check that pidfile has been created */
- if (instance->get_state() == Instance::STARTING &&
- instance->options.load_pid() == 0)
- {
- /* Pid file not created yet, don't go to STARTED state yet */
- }
- else if (instance->get_state() != Instance::STARTED)
- {
- /* clear status fields */
- log_info("Guardian: '%s' is running, set state to STARTED.",
- (const char *) instance->options.instance_name.str);
- instance->reset_stat();
- instance->set_state(Instance::STARTED);
- }
- }
- else
- {
- switch (instance->get_state()) {
- case Instance::NOT_STARTED:
- log_info("Guardian: starting '%s'...",
- (const char *) instance->options.instance_name.str);
-
- /* NOTE: set state to STARTING _before_ start() is called. */
- instance->set_state(Instance::STARTING);
- instance->last_checked= current_time;
-
- instance->start_mysqld();
-
- return;
-
- case Instance::STARTED: /* fallthrough */
- case Instance::STARTING: /* let the instance start or crash */
- if (!instance->is_crashed())
- return;
-
- instance->crash_moment= current_time;
- instance->last_checked= current_time;
- instance->set_state(Instance::JUST_CRASHED);
- /* fallthrough -- restart an instance immediately */
-
- case Instance::JUST_CRASHED:
- if (current_time - instance->crash_moment <= 2)
- {
- if (instance->is_crashed())
- {
- instance->start_mysqld();
- log_info("Guardian: starting '%s'...",
- (const char *) instance->options.instance_name.str);
- }
- }
- else
- instance->set_state(Instance::CRASHED);
-
- return;
-
- case Instance::CRASHED: /* just regular restarts */
- if ((ulong) (current_time - instance->last_checked) <=
- (ulong) Options::Main::monitoring_interval)
- return;
-
- if (instance->restart_counter < restart_retry)
- {
- if (instance->is_crashed())
- {
- instance->start_mysqld();
- instance->last_checked= current_time;
-
- log_info("Guardian: restarting '%s'...",
- (const char *) instance->options.instance_name.str);
- }
- }
- else
- {
- log_info("Guardian: can not start '%s'. "
- "Abandoning attempts to (re)start it",
- (const char *) instance->options.instance_name.str);
-
- instance->set_state(Instance::CRASHED_AND_ABANDONED);
- }
-
- return;
-
- case Instance::CRASHED_AND_ABANDONED:
- return; /* do nothing */
-
- default:
- DBUG_ASSERT(0);
- }
- }
-}
-
-
-/**
- Main function of Guardian thread.
-
- SYNOPSIS
- run()
-
- DESCRIPTION
- Check for all guarded instances and restart them if needed.
-*/
-
-void Guardian::run()
-{
- struct timespec timeout;
-
- log_info("Guardian: started.");
-
- thread_registry->register_thread(&thread_info);
-
- /* Loop, until all instances were shut down at the end. */
-
- while (true)
- {
- Instance_map::Iterator instances_it(instance_map);
- Instance *instance;
- bool all_instances_stopped= TRUE;
-
- instance_map->lock();
-
- while ((instance= instances_it.next()))
- {
- instance->lock();
-
- if (!instance->is_guarded() ||
- instance->get_state() == Instance::STOPPED)
- {
- instance->unlock();
- continue;
- }
-
- process_instance(instance);
-
- if (instance->get_state() != Instance::STOPPED)
- all_instances_stopped= FALSE;
-
- instance->unlock();
- }
-
- instance_map->unlock();
-
- lock();
-
- if (shutdown_requested && all_instances_stopped)
- {
- log_info("Guardian: all guarded mysqlds stopped.");
-
- stopped= TRUE;
- unlock();
- break;
- }
-
- set_timespec(timeout, Options::Main::monitoring_interval);
-
- thread_registry->cond_timedwait(&thread_info, &COND_guardian,
- &LOCK_guardian, &timeout);
- unlock();
- }
-
- log_info("Guardian: stopped.");
-
- /* Now, when the Guardian is stopped we can stop the IM. */
-
- thread_registry->unregister_thread(&thread_info);
- thread_registry->request_shutdown();
-
- log_info("Guardian: finished.");
-}
-
-
-/**
- Return the value of stopped flag.
-*/
-
-bool Guardian::is_stopped()
-{
- int var;
-
- lock();
- var= stopped;
- unlock();
-
- return var;
-}
-
-
-/**
- Wake up Guardian thread.
-
- MT-NOTE: though usually the mutex associated with condition variable should
- be acquired before signalling the variable, here this is not needed.
- Signalling under locked mutex is used to avoid lost signals. In the current
- logic however locking mutex does not guarantee that the signal will not be
- lost.
-*/
-
-void Guardian::ping()
-{
- pthread_cond_signal(&COND_guardian);
-}
-
-
-/**
- Prepare list of instances.
-
- SYNOPSIS
- init()
-
- MT-NOTE: Instance Map must be locked before calling the operation.
-*/
-
-void Guardian::init()
-{
- Instance *instance;
- Instance_map::Iterator iterator(instance_map);
-
- while ((instance= iterator.next()))
- {
- instance->lock();
-
- instance->reset_stat();
- instance->set_state(Instance::NOT_STARTED);
-
- instance->unlock();
- }
-}
-
-
-/**
- An internal method which is called at shutdown to unregister instances and
- attempt to stop them if requested.
-
- SYNOPSIS
- stop_instances()
-
- DESCRIPTION
- Loops through the guarded_instances list and prepares them for shutdown.
- For each instance we issue a stop command and change the state
- accordingly.
-
- NOTE
- Guardian object should be locked by the caller.
-
-*/
-
-void Guardian::stop_instances()
-{
- static const int NUM_STOP_ATTEMPTS = 100;
-
- Instance_map::Iterator instances_it(instance_map);
- Instance *instance;
-
- instance_map->lock();
-
- while ((instance= instances_it.next()))
- {
- instance->lock();
-
- if (!instance->is_guarded() ||
- instance->get_state() == Instance::STOPPED)
- {
- instance->unlock();
- continue;
- }
-
- /*
- If instance is running or was running (and now probably hanging),
- request stop.
- */
-
- if (instance->is_mysqld_running() ||
- instance->get_state() == Instance::STARTED)
- {
- instance->set_state(Instance::STOPPING);
- instance->last_checked= time(NULL);
- }
- else
- {
- /* Otherwise mark it as STOPPED. */
- instance->set_state(Instance::STOPPED);
- }
-
- /* Request mysqld to stop. */
-
- bool instance_stopped= FALSE;
-
- for (int cur_attempt= 0; cur_attempt < NUM_STOP_ATTEMPTS; ++cur_attempt)
- {
- if (!instance->kill_mysqld(SIGTERM))
- {
- instance_stopped= TRUE;
- break;
- }
-
- if (!instance->is_active())
- {
- instance_stopped= TRUE;
- break;
- }
-
- /* Sleep for 0.3 sec and check again. */
-
- my_sleep(300000);
- }
-
- /*
- Abort if we failed to stop mysqld instance. That should not happen,
- but if it happened, we don't know what to do and prefer to have clear
- failure with coredump.
- */
-
- DBUG_ASSERT(instance_stopped);
-
- instance->unlock();
- }
-
- instance_map->unlock();
-}
-
-
-/**
- Lock Guardian.
-*/
-
-void Guardian::lock()
-{
- pthread_mutex_lock(&LOCK_guardian);
-}
-
-
-/**
- Unlock Guardian.
-*/
-
-void Guardian::unlock()
-{
- pthread_mutex_unlock(&LOCK_guardian);
-}
diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h
deleted file mode 100644
index d78058a6fc5..00000000000
--- a/server-tools/instance-manager/guardian.h
+++ /dev/null
@@ -1,110 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 <my_sys.h>
-#include <my_list.h>
-
-#include "thread_registry.h"
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-class Instance;
-class Instance_map;
-class Thread_registry;
-
-/**
- The guardian thread is responsible for monitoring and restarting of guarded
- instances.
-*/
-
-class Guardian: public Thread
-{
-public:
- Guardian(Thread_registry *thread_registry_arg,
- Instance_map *instance_map_arg);
- ~Guardian();
-
- void init();
-
-public:
- void request_shutdown();
-
- bool is_stopped();
-
- void lock();
- void unlock();
-
- void ping();
-
-protected:
- virtual void run();
-
-private:
- void stop_instances();
-
- void process_instance(Instance *instance);
-
-private:
- /*
- LOCK_guardian protectes the members in this section:
- - shutdown_requested;
- - stopped;
-
- Also, it is used for COND_guardian.
- */
- pthread_mutex_t LOCK_guardian;
-
- /*
- Guardian's main loop waits on this condition. So, it should be signalled
- each time, when instance state has been changed and we want Guardian to
- wake up.
-
- TODO: Change this to having data-scoped conditions, i.e. conditions,
- which indicate that some data has been changed.
- */
- pthread_cond_t COND_guardian;
-
- /*
- This variable is set to TRUE, when Manager thread is shutting down.
- The flag is used by Guardian thread to understand that it's time to
- finish.
- */
- bool shutdown_requested;
-
- /*
- This flag is set to TRUE on shutdown by Guardian thread, when all guarded
- mysqlds are stopped.
-
- The flag is used in the Manager thread to wait for Guardian to stop all
- mysqlds.
- */
- bool stopped;
-
- Thread_info thread_info;
- Thread_registry *thread_registry;
- Instance_map *instance_map;
-
-private:
- Guardian(const Guardian &);
- Guardian&operator =(const Guardian &);
-};
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_GUARDIAN_H */
diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc
deleted file mode 100644
index 1ad728d40eb..00000000000
--- a/server-tools/instance-manager/instance.cc
+++ /dev/null
@@ -1,944 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include <my_global.h>
-#include <mysql.h>
-
-#include <signal.h>
-#ifndef __WIN__
-#include <sys/wait.h>
-#endif
-
-#include "manager.h"
-#include "guardian.h"
-#include "instance.h"
-#include "log.h"
-#include "mysql_manager_error.h"
-#include "portability.h"
-#include "priv.h"
-#include "thread_registry.h"
-#include "instance_map.h"
-
-
-/*************************************************************************
- {{{ Platform-specific functions.
-*************************************************************************/
-
-#ifndef __WIN__
-typedef pid_t My_process_info;
-#else
-typedef PROCESS_INFORMATION My_process_info;
-#endif
-
-/*
- Wait for an instance
-
- SYNOPSIS
- wait_process()
- pi Pointer to the process information structure
- (platform-dependent).
-
- RETURN
- 0 - Success
- 1 - Error
-*/
-
-#ifndef __WIN__
-static int wait_process(My_process_info *pi)
-{
- /*
- Here we wait for the child created. This process differs for systems
- running LinuxThreads and POSIX Threads compliant systems. This is because
- according to POSIX we could wait() for a child in any thread of the
- process. While LinuxThreads require that wait() is called by the thread,
- which created the child.
- On the other hand we could not expect mysqld to return the pid, we
- got in from fork(), to wait4() fucntion when running on LinuxThreads.
- This is because MySQL shutdown thread is not the one, which was created
- by our fork() call.
- So basically we have two options: whether the wait() call returns only in
- the creator thread, but we cannot use waitpid() since we have no idea
- which pid we should wait for (in fact it should be the pid of shutdown
- thread, but we don't know this one). Or we could use waitpid(), but
- couldn't use wait(), because it could return in any wait() in the program.
- */
-
- if (Manager::is_linux_threads())
- wait(NULL); /* LinuxThreads were detected */
- else
- waitpid(*pi, NULL, 0);
-
- return 0;
-}
-#else
-static int wait_process(My_process_info *pi)
-{
- /* Wait until child process exits. */
- WaitForSingleObject(pi->hProcess, INFINITE);
-
- DWORD exitcode;
- ::GetExitCodeProcess(pi->hProcess, &exitcode);
-
- /* Close process and thread handles. */
- CloseHandle(pi->hProcess);
- CloseHandle(pi->hThread);
-
- /*
- GetExitCodeProces returns zero on failure. We should revert this value
- to report an error.
- */
- return (!exitcode);
-}
-#endif
-
-/*
- Launch an instance
-
- SYNOPSIS
- start_process()
- instance_options Pointer to the options of the instance to be
- launched.
- pi Pointer to the process information structure
- (platform-dependent).
-
- RETURN
- FALSE - Success
- TRUE - Cannot create an instance
-*/
-
-#ifndef __WIN__
-static bool start_process(Instance_options *instance_options,
- My_process_info *pi)
-{
-#ifndef __QNX__
- *pi= fork();
-#else
- /*
- On QNX one cannot use fork() in multithreaded environment and we
- should use spawn() or one of it's siblings instead.
- Here we use spawnv(), which is a combination of fork() and execv()
- in one call. It returns the pid of newly created process (>0) or -1
- */
- *pi= spawnv(P_NOWAIT, instance_options->mysqld_path, instance_options->argv);
-#endif
-
- switch (*pi) {
- case 0: /* never happens on QNX */
- execv(instance_options->mysqld_path.str, instance_options->argv);
- /* exec never returns */
- exit(1);
- case -1:
- log_error("Instance '%s': can not start mysqld: fork() failed.",
- (const char *) instance_options->instance_name.str);
- return TRUE;
- }
-
- return FALSE;
-}
-#else
-static bool start_process(Instance_options *instance_options,
- My_process_info *pi)
-{
- STARTUPINFO si;
-
- ZeroMemory(&si, sizeof(STARTUPINFO));
- si.cb= sizeof(STARTUPINFO);
- ZeroMemory(pi, sizeof(PROCESS_INFORMATION));
-
- int cmdlen= 0;
- for (int i= 0; instance_options->argv[i] != 0; i++)
- cmdlen+= (uint) strlen(instance_options->argv[i]) + 3;
- cmdlen++; /* make room for the null */
-
- char *cmdline= new char[cmdlen];
- if (cmdline == NULL)
- return TRUE;
-
- cmdline[0]= 0;
- for (int i= 0; instance_options->argv[i] != 0; i++)
- {
- strcat(cmdline, "\"");
- strcat(cmdline, instance_options->argv[i]);
- strcat(cmdline, "\" ");
- }
-
- /* Start the child process */
- BOOL result=
- CreateProcess(NULL, /* Put it all in cmdline */
- cmdline, /* Command line */
- NULL, /* Process handle not inheritable */
- NULL, /* Thread handle not inheritable */
- FALSE, /* Set handle inheritance to FALSE */
- 0, /* No creation flags */
- NULL, /* Use parent's environment block */
- NULL, /* Use parent's starting directory */
- &si, /* Pointer to STARTUPINFO structure */
- pi); /* Pointer to PROCESS_INFORMATION structure */
- delete cmdline;
-
- return !result;
-}
-#endif
-
-#ifdef __WIN__
-
-BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
-{
- DWORD dwTID, dwCode, dwErr= 0;
- HANDLE hProcessDup= INVALID_HANDLE_VALUE;
- HANDLE hRT= NULL;
- HINSTANCE hKernel= GetModuleHandle("Kernel32");
- BOOL bSuccess= FALSE;
-
- BOOL bDup= DuplicateHandle(GetCurrentProcess(),
- hProcess, GetCurrentProcess(), &hProcessDup,
- PROCESS_ALL_ACCESS, FALSE, 0);
-
- // Detect the special case where the process is
- // already dead...
- if (GetExitCodeProcess((bDup) ? hProcessDup : hProcess, &dwCode) &&
- (dwCode == STILL_ACTIVE))
- {
- FARPROC pfnExitProc;
-
- pfnExitProc= GetProcAddress(hKernel, "ExitProcess");
-
- hRT= CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0,
- (LPTHREAD_START_ROUTINE)pfnExitProc,
- (PVOID)uExitCode, 0, &dwTID);
-
- if (hRT == NULL)
- dwErr= GetLastError();
- }
- else
- dwErr= ERROR_PROCESS_ABORTED;
-
- if (hRT)
- {
- // Must wait process to terminate to
- // guarantee that it has exited...
- WaitForSingleObject((bDup) ? hProcessDup : hProcess, INFINITE);
-
- CloseHandle(hRT);
- bSuccess= TRUE;
- }
-
- if (bDup)
- CloseHandle(hProcessDup);
-
- if (!bSuccess)
- SetLastError(dwErr);
-
- return bSuccess;
-}
-
-int kill(pid_t pid, int signum)
-{
- HANDLE processhandle= ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
- if (signum == SIGTERM)
- ::SafeTerminateProcess(processhandle, 0);
- else
- ::TerminateProcess(processhandle, -1);
- return 0;
-}
-#endif
-
-/*************************************************************************
- }}}
-*************************************************************************/
-
-
-/*************************************************************************
- {{{ Static constants.
-*************************************************************************/
-
-const LEX_STRING
-Instance::DFLT_INSTANCE_NAME= { C_STRING_WITH_LEN("mysqld") };
-
-/*************************************************************************
- }}}
-*************************************************************************/
-
-
-/*************************************************************************
- {{{ Instance Monitor thread.
-*************************************************************************/
-
-/**
- Proxy thread is a simple way to avoid all pitfalls of the threads
- implementation in the OS (e.g. LinuxThreads). With such a thread we
- don't have to process SIGCHLD, which is a tricky business if we want
- to do it in a portable way.
-
- Instance Monitor Thread forks a child process, execs mysqld and waits for
- the child to die.
-
- Instance Monitor assumes that the monitoring instance will not be dropped.
- This is guaranteed by having flag monitoring_thread_active and
- Instance::is_active() operation.
-*/
-
-class Instance_monitor: public Thread
-{
-public:
- Instance_monitor(Instance *instance_arg) :instance(instance_arg) {}
-protected:
- virtual void run();
- void start_and_monitor_instance();
-private:
- Instance *instance;
-};
-
-
-void Instance_monitor::run()
-{
- start_and_monitor_instance();
- delete this;
-}
-
-
-void Instance_monitor::start_and_monitor_instance()
-{
- Thread_registry *thread_registry= Manager::get_thread_registry();
- Guardian *guardian= Manager::get_guardian();
-
- My_process_info mysqld_process_info;
- Thread_info monitor_thread_info;
-
- log_info("Instance '%s': Monitor: started.",
- (const char *) instance->get_name()->str);
-
- /*
- For guarded instance register the thread in Thread_registry to wait for
- the thread to stop on shutdown (nonguarded instances are not stopped on
- shutdown, so the thread will no finish).
- */
-
- if (instance->is_guarded())
- {
- thread_registry->register_thread(&monitor_thread_info, FALSE);
- }
-
- /* Starting mysqld. */
-
- log_info("Instance '%s': Monitor: starting mysqld...",
- (const char *) instance->get_name()->str);
-
- if (start_process(&instance->options, &mysqld_process_info))
- {
- instance->lock();
- instance->monitoring_thread_active= FALSE;
- instance->unlock();
-
- return;
- }
-
- /* Waiting for mysqld to die. */
-
- log_info("Instance '%s': Monitor: waiting for mysqld to stop...",
- (const char *) instance->get_name()->str);
-
- wait_process(&mysqld_process_info); /* Don't check for return value. */
-
- log_info("Instance '%s': Monitor: mysqld stopped.",
- (const char *) instance->get_name()->str);
-
- /* Update instance status. */
-
- instance->lock();
-
- if (instance->is_guarded())
- thread_registry->unregister_thread(&monitor_thread_info);
-
- instance->crashed= TRUE;
- instance->monitoring_thread_active= FALSE;
-
- log_info("Instance '%s': Monitor: finished.",
- (const char *) instance->get_name()->str);
-
- instance->unlock();
-
- /* Wake up guardian. */
-
- guardian->ping();
-}
-
-/**************************************************************************
- }}}
-**************************************************************************/
-
-
-/**************************************************************************
- {{{ Static operations.
-**************************************************************************/
-
-/**
- The operation is intended to check whether string is a well-formed
- instance name or not.
-
- SYNOPSIS
- is_name_valid()
- name string to check
-
- RETURN
- TRUE string is a valid instance name
- FALSE string is not a valid instance name
-
- TODO: Move to Instance_name class: Instance_name::is_valid().
-*/
-
-bool Instance::is_name_valid(const LEX_STRING *name)
-{
- const char *name_suffix= name->str + DFLT_INSTANCE_NAME.length;
-
- if (strncmp(name->str, Instance::DFLT_INSTANCE_NAME.str,
- Instance::DFLT_INSTANCE_NAME.length) != 0)
- return FALSE;
-
- return *name_suffix == 0 || my_isdigit(default_charset_info, *name_suffix);
-}
-
-
-/**
- The operation is intended to check if the given instance name is
- mysqld-compatible or not.
-
- SYNOPSIS
- is_mysqld_compatible_name()
- name name to check
-
- RETURN
- TRUE name is mysqld-compatible
- FALSE otherwise
-
- TODO: Move to Instance_name class: Instance_name::is_mysqld_compatible().
-*/
-
-bool Instance::is_mysqld_compatible_name(const LEX_STRING *name)
-{
- return strcmp(name->str, DFLT_INSTANCE_NAME.str) == 0;
-}
-
-
-/**
- Return client state name. Must not be used outside the class.
- Use Instance::get_state_name() instead.
-*/
-
-const char * Instance::get_instance_state_name(enum_instance_state state)
-{
- switch (state) {
- case STOPPED:
- return "offline";
-
- case NOT_STARTED:
- return "not started";
-
- case STARTING:
- return "starting";
-
- case STARTED:
- return "online";
-
- case JUST_CRASHED:
- return "failed";
-
- case CRASHED:
- return "crashed";
-
- case CRASHED_AND_ABANDONED:
- return "abandoned";
-
- case STOPPING:
- return "stopping";
- }
-
- return NULL; /* just to ignore compiler warning. */
-}
-
-/**************************************************************************
- }}}
-**************************************************************************/
-
-
-/**************************************************************************
- {{{ Initialization & deinitialization.
-**************************************************************************/
-
-Instance::Instance()
- :monitoring_thread_active(FALSE),
- crashed(FALSE),
- configured(FALSE),
- /* mysqld_compatible is initialized in init() */
- state(NOT_STARTED),
- restart_counter(0),
- crash_moment(0),
- last_checked(0)
-{
- pthread_mutex_init(&LOCK_instance, 0);
-}
-
-
-Instance::~Instance()
-{
- log_info("Instance '%s': destroying...", (const char *) get_name()->str);
-
- pthread_mutex_destroy(&LOCK_instance);
-}
-
-
-/**
- Initialize instance options.
-
- SYNOPSIS
- init()
- name_arg name of the instance
-
- RETURN:
- FALSE - ok
- TRUE - error
-*/
-
-bool Instance::init(const LEX_STRING *name_arg)
-{
- mysqld_compatible= is_mysqld_compatible_name(name_arg);
-
- return options.init(name_arg);
-}
-
-
-/**
- @brief Complete instance options initialization.
-
- @return Error status.
- @retval FALSE ok
- @retval TRUE error
-*/
-
-bool Instance::complete_initialization()
-{
- configured= ! options.complete_initialization();
- return !configured;
-}
-
-/**************************************************************************
- }}}
-**************************************************************************/
-
-
-/**************************************************************************
- {{{ Instance: public interface implementation.
-**************************************************************************/
-
-/**
- Determine if there is some activity with the instance.
-
- SYNOPSIS
- is_active()
-
- DESCRIPTION
- An instance is active if one of the following conditions is true:
- - Instance-monitoring thread is running;
- - Instance is guarded and its state is other than STOPPED;
- - Corresponding mysqld-server accepts connections.
-
- MT-NOTE: instance must be locked before calling the operation.
-
- RETURN
- TRUE - instance is active
- FALSE - otherwise.
-*/
-
-bool Instance::is_active()
-{
- if (monitoring_thread_active)
- return TRUE;
-
- if (is_guarded() && get_state() != STOPPED)
- return TRUE;
-
- return is_mysqld_running();
-}
-
-
-/**
- Determine if mysqld is accepting connections.
-
- SYNOPSIS
- is_mysqld_running()
-
- DESCRIPTION
- Try to connect to mysqld with fake login/password to check whether it is
- accepting connections or not.
-
- MT-NOTE: instance must be locked before calling the operation.
-
- RETURN
- TRUE - mysqld is alive and accept connections
- FALSE - otherwise.
-*/
-
-bool Instance::is_mysqld_running()
-{
- MYSQL mysql;
- uint port= options.get_mysqld_port(); /* 0 if not specified. */
- const char *socket= NULL;
- static const char *password= "check_connection";
- static const char *username= "MySQL_Instance_Manager";
- static const char *access_denied_message= "Access denied for user";
- bool return_val;
-
- if (options.mysqld_socket)
- socket= options.mysqld_socket;
-
- /* no port was specified => instance falled back to default value */
- if (!port && !options.mysqld_socket)
- port= SERVER_DEFAULT_PORT;
-
- mysql_init(&mysql);
- /* try to connect to a server with a fake username/password pair */
- if (mysql_real_connect(&mysql, LOCAL_HOST, username,
- password,
- NullS, port,
- socket, 0))
- {
- /*
- We have successfully connected to the server using fake
- username/password. Write a warning to the logfile.
- */
- log_error("Instance '%s': was able to log into mysqld.",
- (const char *) get_name()->str);
- return_val= TRUE; /* server is alive */
- }
- else
- return_val= test(!strncmp(access_denied_message, mysql_error(&mysql),
- sizeof(access_denied_message) - 1));
-
- mysql_close(&mysql);
-
- return return_val;
-}
-
-
-/**
- @brief Start mysqld.
-
- Reset flags and start Instance Monitor thread, which will start mysqld.
-
- @note Instance must be locked before calling the operation.
-
- @return Error status code
- @retval FALSE Ok
- @retval TRUE Could not start instance
-*/
-
-bool Instance::start_mysqld()
-{
- Instance_monitor *instance_monitor;
-
- if (!configured)
- return TRUE;
-
- /*
- Prepare instance to start Instance Monitor thread.
-
- NOTE: It's important to set these actions here in order to avoid
- race conditions -- these actions must be done under acquired lock on
- Instance.
- */
-
- crashed= FALSE;
- monitoring_thread_active= TRUE;
-
- remove_pid();
-
- /* Create and start the Instance Monitor thread. */
-
- instance_monitor= new Instance_monitor(this);
-
- if (instance_monitor == NULL || instance_monitor->start(Thread::DETACHED))
- {
- delete instance_monitor;
- monitoring_thread_active= FALSE;
-
- log_error("Instance '%s': can not create instance monitor thread.",
- (const char *) get_name()->str);
-
- return TRUE;
- }
-
- ++restart_counter;
-
- /* The Instance Monitor thread will delete itself when it's finished. */
-
- return FALSE;
-}
-
-
-/**
- Stop mysqld.
-
- SYNOPSIS
- stop_mysqld()
-
- DESCRIPTION
- Try to stop mysqld gracefully. Otherwise kill it with SIGKILL.
-
- MT-NOTE: instance must be locked before calling the operation.
-
- RETURN
- FALSE - ok
- TRUE - could not stop the instance
-*/
-
-bool Instance::stop_mysqld()
-{
- log_info("Instance '%s': stopping mysqld...",
- (const char *) get_name()->str);
-
- kill_mysqld(SIGTERM);
-
- if (!wait_for_stop())
- {
- log_info("Instance '%s': mysqld stopped gracefully.",
- (const char *) get_name()->str);
- return FALSE;
- }
-
- log_info("Instance '%s': mysqld failed to stop gracefully within %d seconds.",
- (const char *) get_name()->str,
- (int) options.get_shutdown_delay());
-
- log_info("Instance'%s': killing mysqld...",
- (const char *) get_name()->str);
-
- kill_mysqld(SIGKILL);
-
- if (!wait_for_stop())
- {
- log_info("Instance '%s': mysqld has been killed.",
- (const char *) get_name()->str);
- return FALSE;
- }
-
- log_info("Instance '%s': can not kill mysqld within %d seconds.",
- (const char *) get_name()->str,
- (int) options.get_shutdown_delay());
-
- return TRUE;
-}
-
-
-/**
- Send signal to mysqld.
-
- SYNOPSIS
- kill_mysqld()
-
- DESCRIPTION
- Load pid from the pid file and send the given signal to that process.
- If the signal is SIGKILL, remove the pid file after sending the signal.
-
- MT-NOTE: instance must be locked before calling the operation.
-
- TODO
- This too low-level and OS-specific operation for public interface.
- Also, it has some implicit behaviour for SIGKILL signal. Probably, we
- should have the following public operations instead:
- - start_mysqld() -- as is;
- - stop_mysqld -- request mysqld to shutdown gracefully (send SIGTERM);
- don't wait for complete shutdown;
- - wait_for_stop() (or join_mysqld()) -- wait for mysqld to stop within
- time interval;
- - kill_mysqld() -- request to terminate mysqld; don't wait for
- completion.
- These operations should also be used in Guardian to manage instances.
-*/
-
-bool Instance::kill_mysqld(int signum)
-{
- pid_t mysqld_pid= options.load_pid();
-
- if (mysqld_pid == 0)
- {
- log_info("Instance '%s': no pid file to send a signal (%d).",
- (const char *) get_name()->str,
- (int) signum);
- return TRUE;
- }
-
- log_info("Instance '%s': sending %d to %d...",
- (const char *) get_name()->str,
- (int) signum,
- (int) mysqld_pid);
-
- if (kill(mysqld_pid, signum))
- {
- log_info("Instance '%s': kill() failed.",
- (const char *) get_name()->str);
- return TRUE;
- }
-
- /* Kill suceeded */
- if (signum == SIGKILL) /* really killed instance with SIGKILL */
- {
- log_error("Instance '%s': killed.",
- (const char *) options.instance_name.str);
-
- /* After sucessful hard kill the pidfile need to be removed */
- options.unlink_pidfile();
- }
-
- return FALSE;
-}
-
-
-/**
- Lock instance.
-*/
-
-void Instance::lock()
-{
- pthread_mutex_lock(&LOCK_instance);
-}
-
-
-/**
- Unlock instance.
-*/
-
-void Instance::unlock()
-{
- pthread_mutex_unlock(&LOCK_instance);
-}
-
-
-/**
- Return instance state name.
-
- SYNOPSIS
- get_state_name()
-
- DESCRIPTION
- The operation returns user-friendly state name. The operation can be
- used both for guarded and non-guarded instances.
-
- MT-NOTE: instance must be locked before calling the operation.
-
- TODO: Replace with the static get_state_name(state_code) function.
-*/
-
-const char *Instance::get_state_name()
-{
- if (!is_configured())
- return "misconfigured";
-
- if (is_guarded())
- {
- /* The instance is managed by Guardian: we can report precise state. */
-
- return get_instance_state_name(get_state());
- }
-
- /* The instance is not managed by Guardian: we can report status only. */
-
- return is_active() ? "online" : "offline";
-}
-
-
-/**
- Reset statistics.
-
- SYNOPSIS
- reset_stat()
-
- DESCRIPTION
- The operation resets statistics used for guarding the instance.
-
- MT-NOTE: instance must be locked before calling the operation.
-
- TODO: Make private.
-*/
-
-void Instance::reset_stat()
-{
- restart_counter= 0;
- crash_moment= 0;
- last_checked= 0;
-}
-
-/**************************************************************************
- }}}
-**************************************************************************/
-
-
-/**************************************************************************
- {{{ Instance: implementation of private operations.
-**************************************************************************/
-
-/**
- Remove pid file.
-*/
-
-void Instance::remove_pid()
-{
- int mysqld_pid= options.load_pid();
-
- if (mysqld_pid == 0)
- return;
-
- if (options.unlink_pidfile())
- {
- log_error("Instance '%s': can not unlink pid file.",
- (const char *) options.instance_name.str);
- }
-}
-
-
-/**
- Wait for mysqld to stop within shutdown interval.
-*/
-
-bool Instance::wait_for_stop()
-{
- int start_time= (int) time(NULL);
- int finish_time= start_time + options.get_shutdown_delay();
-
- log_info("Instance '%s': waiting for mysqld to stop "
- "(timeout: %d seconds)...",
- (const char *) get_name()->str,
- (int) options.get_shutdown_delay());
-
- while (true)
- {
- if (options.load_pid() == 0 && !is_mysqld_running())
- return FALSE;
-
- if (time(NULL) >= finish_time)
- return TRUE;
-
- /* Sleep for 0.3 sec and check again. */
-
- my_sleep(300000);
- }
-}
-
-/**************************************************************************
- }}}
-**************************************************************************/
diff --git a/server-tools/instance-manager/instance.h b/server-tools/instance-manager/instance.h
deleted file mode 100644
index aa9c923cba1..00000000000
--- a/server-tools/instance-manager/instance.h
+++ /dev/null
@@ -1,273 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 "instance_options.h"
-#include "priv.h"
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-class Instance_map;
-class Thread_registry;
-
-
-/**
- Instance_name -- the class represents instance name -- a string of length
- less than MAX_INSTANCE_NAME_SIZE.
-
- Generally, this is just a string with self-memory-management and should be
- eliminated in the future.
-*/
-
-class Instance_name
-{
-public:
- Instance_name(const LEX_STRING *name);
-
-public:
- inline const LEX_STRING *get_str() const
- {
- return &str;
- }
-
- inline const char *get_c_str() const
- {
- return str.str;
- }
-
- inline uint get_length() const
- {
- return str.length;
- }
-
-private:
- LEX_STRING str;
- char str_buffer[MAX_INSTANCE_NAME_SIZE];
-};
-
-
-class Instance
-{
-public:
- /* States of an instance. */
- enum enum_instance_state
- {
- STOPPED,
- NOT_STARTED,
- STARTING,
- STARTED,
- JUST_CRASHED,
- CRASHED,
- CRASHED_AND_ABANDONED,
- STOPPING
- };
-
-public:
- /**
- The constant defines name of the default mysqld-instance ("mysqld").
- */
- static const LEX_STRING DFLT_INSTANCE_NAME;
-
-public:
- static bool is_name_valid(const LEX_STRING *name);
- static bool is_mysqld_compatible_name(const LEX_STRING *name);
-
-public:
- Instance();
- ~Instance();
-
- bool init(const LEX_STRING *name_arg);
- bool complete_initialization();
-
-public:
- bool is_active();
-
- bool is_mysqld_running();
-
- bool start_mysqld();
- bool stop_mysqld();
- bool kill_mysqld(int signo);
-
- void lock();
- void unlock();
-
- const char *get_state_name();
-
- void reset_stat();
-
-public:
- /**
- The operation is intended to check if the instance is mysqld-compatible
- or not.
- */
- inline bool is_mysqld_compatible() const;
-
- /**
- The operation is intended to check if the instance is configured properly
- or not. Misconfigured instances are not managed.
- */
- inline bool is_configured() const;
-
- /**
- The operation returns TRUE if the instance is guarded and FALSE otherwise.
- */
- inline bool is_guarded() const;
-
- /**
- The operation returns name of the instance.
- */
- inline const LEX_STRING *get_name() const;
-
- /**
- The operation returns the current state of the instance.
-
- NOTE: At the moment should be used only for guarded instances.
- */
- inline enum_instance_state get_state() const;
-
- /**
- The operation changes the state of the instance.
-
- NOTE: At the moment should be used only for guarded instances.
- TODO: Make private.
- */
- inline void set_state(enum_instance_state new_state);
-
- /**
- The operation returns crashed flag.
- */
- inline bool is_crashed();
-
-public:
- /**
- This attributes contains instance options.
-
- TODO: Make private.
- */
- Instance_options options;
-
-private:
- /**
- monitoring_thread_active is TRUE if there is a thread that monitors the
- corresponding mysqld-process.
- */
- bool monitoring_thread_active;
-
- /**
- crashed is TRUE when corresponding mysqld-process has been died after
- start.
- */
- bool crashed;
-
- /**
- configured is TRUE when the instance is configured and FALSE otherwise.
- Misconfigured instances are not managed.
- */
- bool configured;
-
- /*
- mysqld_compatible specifies whether the instance is mysqld-compatible
- or not. Mysqld-compatible instances can contain only mysqld-specific
- options. At the moment an instance is mysqld-compatible if its name is
- "mysqld".
-
- The idea is that [mysqld] section should contain only mysqld-specific
- options (no Instance Manager-specific options) to be readable by mysqld
- program.
- */
- bool mysqld_compatible;
-
- /*
- Mutex protecting the instance.
- */
- pthread_mutex_t LOCK_instance;
-
-private:
- /* Guarded-instance attributes. */
-
- /* state of an instance (i.e. STARTED, CRASHED, etc.) */
- enum_instance_state state;
-
-public:
- /* the amount of attemts to restart instance (cleaned up at success) */
- int restart_counter;
-
- /* triggered at a crash */
- time_t crash_moment;
-
- /* General time field. Used to provide timeouts (at shutdown and restart) */
- time_t last_checked;
-
-private:
- static const char *get_instance_state_name(enum_instance_state state);
-
-private:
- void remove_pid();
-
- bool wait_for_stop();
-
-private:
- friend class Instance_monitor;
-};
-
-
-inline bool Instance::is_mysqld_compatible() const
-{
- return mysqld_compatible;
-}
-
-
-inline bool Instance::is_configured() const
-{
- return configured;
-}
-
-
-inline bool Instance::is_guarded() const
-{
- return !options.nonguarded;
-}
-
-
-inline const LEX_STRING *Instance::get_name() const
-{
- return &options.instance_name;
-}
-
-
-inline Instance::enum_instance_state Instance::get_state() const
-{
- return state;
-}
-
-
-inline void Instance::set_state(enum_instance_state new_state)
-{
- state= new_state;
-}
-
-
-inline bool Instance::is_crashed()
-{
- return crashed;
-}
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_H */
diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc
deleted file mode 100644
index b137370b50a..00000000000
--- a/server-tools/instance-manager/instance_map.cc
+++ /dev/null
@@ -1,649 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "instance_map.h"
-
-#include <my_global.h>
-#include <m_ctype.h>
-#include <mysql_com.h>
-
-#include "buffer.h"
-#include "instance.h"
-#include "log.h"
-#include "mysqld_error.h"
-#include "mysql_manager_error.h"
-#include "options.h"
-#include "priv.h"
-
-C_MODE_START
-
-/**
- HASH-routines: get key of instance for storing in hash.
-*/
-
-static uchar* get_instance_key(const uchar* u, size_t* len,
- my_bool __attribute__((unused)) t)
-{
- const Instance *instance= (const Instance *) u;
- *len= instance->options.instance_name.length;
- return (uchar *) instance->options.instance_name.str;
-}
-
-/**
- HASH-routines: cleanup handler.
-*/
-
-static void delete_instance(void *u)
-{
- Instance *instance= (Instance *) u;
- delete instance;
-}
-
-/**
- The option handler to pass to the process_default_option_files function.
-
- SYNOPSIS
- process_option()
- ctx Handler context. Here it is an instance_map structure.
- group_name The name of the group the option belongs to.
- option The very option to be processed. It is already
- prepared to be used in argv (has -- prefix)
-
- DESCRIPTION
-
- This handler checks whether a group is an instance group and adds
- an option to the appropriate instance class. If this is the first
- occurence of an instance name, we'll also create the instance
- with such name and add it to the instance map.
-
- RETURN
- 0 - ok
- 1 - error occured
-*/
-
-static int process_option(void *ctx, const char *group, const char *option)
-{
- Instance_map *map= (Instance_map*) ctx;
- LEX_STRING group_str;
-
- group_str.str= (char *) group;
- group_str.length= strlen(group);
-
- return map->process_one_option(&group_str, option);
-}
-
-C_MODE_END
-
-
-/**
- Parse option string.
-
- SYNOPSIS
- parse_option()
- option_str [IN] option string (e.g. "--name=value")
- option_name_buf [OUT] parsed name of the option.
- Must be of (MAX_OPTION_LEN + 1) size.
- option_value_buf [OUT] parsed value of the option.
- Must be of (MAX_OPTION_LEN + 1) size.
-
- DESCRIPTION
- This is an auxiliary function and should not be used externally. It is
- intended to parse whole option string into option name and option value.
-*/
-
-static void parse_option(const char *option_str,
- char *option_name_buf,
- char *option_value_buf)
-{
- const char *eq_pos;
- const char *ptr= option_str;
-
- while (*ptr == '-')
- ++ptr;
-
- strmake(option_name_buf, ptr, MAX_OPTION_LEN + 1);
-
- eq_pos= strchr(ptr, '=');
- if (eq_pos)
- {
- option_name_buf[eq_pos - ptr]= 0;
- strmake(option_value_buf, eq_pos + 1, MAX_OPTION_LEN + 1);
- }
- else
- {
- option_value_buf[0]= 0;
- }
-}
-
-
-/**
- Process one option from the configuration file.
-
- SYNOPSIS
- Instance_map::process_one_option()
- group group name
- option option string (e.g. "--name=value")
-
- DESCRIPTION
- This is an auxiliary function and should not be used externally.
- It is used only by flush_instances(), which pass it to
- process_option(). The caller ensures proper locking
- of the instance map object.
-*/
- /*
- Process a given option and assign it to appropricate instance. This is
- required for the option handler, passed to my_search_option_files().
- */
-
-int Instance_map::process_one_option(const LEX_STRING *group,
- const char *option)
-{
- Instance *instance= NULL;
-
- if (!Instance::is_name_valid(group))
- {
- /*
- Current section name is not a valid instance name.
- We should skip it w/o error.
- */
- return 0;
- }
-
- if (!(instance= (Instance *) hash_search(&hash, (uchar *) group->str,
- group->length)))
- {
- if (!(instance= new Instance()))
- return 1;
-
- if (instance->init(group) || add_instance(instance))
- {
- delete instance;
- return 1;
- }
-
- if (instance->is_mysqld_compatible())
- log_info("Warning: instance name '%s' is mysqld-compatible.",
- (const char *) group->str);
-
- log_info("mysqld instance '%s' has been added successfully.",
- (const char *) group->str);
- }
-
- if (option)
- {
- char option_name[MAX_OPTION_LEN + 1];
- char option_value[MAX_OPTION_LEN + 1];
-
- parse_option(option, option_name, option_value);
-
- if (instance->is_mysqld_compatible() &&
- Instance_options::is_option_im_specific(option_name))
- {
- log_info("Warning: configuration of mysqld-compatible instance '%s' "
- "contains IM-specific option '%s'. "
- "This breaks backward compatibility for the configuration file.",
- (const char *) group->str,
- (const char *) option_name);
- }
-
- Named_value option(option_name, option_value);
-
- if (instance->options.set_option(&option))
- return 1; /* the instance'll be deleted when we destroy the map */
- }
-
- return 0;
-}
-
-
-/**
- Instance_map constructor.
-*/
-
-Instance_map::Instance_map()
-{
- pthread_mutex_init(&LOCK_instance_map, 0);
-}
-
-
-/**
- Initialize Instance_map internals.
-*/
-
-bool Instance_map::init()
-{
- return hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
- get_instance_key, delete_instance, 0);
-}
-
-
-/**
- Reset Instance_map data.
-*/
-
-bool Instance_map::reset()
-{
- hash_free(&hash);
- return init();
-}
-
-
-/**
- Instance_map destructor.
-*/
-
-Instance_map::~Instance_map()
-{
- lock();
-
- /*
- NOTE: it's necessary to synchronize on each instance before removal,
- because Instance-monitoring thread can be still alive an hold the mutex
- (because it is detached and we have no control over it).
- */
-
- while (true)
- {
- Iterator it(this);
- Instance *instance= it.next();
-
- if (!instance)
- break;
-
- instance->lock();
- instance->unlock();
-
- remove_instance(instance);
- }
-
- hash_free(&hash);
- unlock();
-
- pthread_mutex_destroy(&LOCK_instance_map);
-}
-
-
-/**
- Lock Instance_map.
-*/
-
-void Instance_map::lock()
-{
- pthread_mutex_lock(&LOCK_instance_map);
-}
-
-
-/**
- Unlock Instance_map.
-*/
-
-void Instance_map::unlock()
-{
- pthread_mutex_unlock(&LOCK_instance_map);
-}
-
-
-/**
- Check if there is an active instance or not.
-*/
-
-bool Instance_map::is_there_active_instance()
-{
- Instance *instance;
- Iterator iterator(this);
-
- while ((instance= iterator.next()))
- {
- bool active_instance_found;
-
- instance->lock();
- active_instance_found= instance->is_active();
- instance->unlock();
-
- if (active_instance_found)
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/**
- Add an instance into the internal hash.
-
- MT-NOTE: Instance Map must be locked before calling the operation.
-*/
-
-int Instance_map::add_instance(Instance *instance)
-{
- return my_hash_insert(&hash, (uchar *) instance);
-}
-
-
-/**
- Remove instance from the internal hash.
-
- MT-NOTE: Instance Map must be locked before calling the operation.
-*/
-
-int Instance_map::remove_instance(Instance *instance)
-{
- return hash_delete(&hash, (uchar *) instance);
-}
-
-
-/**
- Create a new instance and register it in the internal hash.
-
- MT-NOTE: Instance Map must be locked before calling the operation.
-*/
-
-int Instance_map::create_instance(const LEX_STRING *instance_name,
- const Named_value_arr *options)
-{
- Instance *instance= new Instance();
-
- if (!instance)
- {
- log_error("Can not allocate instance (name: '%s').",
- (const char *) instance_name->str);
- return ER_OUT_OF_RESOURCES;
- }
-
- if (instance->init(instance_name))
- {
- log_error("Can not initialize instance (name: '%s').",
- (const char *) instance_name->str);
- delete instance;
- return ER_OUT_OF_RESOURCES;
- }
-
- for (int i= 0; options && i < options->get_size(); ++i)
- {
- Named_value option= options->get_element(i);
-
- if (instance->is_mysqld_compatible() &&
- Instance_options::is_option_im_specific(option.get_name()))
- {
- log_error("IM-option (%s) can not be used "
- "in configuration of mysqld-compatible instance (%s).",
- (const char *) option.get_name(),
- (const char *) instance_name->str);
- delete instance;
- return ER_INCOMPATIBLE_OPTION;
- }
-
- instance->options.set_option(&option);
- }
-
- if (instance->is_mysqld_compatible())
- log_info("Warning: instance name '%s' is mysqld-compatible.",
- (const char *) instance_name->str);
-
- if (instance->complete_initialization())
- {
- log_error("Can not complete initialization of instance (name: '%s').",
- (const char *) instance_name->str);
- delete instance;
- return ER_OUT_OF_RESOURCES;
- /* TODO: return more appropriate error code in this case. */
- }
-
- if (add_instance(instance))
- {
- log_error("Can not register instance (name: '%s').",
- (const char *) instance_name->str);
- delete instance;
- return ER_OUT_OF_RESOURCES;
- }
-
- return 0;
-}
-
-
-/**
- Return a pointer to the instance or NULL, if there is no such instance.
-
- MT-NOTE: Instance Map must be locked before calling the operation.
-*/
-
-Instance * Instance_map::find(const LEX_STRING *name)
-{
- return (Instance *) hash_search(&hash, (uchar *) name->str, name->length);
-}
-
-
-/**
- Init instances command line arguments after all options have been loaded.
-*/
-
-bool Instance_map::complete_initialization()
-{
- bool mysqld_found;
-
- /* Complete initialization of all registered instances. */
-
- for (uint i= 0; i < hash.records; ++i)
- {
- Instance *instance= (Instance *) hash_element(&hash, i);
-
- if (instance->complete_initialization())
- return TRUE;
- }
-
- /* That's all if we are runnning in an ordinary mode. */
-
- if (!Options::Main::mysqld_safe_compatible)
- return FALSE;
-
- /* In mysqld-compatible mode we must ensure that there 'mysqld' instance. */
-
- mysqld_found= find(&Instance::DFLT_INSTANCE_NAME) != NULL;
-
- if (mysqld_found)
- return FALSE;
-
- if (create_instance(&Instance::DFLT_INSTANCE_NAME, NULL))
- {
- log_error("Can not create default instance.");
- return TRUE;
- }
-
- switch (create_instance_in_file(&Instance::DFLT_INSTANCE_NAME, NULL))
- {
- case 0:
- case ER_CONF_FILE_DOES_NOT_EXIST:
- /*
- Continue if the instance has been added to the config file
- successfully, or the config file just does not exist.
- */
- break;
-
- default:
- log_error("Can not add default instance to the config file.");
-
- Instance *instance= find(&Instance::DFLT_INSTANCE_NAME);
-
- if (instance)
- remove_instance(instance); /* instance is deleted here. */
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/**
- Load options from config files and create appropriate instance
- structures.
-*/
-
-int Instance_map::load()
-{
- int argc= 1;
- /* this is a dummy variable for search_option_files() */
- uint args_used= 0;
- const char *argv_options[3];
- char **argv= (char **) &argv_options;
- char defaults_file_arg[FN_REFLEN];
-
- /* the name of the program may be orbitrary here in fact */
- argv_options[0]= "mysqlmanager";
-
- /*
- If the option file was forced by the user when starting
- the IM with --defaults-file=xxxx, make sure it is also
- passed as --defaults-file, not only as Options::config_file.
- This is important for option files given with relative path:
- e.g. --defaults-file=my.cnf.
- Otherwise my_search_option_files will treat "my.cnf" as a group
- name and start looking for files named "my.cnf.cnf" in all
- default dirs. Which is not what we want.
- */
- if (Options::Main::is_forced_default_file)
- {
- snprintf(defaults_file_arg, FN_REFLEN, "--defaults-file=%s",
- Options::Main::config_file);
-
- argv_options[1]= defaults_file_arg;
- argv_options[2]= '\0';
-
- argc= 2;
- }
- else
- argv_options[1]= '\0';
-
- /*
- If the routine failed, we'll simply fallback to defaults in
- complete_initialization().
- */
- if (my_search_option_files(Options::Main::config_file, &argc,
- (char ***) &argv, &args_used,
- process_option, (void*) this,
- Options::default_directories))
- log_info("Falling back to compiled-in defaults.");
-
- return complete_initialization();
-}
-
-
-/*************************************************************************
- {{{ Instance_map::Iterator implementation.
-*************************************************************************/
-
-void Instance_map::Iterator::go_to_first()
-{
- current_instance=0;
-}
-
-
-Instance *Instance_map::Iterator::next()
-{
- if (current_instance < instance_map->hash.records)
- return (Instance *) hash_element(&instance_map->hash, current_instance++);
-
- return NULL;
-}
-
-/*************************************************************************
- }}}
-*************************************************************************/
-
-
-/**
- Create a new configuration section for mysqld-instance in the config file.
-
- SYNOPSIS
- create_instance_in_file()
- instance_name mysqld-instance name
- options options for the new mysqld-instance
-
- RETURN
- 0 On success
- ER_CONF_FILE_DOES_NOT_EXIST If config file does not exist
- ER_ACCESS_OPTION_FILE If config file is not writable or some I/O
- error ocurred during writing configuration
-*/
-
-int create_instance_in_file(const LEX_STRING *instance_name,
- const Named_value_arr *options)
-{
- File cnf_file;
-
- if (my_access(Options::Main::config_file, W_OK))
- {
- log_error("Configuration file (%s) does not exist.",
- (const char *) Options::Main::config_file);
- return ER_CONF_FILE_DOES_NOT_EXIST;
- }
-
- cnf_file= my_open(Options::Main::config_file, O_WRONLY | O_APPEND, MYF(0));
-
- if (cnf_file <= 0)
- {
- log_error("Can not open configuration file (%s): %s.",
- (const char *) Options::Main::config_file,
- (const char *) strerror(errno));
- return ER_ACCESS_OPTION_FILE;
- }
-
- if (my_write(cnf_file, (uchar*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)) ||
- my_write(cnf_file, (uchar*)"[", 1, MYF(MY_NABP)) ||
- my_write(cnf_file, (uchar*)instance_name->str, instance_name->length,
- MYF(MY_NABP)) ||
- my_write(cnf_file, (uchar*)"]", 1, MYF(MY_NABP)) ||
- my_write(cnf_file, (uchar*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)))
- {
- log_error("Can not write to configuration file (%s): %s.",
- (const char *) Options::Main::config_file,
- (const char *) strerror(errno));
- my_close(cnf_file, MYF(0));
- return ER_ACCESS_OPTION_FILE;
- }
-
- for (int i= 0; options && i < options->get_size(); ++i)
- {
- char option_str[MAX_OPTION_STR_LEN];
- char *ptr;
- int option_str_len;
- Named_value option= options->get_element(i);
-
- ptr= strxnmov(option_str, MAX_OPTION_LEN + 1, option.get_name(), NullS);
-
- if (option.get_value()[0])
- ptr= strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
-
- option_str_len= ptr - option_str;
-
- if (my_write(cnf_file, (uchar*)option_str, option_str_len, MYF(MY_NABP)) ||
- my_write(cnf_file, (uchar*)NEWLINE, NEWLINE_LEN, MYF(MY_NABP)))
- {
- log_error("Can not write to configuration file (%s): %s.",
- (const char *) Options::Main::config_file,
- (const char *) strerror(errno));
- my_close(cnf_file, MYF(0));
- return ER_ACCESS_OPTION_FILE;
- }
- }
-
- my_close(cnf_file, MYF(0));
-
- return 0;
-}
diff --git a/server-tools/instance-manager/instance_map.h b/server-tools/instance-manager/instance_map.h
deleted file mode 100644
index af2f1868195..00000000000
--- a/server-tools/instance-manager/instance_map.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 <my_sys.h>
-#include <m_string.h>
-#include <hash.h>
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-class Guardian;
-class Instance;
-class Named_value_arr;
-class Thread_registry;
-
-extern int load_all_groups(char ***groups, const char *filename);
-extern void free_groups(char **groups);
-
-extern int create_instance_in_file(const LEX_STRING *instance_name,
- const Named_value_arr *options);
-
-
-/**
- Instance_map - stores all existing instances
-*/
-
-class Instance_map
-{
-public:
- /**
- Instance_map iterator
- */
-
- class Iterator
- {
- private:
- uint current_instance;
- Instance_map *instance_map;
- public:
- Iterator(Instance_map *instance_map_arg) :
- current_instance(0), instance_map(instance_map_arg)
- {}
-
- void go_to_first();
- Instance *next();
- };
-
-public:
- Instance *find(const LEX_STRING *name);
-
- bool is_there_active_instance();
-
- void lock();
- void unlock();
-
- bool init();
- bool reset();
-
- int load();
-
- int process_one_option(const LEX_STRING *group, const char *option);
-
- int add_instance(Instance *instance);
-
- int remove_instance(Instance *instance);
-
- int create_instance(const LEX_STRING *instance_name,
- const Named_value_arr *options);
-
-public:
- Instance_map();
- ~Instance_map();
-
-private:
- bool complete_initialization();
-
-private:
- enum { START_HASH_SIZE = 16 };
- pthread_mutex_t LOCK_instance_map;
- HASH hash;
-
-private:
- friend class Iterator;
-};
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_MAP_H */
diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc
deleted file mode 100644
index 8b96d6f0f96..00000000000
--- a/server-tools/instance-manager/instance_options.cc
+++ /dev/null
@@ -1,753 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "instance_options.h"
-
-#include <my_global.h>
-#include <my_sys.h>
-#include <m_string.h>
-
-#include <signal.h>
-
-#include "buffer.h"
-#include "instance.h"
-#include "log.h"
-#include "options.h"
-#include "parse_output.h"
-#include "priv.h"
-
-
-/* Create "mysqld ..." command in the buffer */
-
-static inline bool create_mysqld_command(Buffer *buf,
- const LEX_STRING *mysqld_path,
- const LEX_STRING *option)
-{
- int position= 0;
-
- if (buf->get_size()) /* malloc succeeded */
- {
-#ifdef __WIN__
- buf->append(position++, "\"", 1);
-#endif
- buf->append(position, mysqld_path->str, mysqld_path->length);
- position+= mysqld_path->length;
-#ifdef __WIN__
- buf->append(position++, "\"", 1);
-#endif
- /* here the '\0' character is copied from the option string */
- buf->append(position, option->str, option->length + 1);
-
- return buf->is_error() ? TRUE : FALSE;
- }
- return TRUE;
-}
-
-static inline bool is_path_separator(char ch)
-{
-#if defined(__WIN__) || defined(__NETWARE__)
- /* On windows and netware more delimiters are possible */
- return ch == FN_LIBCHAR || ch == FN_DEVCHAR || ch == '/';
-#else
- return ch == FN_LIBCHAR; /* Unixes */
-#endif
-}
-
-
-static char *find_last_path_separator(char *path, uint length)
-{
- while (length)
- {
- if (is_path_separator(path[length]))
- return path + length;
- length--;
- }
- return NULL; /* No path separator found */
-}
-
-
-
-bool Instance_options::is_option_im_specific(const char *option_name)
-{
- static const char *IM_SPECIFIC_OPTIONS[] =
- {
- "nonguarded",
- "mysqld-path",
- "shutdown-delay",
- NULL
- };
-
- for (int i= 0; IM_SPECIFIC_OPTIONS[i]; ++i)
- {
- if (!strcmp(option_name, IM_SPECIFIC_OPTIONS[i]))
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-Instance_options::Instance_options()
- :mysqld_version(NULL), mysqld_socket(NULL), mysqld_datadir(NULL),
- mysqld_pid_file(NULL),
- nonguarded(NULL),
- mysqld_port(NULL),
- mysqld_port_val(0),
- shutdown_delay(NULL),
- shutdown_delay_val(0),
- filled_default_options(0)
-{
- mysqld_path.str= NULL;
- mysqld_path.length= 0;
-
- mysqld_real_path.str= NULL;
- mysqld_real_path.length= 0;
-
- memset(logs, 0, sizeof(logs));
-}
-
-
-/*
- Get compiled-in value of default_option
-
- SYNOPSIS
- get_default_option()
- result buffer to put found value
- result_len buffer size
- option_name the name of the option, prefixed with "--"
-
- DESCRIPTION
-
- Get compile-in value of requested option from server
-
- RETURN
- 0 - ok
- 1 - error occured
-*/
-
-
-int Instance_options::get_default_option(char *result, size_t result_len,
- const char *option_name)
-{
- int rc= 1;
- LEX_STRING verbose_option=
- { C_STRING_WITH_LEN(" --no-defaults --verbose --help") };
-
- /* reserve space for the path + option + final '\0' */
- Buffer cmd(mysqld_path.length + verbose_option.length + 1);
-
- if (create_mysqld_command(&cmd, &mysqld_path, &verbose_option))
- goto err;
-
- /* +2 eats first "--" from the option string (E.g. "--datadir") */
- rc= parse_output_and_get_value((char*) cmd.buffer,
- option_name + 2, strlen(option_name + 2),
- result, result_len, GET_VALUE);
-err:
- return rc;
-}
-
-
-/*
- Fill mysqld_version option (used at initialization stage)
-
- SYNOPSIS
- fill_instance_version()
-
- DESCRIPTION
-
- Get mysqld version string from "mysqld --version" output.
-
- RETURN
- FALSE - ok
- TRUE - error occured
-*/
-
-bool Instance_options::fill_instance_version()
-{
- char result[MAX_VERSION_LENGTH];
- LEX_STRING version_option=
- { C_STRING_WITH_LEN(" --no-defaults --version") };
- Buffer cmd(mysqld_path.length + version_option.length + 1);
-
- if (create_mysqld_command(&cmd, &mysqld_path, &version_option))
- {
- log_error("Failed to get version of '%s': out of memory.",
- (const char *) mysqld_path.str);
- return TRUE;
- }
-
- bzero(result, MAX_VERSION_LENGTH);
-
- if (parse_output_and_get_value((char*) cmd.buffer, STRING_WITH_LEN("Ver"),
- result, MAX_VERSION_LENGTH, GET_LINE))
- {
- log_error("Failed to get version of '%s': unexpected output.",
- (const char *) mysqld_path.str);
- return TRUE;
- }
-
- DBUG_ASSERT(*result != '\0');
-
- {
- char *start;
-
- /* trim leading whitespaces */
- start= result;
- while (my_isspace(default_charset_info, *start))
- ++start;
-
- mysqld_version= strdup_root(&alloc, start);
- }
-
- return FALSE;
-}
-
-
-/*
- Fill mysqld_real_path
-
- SYNOPSIS
- fill_mysqld_real_path()
-
- DESCRIPTION
-
- Get the real path to mysqld from "mysqld --help" output.
- Will print the realpath of mysqld between "Usage: " and "[OPTIONS]"
-
- This is needed if the mysqld_path variable is pointing at a
- script(for example libtool) or a symlink.
-
- RETURN
- FALSE - ok
- TRUE - error occured
-*/
-
-bool Instance_options::fill_mysqld_real_path()
-{
- char result[FN_REFLEN];
- LEX_STRING help_option=
- { C_STRING_WITH_LEN(" --no-defaults --help") };
- Buffer cmd(mysqld_path.length + help_option.length);
-
- if (create_mysqld_command(&cmd, &mysqld_path, &help_option))
- {
- log_error("Failed to get real path of '%s': out of memory.",
- (const char *) mysqld_path.str);
- return TRUE;
- }
-
- bzero(result, FN_REFLEN);
-
- if (parse_output_and_get_value((char*) cmd.buffer,
- STRING_WITH_LEN("Usage: "),
- result, FN_REFLEN,
- GET_LINE))
- {
- log_error("Failed to get real path of '%s': unexpected output.",
- (const char *) mysqld_path.str);
- return TRUE;
- }
-
- DBUG_ASSERT(*result != '\0');
-
- {
- char* options_str;
- /* chop the path of at [OPTIONS] */
- if ((options_str= strstr(result, "[OPTIONS]")))
- *options_str= '\0';
- mysqld_real_path.str= strdup_root(&alloc, result);
- mysqld_real_path.length= strlen(mysqld_real_path.str);
- }
-
- return FALSE;
-}
-
-
-/*
- Fill various log options
-
- SYNOPSIS
- fill_log_options()
-
- DESCRIPTION
-
- Compute paths to enabled log files. If the path is not specified in the
- instance explicitly (I.e. log=/home/user/mysql.log), we try to guess the
- file name and placement.
-
- RETURN
- FALSE - ok
- TRUE - error occured
-*/
-
-bool Instance_options::fill_log_options()
-{
- Buffer buff;
- enum { MAX_LOG_OPTION_LENGTH= 256 };
- char datadir[MAX_LOG_OPTION_LENGTH];
- char hostname[MAX_LOG_OPTION_LENGTH];
- uint hostname_length;
- struct log_files_st
- {
- const char *name;
- uint length;
- char **value;
- const char *default_suffix;
- } logs_st[]=
- {
- {"--log-error", 11, &(logs[IM_LOG_ERROR]), ".err"},
- {"--log", 5, &(logs[IM_LOG_GENERAL]), ".log"},
- {"--log-slow-queries", 18, &(logs[IM_LOG_SLOW]), "-slow.log"},
- {NULL, 0, NULL, NULL}
- };
- struct log_files_st *log_files;
-
- /* compute hostname and datadir for the instance */
- if (mysqld_datadir == NULL)
- {
- if (get_default_option(datadir, MAX_LOG_OPTION_LENGTH, "--datadir"))
- return TRUE;
- }
- else
- {
- /* below is safe, as --datadir always has a value */
- strmake(datadir, mysqld_datadir, MAX_LOG_OPTION_LENGTH - 1);
- }
-
- if (gethostname(hostname,sizeof(hostname)-1) < 0)
- strmov(hostname, "mysql");
-
- hostname[MAX_LOG_OPTION_LENGTH - 1]= 0; /* Safety */
- hostname_length= strlen(hostname);
-
-
- for (log_files= logs_st; log_files->name; log_files++)
- {
- for (int i=0; (argv[i] != 0); i++)
- {
- if (!strncmp(argv[i], log_files->name, log_files->length))
- {
- /*
- This is really log_files->name option if and only if it is followed
- by '=', '\0' or space character. This way we can distinguish such
- options as '--log' and '--log-bin'. This is checked in the following
- two statements.
- */
- if (argv[i][log_files->length] == '\0' ||
- my_isspace(default_charset_info, argv[i][log_files->length]))
- {
- char full_name[MAX_LOG_OPTION_LENGTH];
-
- fn_format(full_name, hostname, datadir, "",
- MY_UNPACK_FILENAME | MY_SAFE_PATH);
-
-
- if ((MAX_LOG_OPTION_LENGTH - strlen(full_name)) <=
- strlen(log_files->default_suffix))
- return TRUE;
-
- strmov(full_name + strlen(full_name), log_files->default_suffix);
-
- /*
- If there were specified two identical logfiles options,
- we would loose some memory in MEM_ROOT here. However
- this situation is not typical.
- */
- *(log_files->value)= strdup_root(&alloc, full_name);
- }
-
- if (argv[i][log_files->length] == '=')
- {
- char full_name[MAX_LOG_OPTION_LENGTH];
-
- fn_format(full_name, argv[i] +log_files->length + 1,
- datadir, "", MY_UNPACK_FILENAME | MY_SAFE_PATH);
-
- if (!(*(log_files->value)= strdup_root(&alloc, full_name)))
- return TRUE;
- }
- }
- }
- }
-
- return FALSE;
-}
-
-
-/*
- Get the full pid file name with path
-
- SYNOPSIS
- get_pid_filaname()
- result buffer to sotre the pidfile value
-
- IMPLEMENTATION
- Get the data directory, then get the pid filename
- (which is always set for an instance), then load the
- full path with my_load_path(). It takes into account
- whether it is already an absolute path or it should be
- prefixed with the datadir and so on.
-
- RETURN
- 0 - ok
- 1 - error occured
-*/
-
-int Instance_options::get_pid_filename(char *result)
-{
- char datadir[MAX_PATH_LEN];
-
- if (mysqld_datadir == NULL)
- {
- /* we might get an error here if we have wrong path to the mysqld binary */
- if (get_default_option(datadir, sizeof(datadir), "--datadir"))
- return 1;
- }
- else
- strxnmov(datadir, MAX_PATH_LEN - 1, mysqld_datadir, "/", NullS);
-
- /* get the full path to the pidfile */
- my_load_path(result, mysqld_pid_file, datadir);
- return 0;
-}
-
-
-int Instance_options::unlink_pidfile()
-{
- return unlink(pid_file_with_path);
-}
-
-
-pid_t Instance_options::load_pid()
-{
- FILE *pid_file_stream;
-
- /* get the pid */
- if ((pid_file_stream= my_fopen(pid_file_with_path,
- O_RDONLY | O_BINARY, MYF(0))) != NULL)
- {
- pid_t pid;
-
- if (fscanf(pid_file_stream, "%i", &pid) != 1)
- pid= -1;
- my_fclose(pid_file_stream, MYF(0));
- return pid;
- }
- return 0;
-}
-
-
-bool Instance_options::complete_initialization()
-{
- int arg_idx;
- const char *tmp;
- char *end;
- char bin_name_firstchar;
-
- if (!mysqld_path.str)
- {
- /*
- Need to copy the path to allocated memory, as convert_dirname() might
- need to change it
- */
- mysqld_path.str= strdup_root(&alloc, Options::Main::default_mysqld_path);
- if (!mysqld_path.str)
- return TRUE;
- }
-
- mysqld_path.length= strlen(mysqld_path.str);
-
- /*
- If we found path with no slashes (end == NULL), we should not call
- convert_dirname() at all. As we have got relative path to the binary.
- That is, user supposes that mysqld resides in the same dir as
- mysqlmanager.
- */
- if ((end= find_last_path_separator(mysqld_path.str, mysqld_path.length)))
- {
- bin_name_firstchar= end[1];
-
- /*
- Below we will conver the path to mysqld in the case, it was given
- in a format of another OS (e.g. uses '/' instead of '\' etc).
- Here we strip the path to get rid of the binary name ("mysqld"),
- we do it by removing first letter of the binary name (e.g. 'm'
- in "mysqld"). Later we put it back.
- */
- end[1]= 0;
-
- /* convert dirname to the format of current OS */
- convert_dirname((char*)mysqld_path.str, mysqld_path.str, NullS);
-
- /* put back the first character of the binary name*/
- end[1]= bin_name_firstchar;
- }
-
- if (mysqld_port)
- mysqld_port_val= atoi(mysqld_port);
-
- if (shutdown_delay)
- shutdown_delay_val= atoi(shutdown_delay);
-
- if (!(tmp= strdup_root(&alloc, "--no-defaults")))
- return TRUE;
-
- if (!mysqld_pid_file)
- {
- char pidfilename[MAX_PATH_LEN];
- char hostname[MAX_PATH_LEN];
-
- /*
- If we created only one istance [mysqld], because no config. files were
- found, we would like to model mysqld pid file values.
- */
-
- if (!gethostname(hostname, sizeof(hostname) - 1))
- {
- if (Instance::is_mysqld_compatible_name(&instance_name))
- strxnmov(pidfilename, MAX_PATH_LEN - 1, hostname, ".pid", NullS);
- else
- strxnmov(pidfilename, MAX_PATH_LEN - 1, instance_name.str, "-",
- hostname, ".pid", NullS);
- }
- else
- {
- if (Instance::is_mysqld_compatible_name(&instance_name))
- strxnmov(pidfilename, MAX_PATH_LEN - 1, "mysql", ".pid", NullS);
- else
- strxnmov(pidfilename, MAX_PATH_LEN - 1, instance_name.str, ".pid",
- NullS);
- }
-
- Named_value option((char *) "pid-file", pidfilename);
-
- set_option(&option);
- }
-
- if (get_pid_filename(pid_file_with_path))
- return TRUE;
-
- /* we need to reserve space for the final zero + possible default options */
- if (!(argv= (char**)
- alloc_root(&alloc, (get_num_options() + 1
- + MAX_NUMBER_OF_DEFAULT_OPTIONS) * sizeof(char*))))
- return TRUE;
- filled_default_options= 0;
-
- /* the path must be first in the argv */
- if (add_to_argv(mysqld_path.str))
- return TRUE;
-
- if (add_to_argv(tmp))
- return TRUE;
-
- arg_idx= filled_default_options;
- for (int opt_idx= 0; opt_idx < get_num_options(); ++opt_idx)
- {
- char option_str[MAX_OPTION_STR_LEN];
- Named_value option= get_option(opt_idx);
-
- if (is_option_im_specific(option.get_name()))
- continue;
-
- char *ptr= strxnmov(option_str, MAX_OPTION_LEN + 3, "--", option.get_name(),
- NullS);
-
- if (option.get_value()[0])
- strxnmov(ptr, MAX_OPTION_LEN + 2, "=", option.get_value(), NullS);
-
- argv[arg_idx++]= strdup_root(&alloc, option_str);
- }
-
- argv[arg_idx]= 0;
-
- if (fill_log_options() || fill_mysqld_real_path() || fill_instance_version())
- return TRUE;
-
- return FALSE;
-}
-
-
-bool Instance_options::set_option(Named_value *option)
-{
- bool err_status;
- int idx= find_option(option->get_name());
- char *option_name_str;
- char *option_value_str;
-
- if (!(option_name_str= Named_value::alloc_str(option->get_name())))
- return TRUE;
-
- if (!(option_value_str= Named_value::alloc_str(option->get_value())))
- {
- Named_value::free_str(&option_name_str);
- return TRUE;
- }
-
- Named_value option_copy(option_name_str, option_value_str);
-
- if (idx < 0)
- err_status= options.add_element(&option_copy);
- else
- err_status= options.replace_element(idx, &option_copy);
-
- if (!err_status)
- update_var(option_copy.get_name(), option_copy.get_value());
- else
- option_copy.free();
-
- return err_status;
-}
-
-
-void Instance_options::unset_option(const char *option_name)
-{
- int idx= find_option(option_name);
-
- if (idx < 0)
- return; /* the option has not been set. */
-
- options.remove_element(idx);
-
- update_var(option_name, NULL);
-}
-
-
-void Instance_options::update_var(const char *option_name,
- const char *option_value)
-{
- struct options_st
- {
- const char *name;
- uint name_len;
- const char **var;
- } options_def[]=
- {
- {"socket", 6, &mysqld_socket},
- {"port", 4, &mysqld_port},
- {"datadir", 7, &mysqld_datadir},
- {"pid-file", 8, &mysqld_pid_file},
- {"nonguarded", 10, &nonguarded},
- {"mysqld-path", 11, (const char **) &mysqld_path.str},
- {"shutdown-delay", 14, &shutdown_delay},
- {NULL, 0, NULL}
- };
-
- for (options_st *opt= options_def; opt->name; ++opt)
- {
- if (!strncmp(opt->name, option_name, opt->name_len))
- {
- *(opt->var)= option_value;
- break;
- }
- }
-}
-
-
-int Instance_options::find_option(const char *option_name)
-{
- for (int i= 0; i < get_num_options(); i++)
- {
- if (!strcmp(get_option(i).get_name(), option_name))
- return i;
- }
-
- return -1;
-}
-
-
-int Instance_options::add_to_argv(const char* option)
-{
- DBUG_ASSERT(filled_default_options < MAX_NUMBER_OF_DEFAULT_OPTIONS);
-
- if (option)
- argv[filled_default_options++]= (char*) option;
- return 0;
-}
-
-
-/* function for debug purposes */
-void Instance_options::print_argv()
-{
- int i;
-
- printf("printing out an instance %s argv:\n",
- (const char *) instance_name.str);
-
- for (i=0; argv[i] != NULL; i++)
- printf("argv: %s\n", argv[i]);
-}
-
-
-/*
- We execute this function to initialize some options.
-
- RETURN
- FALSE - ok
- TRUE - memory allocation error
-*/
-
-bool Instance_options::init(const LEX_STRING *instance_name_arg)
-{
- instance_name.length= instance_name_arg->length;
-
- init_alloc_root(&alloc, MEM_ROOT_BLOCK_SIZE, 0);
-
- if (options.init())
- return TRUE;
-
- if (!(instance_name.str= strmake_root(&alloc, instance_name_arg->str,
- instance_name_arg->length)))
- return TRUE;
-
- return FALSE;
-}
-
-
-Instance_options::~Instance_options()
-{
- free_root(&alloc, MYF(0));
-}
-
-
-uint Instance_options::get_shutdown_delay() const
-{
- static const uint DEFAULT_SHUTDOWN_DELAY= 35;
-
- /*
- NOTE: it is important to check shutdown_delay here, but use
- shutdown_delay_val. The idea is that if the option is unset,
- shutdown_delay will be NULL, but shutdown_delay_val will not be reset.
- */
-
- return shutdown_delay ? shutdown_delay_val : DEFAULT_SHUTDOWN_DELAY;
-}
-
-int Instance_options::get_mysqld_port() const
-{
- /*
- NOTE: it is important to check mysqld_port here, but use mysqld_port_val.
- The idea is that if the option is unset, mysqld_port will be NULL, but
- mysqld_port_val will not be reset.
- */
-
- return mysqld_port ? mysqld_port_val : 0;
-}
-
diff --git a/server-tools/instance-manager/instance_options.h b/server-tools/instance-manager/instance_options.h
deleted file mode 100644
index b0503815036..00000000000
--- a/server-tools/instance-manager/instance_options.h
+++ /dev/null
@@ -1,126 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 <my_sys.h>
-
-#include "parse.h"
-#include "portability.h" /* for pid_t on Win32 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-
-/*
- This class contains options of an instance and methods to operate them.
-
- We do not provide this class with the means of synchronization as it is
- supposed that options for instances are all loaded at once during the
- instance_map initilization and we do not change them later. This way we
- don't have to synchronize between threads.
-*/
-
-class Instance_options
-{
-public:
- /* The operation is used to check if the option is IM-specific or not. */
- static bool is_option_im_specific(const char *option_name);
-
-public:
- Instance_options();
- ~Instance_options();
-
- bool complete_initialization();
-
- bool set_option(Named_value *option);
- void unset_option(const char *option_name);
-
- inline int get_num_options() const;
- inline Named_value get_option(int idx) const;
-
-public:
- bool init(const LEX_STRING *instance_name_arg);
- pid_t load_pid();
- int get_pid_filename(char *result);
- int unlink_pidfile();
- void print_argv();
-
- uint get_shutdown_delay() const;
- int get_mysqld_port() const;
-
-public:
- /*
- We need this value to be greater or equal then FN_REFLEN found in
- my_global.h to use my_load_path()
- */
- enum { MAX_PATH_LEN= 512 };
- enum { MAX_NUMBER_OF_DEFAULT_OPTIONS= 2 };
- char pid_file_with_path[MAX_PATH_LEN];
- char **argv;
- /*
- Here we cache the version string, obtained from mysqld --version.
- In the case when mysqld binary is not found we get NULL here.
- */
- const char *mysqld_version;
- /* We need the some options, so we store them as a separate pointers */
- const char *mysqld_socket;
- const char *mysqld_datadir;
- const char *mysqld_pid_file;
- LEX_STRING instance_name;
- LEX_STRING mysqld_path;
- LEX_STRING mysqld_real_path;
- const char *nonguarded;
- /* log enums are defined in parse.h */
- char *logs[3];
-
-private:
- bool fill_log_options();
- bool fill_instance_version();
- bool fill_mysqld_real_path();
- int add_to_argv(const char *option);
- int get_default_option(char *result, size_t result_len,
- const char *option_name);
-
- void update_var(const char *option_name, const char *option_value);
- int find_option(const char *option_name);
-
-private:
- const char *mysqld_port;
- uint mysqld_port_val;
- const char *shutdown_delay;
- uint shutdown_delay_val;
-
- uint filled_default_options;
- MEM_ROOT alloc;
-
- Named_value_arr options;
-};
-
-
-inline int Instance_options::get_num_options() const
-{
- return options.get_size();
-}
-
-
-inline Named_value Instance_options::get_option(int idx) const
-{
- return options.get_element(idx);
-}
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_INSTANCE_OPTIONS_H */
diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc
deleted file mode 100644
index 4d8a33e7db1..00000000000
--- a/server-tools/instance-manager/listener.cc
+++ /dev/null
@@ -1,337 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "listener.h"
-
-#include <my_global.h>
-#include <mysql.h>
-#include <violite.h>
-
-#include <sys/stat.h>
-#ifndef __WIN__
-#include <sys/un.h>
-#endif
-
-#include "log.h"
-#include "mysql_connection.h"
-#include "options.h"
-#include "portability.h"
-#include "priv.h"
-#include "thread_registry.h"
-
-
-static void set_non_blocking(int socket)
-{
-#ifndef __WIN__
- int flags= fcntl(socket, F_GETFL, 0);
- fcntl(socket, F_SETFL, flags | O_NONBLOCK);
-#else
- u_long arg= 1;
- ioctlsocket(socket, FIONBIO, &arg);
-#endif
-}
-
-
-static void set_no_inherit(int socket)
-{
-#ifndef __WIN__
- int flags= fcntl(socket, F_GETFD, 0);
- fcntl(socket, F_SETFD, flags | FD_CLOEXEC);
-#endif
-}
-
-const int Listener::LISTEN_BACK_LOG_SIZE= 5; /* standard backlog size */
-
-Listener::Listener(Thread_registry *thread_registry_arg,
- User_map *user_map_arg)
- :thread_registry(thread_registry_arg),
- user_map(user_map_arg),
- total_connection_count(0),
- num_sockets(0)
-{
-}
-
-
-/*
- Listener::run() - listen all supported sockets and spawn a thread
- to handle incoming connection.
- Using 'die' in case of syscall failure is OK now - we don't hold any
- resources and 'die' kills the signal thread automatically. To be rewritten
- one day.
- See also comments in mysqlmanager.cc to picture general Instance Manager
- architecture.
-*/
-
-void Listener::run()
-{
- int i, n= 0;
-
-#ifndef __WIN__
- struct sockaddr_un unix_socket_address;
-#endif
-
- log_info("Listener: started.");
-
- thread_registry->register_thread(&thread_info);
-
- FD_ZERO(&read_fds);
-
- /* I. prepare 'listen' sockets */
- if (create_tcp_socket())
- goto err;
-
-#ifndef __WIN__
- if (create_unix_socket(unix_socket_address))
- goto err;
-#endif
-
- /* II. Listen sockets and spawn childs */
- for (i= 0; i < num_sockets; i++)
- n= max(n, sockets[i]);
- n++;
-
- timeval tv;
- while (!thread_registry->is_shutdown())
- {
- fd_set read_fds_arg= read_fds;
- /*
- We should reintialize timer as on linux it is modified
- to reflect amount of time not slept.
- */
- tv.tv_sec= 0;
- tv.tv_usec= 100000;
-
- /*
- When using valgrind 2.0 this syscall doesn't get kicked off by a
- signal during shutdown. This results in failing assert
- (Thread_registry::~Thread_registry). Valgrind 2.2 works fine.
- */
- int rc= select(n, &read_fds_arg, 0, 0, &tv);
-
- if (rc == 0 || rc == -1)
- {
- if (rc == -1 && errno != EINTR)
- log_error("Listener: select() failed: %s.",
- (const char *) strerror(errno));
- continue;
- }
-
-
- for (int socket_index= 0; socket_index < num_sockets; socket_index++)
- {
- /* Assuming that rc > 0 as we asked to wait forever */
- if (FD_ISSET(sockets[socket_index], &read_fds_arg))
- {
- int client_fd= accept(sockets[socket_index], 0, 0);
- /* accept may return -1 (failure or spurious wakeup) */
- if (client_fd >= 0) // connection established
- {
- set_no_inherit(client_fd);
-
- struct st_vio *vio=
- vio_new(client_fd,
- socket_index == 0 ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP,
- socket_index == 0 ? 1 : 0);
-
- if (vio != NULL)
- handle_new_mysql_connection(vio);
- else
- {
- shutdown(client_fd, SHUT_RDWR);
- closesocket(client_fd);
- }
- }
- }
- }
- }
-
- /* III. Release all resources and exit */
-
- log_info("Listener: shutdown requested, exiting...");
-
- for (i= 0; i < num_sockets; i++)
- closesocket(sockets[i]);
-
-#ifndef __WIN__
- unlink(unix_socket_address.sun_path);
-#endif
-
- thread_registry->unregister_thread(&thread_info);
-
- log_info("Listener: finished.");
- return;
-
-err:
- log_error("Listener: failed to initialize. Initiate shutdown...");
-
- // we have to close the ip sockets in case of error
- for (i= 0; i < num_sockets; i++)
- closesocket(sockets[i]);
-
- thread_registry->set_error_status();
- thread_registry->unregister_thread(&thread_info);
- thread_registry->request_shutdown();
- return;
-}
-
-int Listener::create_tcp_socket()
-{
- /* value to be set by setsockopt */
- int arg= 1;
-
- int ip_socket= socket(AF_INET, SOCK_STREAM, 0);
- if (ip_socket == INVALID_SOCKET)
- {
- log_error("Listener: socket(AF_INET) failed: %s.",
- (const char *) strerror(errno));
- return -1;
- }
-
- struct sockaddr_in ip_socket_address;
- bzero(&ip_socket_address, sizeof(ip_socket_address));
-
- ulong im_bind_addr;
- if (Options::Main::bind_address != 0)
- {
- im_bind_addr= (ulong) inet_addr(Options::Main::bind_address);
-
- if (im_bind_addr == (ulong) INADDR_NONE)
- im_bind_addr= htonl(INADDR_ANY);
- }
- else
- im_bind_addr= htonl(INADDR_ANY);
- uint im_port= Options::Main::port_number;
-
- ip_socket_address.sin_family= AF_INET;
- ip_socket_address.sin_addr.s_addr= im_bind_addr;
-
-
- ip_socket_address.sin_port= (unsigned short)
- htons((unsigned short) im_port);
-
- setsockopt(ip_socket, SOL_SOCKET, SO_REUSEADDR, (char*) &arg, sizeof(arg));
- if (bind(ip_socket, (struct sockaddr *) &ip_socket_address,
- sizeof(ip_socket_address)))
- {
- log_error("Listener: bind(ip socket) failed: %s.",
- (const char *) strerror(errno));
- closesocket(ip_socket);
- return -1;
- }
-
- if (listen(ip_socket, LISTEN_BACK_LOG_SIZE))
- {
- log_error("Listener: listen(ip socket) failed: %s.",
- (const char *) strerror(errno));
- closesocket(ip_socket);
- return -1;
- }
-
- /* set the socket nonblocking */
- set_non_blocking(ip_socket);
-
- /* make sure that instances won't be listening our sockets */
- set_no_inherit(ip_socket);
-
- FD_SET(ip_socket, &read_fds);
- sockets[num_sockets++]= ip_socket;
- log_info("Listener: accepting connections on ip socket (port: %d)...",
- (int) im_port);
- return 0;
-}
-
-#ifndef __WIN__
-int Listener::
-create_unix_socket(struct sockaddr_un &unix_socket_address)
-{
- int unix_socket= socket(AF_UNIX, SOCK_STREAM, 0);
- if (unix_socket == INVALID_SOCKET)
- {
- log_error("Listener: socket(AF_UNIX) failed: %s.",
- (const char *) strerror(errno));
- return -1;
- }
-
- bzero(&unix_socket_address, sizeof(unix_socket_address));
-
- unix_socket_address.sun_family= AF_UNIX;
- strmake(unix_socket_address.sun_path, Options::Main::socket_file_name,
- sizeof(unix_socket_address.sun_path));
- unlink(unix_socket_address.sun_path); // in case we have stale socket file
-
- /*
- POSIX specifies default permissions for a pathname created by bind
- to be 0777. We need everybody to have access to the socket.
- */
- mode_t old_mask= umask(0);
- if (bind(unix_socket, (struct sockaddr *) &unix_socket_address,
- sizeof(unix_socket_address)))
- {
- log_error("Listener: bind(unix socket) failed for '%s': %s.",
- (const char *) unix_socket_address.sun_path,
- (const char *) strerror(errno));
- close(unix_socket);
- return -1;
- }
-
- umask(old_mask);
-
- if (listen(unix_socket, LISTEN_BACK_LOG_SIZE))
- {
- log_error("Listener: listen(unix socket) failed: %s.",
- (const char *) strerror(errno));
- close(unix_socket);
- return -1;
- }
-
- /* set the socket nonblocking */
- set_non_blocking(unix_socket);
-
- /* make sure that instances won't be listening our sockets */
- set_no_inherit(unix_socket);
-
- log_info("Listener: accepting connections on unix socket '%s'...",
- (const char *) unix_socket_address.sun_path);
- sockets[num_sockets++]= unix_socket;
- FD_SET(unix_socket, &read_fds);
- return 0;
-}
-#endif
-
-
-/*
- Create new mysql connection. Created thread is responsible for deletion of
- the Mysql_connection and Vio instances passed to it.
- SYNOPSIS
- handle_new_mysql_connection()
-*/
-
-void Listener::handle_new_mysql_connection(struct st_vio *vio)
-{
- Mysql_connection *mysql_connection=
- new Mysql_connection(thread_registry, user_map,
- vio, ++total_connection_count);
- if (mysql_connection == NULL || mysql_connection->start(Thread::DETACHED))
- {
- log_error("Listener: can not start connection handler.");
- delete mysql_connection;
- vio_delete(vio);
- }
- /* The connection will delete itself when the thread is finished */
-}
diff --git a/server-tools/instance-manager/listener.h b/server-tools/instance-manager/listener.h
deleted file mode 100644
index 964fb361fb5..00000000000
--- a/server-tools/instance-manager/listener.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_LISTENER_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_LISTENER_H
-
-#include "thread_registry.h"
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-class Thread_registry;
-class User_map;
-
-/**
- Listener - a thread listening on sockets and spawning
- connection threads.
-*/
-
-class Listener: public Thread
-{
-public:
- Listener(Thread_registry *thread_registry_arg, User_map *user_map_arg);
-
-protected:
- virtual void run();
-
-private:
- static const int LISTEN_BACK_LOG_SIZE;
-
-private:
- Thread_info thread_info;
- Thread_registry *thread_registry;
- User_map *user_map;
-
- ulong total_connection_count;
-
- int sockets[2];
- int num_sockets;
- fd_set read_fds;
-
-private:
- void handle_new_mysql_connection(struct st_vio *vio);
- int create_tcp_socket();
- int create_unix_socket(struct sockaddr_un &unix_socket_address);
-};
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_LISTENER_H
diff --git a/server-tools/instance-manager/log.cc b/server-tools/instance-manager/log.cc
deleted file mode 100644
index 9f276523e49..00000000000
--- a/server-tools/instance-manager/log.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#include "log.h"
-
-#include <my_global.h>
-#include <m_string.h>
-#include <my_sys.h>
-
-#include <stdarg.h>
-
-#include "portability.h" /* for vsnprintf() on Windows. */
-
-/*
- TODO:
- - add flexible header support
- - rewrite all fprintf with fwrite
- - think about using 'write' instead of fwrite/fprintf on POSIX systems
-*/
-
-/*
- Format log entry and write it to the given stream.
- SYNOPSIS
- log()
-*/
-
-static void log(FILE *file,const char *level_tag, const char *format,
- va_list args)
-{
- /*
- log() should be thread-safe; it implies that we either call fprintf()
- once per log(), or use flockfile()/funlockfile(). But flockfile() is
- POSIX, not ANSI C, so we try to vsnprintf the whole message to the
- stack, and if stack buffer is not enough, to malloced string. When
- message is formatted, it is fprintf()'ed to the file.
- */
-
- /* Format time like MYSQL_LOG does. */
- time_t now= time(0);
- struct tm bd_time; // broken-down time
- localtime_r(&now, &bd_time);
-
- char buff_date[128];
- sprintf(buff_date, "[%d/%lu] [%02d/%02d/%02d %02d:%02d:%02d] [%s] ",
- (int) getpid(),
- (unsigned long) pthread_self(),
- (int) bd_time.tm_year % 100,
- (int) bd_time.tm_mon + 1,
- (int) bd_time.tm_mday,
- (int) bd_time.tm_hour,
- (int) bd_time.tm_min,
- (int) bd_time.tm_sec,
- (const char *) level_tag);
- /* Format the message */
- char buff_stack[256];
-
- int n= vsnprintf(buff_stack, sizeof(buff_stack), format, args);
- /*
- return value of vsnprintf can vary, according to various standards;
- try to check all cases.
- */
- char *buff_msg= buff_stack;
- if (n < 0 || n == sizeof(buff_stack))
- {
- int size= sizeof(buff_stack) * 2;
- buff_msg= (char*) my_malloc(size, MYF(0));
- while (TRUE)
- {
- if (buff_msg == 0)
- {
- strmake(buff_stack, "log(): message is too big, my_malloc() failed",
- sizeof(buff_stack) - 1);
- buff_msg= buff_stack;
- break;
- }
- n = vsnprintf(buff_msg, size, format, args);
- if (n >= 0 && n < size)
- break;
- size*= 2;
- /* realloc() does unnecessary memcpy */
- my_free(buff_msg, 0);
- buff_msg= (char*) my_malloc(size, MYF(0));
- }
- }
- else if ((size_t) n > sizeof(buff_stack))
- {
- buff_msg= (char*) my_malloc(n + 1, MYF(0));
-#ifdef DBUG
- DBUG_ASSERT(n == vsnprintf(buff_msg, n + 1, format, args));
-#else
- vsnprintf(buff_msg, n + 1, format, args);
-#endif
- }
- fprintf(file, "%s%s\n", buff_date, buff_msg);
- if (buff_msg != buff_stack)
- my_free(buff_msg, 0);
-
- /* don't fflush() the file: buffering strategy is set in log_init() */
-}
-
-/**************************************************************************
- Logging: implementation of public interface.
-**************************************************************************/
-
-/*
- The function initializes logging sub-system.
-
- SYNOPSIS
- log_init()
-*/
-
-void log_init()
-{
- /*
- stderr is unbuffered by default; there is no good of line buffering,
- as all logging is performed linewise - so remove buffering from stdout
- also
- */
- setbuf(stdout, 0);
-}
-
-
-/*
- The function is intended to log error messages. It precedes a message
- with date, time and [ERROR] tag and print it to the stderr and stdout.
-
- We want to print it on stdout to be able to know in which context we got the
- error
-
- SYNOPSIS
- log_error()
- format [IN] format string
- ... [IN] arguments to format
-*/
-
-void log_error(const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- log(stdout, "ERROR", format, args);
- fflush(stdout);
- log(stderr, "ERROR", format, args);
- fflush(stderr);
- va_end(args);
-}
-
-
-/*
- The function is intended to log information messages. It precedes
- a message with date, time and [INFO] tag and print it to the stdout.
-
- SYNOPSIS
- log_error()
- format [IN] format string
- ... [IN] arguments to format
-*/
-
-void log_info(const char *format, ...)
-{
- va_list args;
- va_start(args, format);
- log(stdout, "INFO", format, args);
- va_end(args);
-}
-
-/*
- The function prints information to the error log and eixt(1).
-
- SYNOPSIS
- die()
- format [IN] format string
- ... [IN] arguments to format
-*/
-
-void die(const char *format, ...)
-{
- va_list args;
- fprintf(stderr,"%s: ", my_progname);
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
- fprintf(stderr, "\n");
- exit(1);
-}
diff --git a/server-tools/instance-manager/log.h b/server-tools/instance-manager/log.h
deleted file mode 100644
index e6c3b55c54c..00000000000
--- a/server-tools/instance-manager/log.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
-
-/*
- Logging facilities.
-
- Two logging streams are supported: error log and info log.
- Additionally libdbug may be used for debug information output.
-
- ANSI C buffered I/O is used to perform logging.
-
- Logging is performed via stdout/stder, so one can reopen them to point to
- ordinary files. To initialize logging environment log_init() must be called.
-
- Rationale:
- - no MYSQL_LOG as it has BIN mode, and not easy to fetch from sql_class.h
- - no constructors/desctructors to make logging available all the time
-*/
-
-
-void log_init();
-
-
-void log_info(const char *format, ...)
-#ifdef __GNUC__
- __attribute__ ((format(printf, 1, 2)))
-#endif
- ;
-
-
-void log_error(const char *format, ...)
-#ifdef __GNUC__
- __attribute__ ((format (printf, 1, 2)))
-#endif
- ;
-
-
-void die(const char *format, ...)
-#ifdef __GNUC__
- __attribute__ ((format (printf, 1, 2)))
-#endif
- ;
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_LOG_H
diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc
deleted file mode 100644
index 792461e41a9..00000000000
--- a/server-tools/instance-manager/manager.cc
+++ /dev/null
@@ -1,526 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#include "manager.h"
-
-#include <my_global.h>
-#include <m_string.h>
-#include <my_sys.h>
-#include <thr_alarm.h>
-
-#include <signal.h>
-#ifndef __WIN__
-#include <sys/wait.h>
-#endif
-
-#include "exit_codes.h"
-#include "guardian.h"
-#include "instance_map.h"
-#include "listener.h"
-#include "mysql_manager_error.h"
-#include "mysqld_error.h"
-#include "log.h"
-#include "options.h"
-#include "priv.h"
-#include "thread_registry.h"
-#include "user_map.h"
-
-
-/**********************************************************************
- {{{ Platform-specific implementation.
-**********************************************************************/
-
-#ifndef __WIN__
-void set_signals(sigset_t *mask)
-{
- /* block signals */
- sigemptyset(mask);
- sigaddset(mask, SIGINT);
- sigaddset(mask, SIGTERM);
- sigaddset(mask, SIGPIPE);
- sigaddset(mask, SIGHUP);
- signal(SIGPIPE, SIG_IGN);
-
- /*
- We want this signal to be blocked in all theads but the signal
- one. It is needed for the thr_alarm subsystem to work.
- */
- sigaddset(mask,THR_SERVER_ALARM);
-
- /* all new threads will inherite this signal mask */
- pthread_sigmask(SIG_BLOCK, mask, NULL);
-
- /*
- In our case the signal thread also implements functions of alarm thread.
- Here we init alarm thread functionality. We suppose that we won't have
- more then 10 alarms at the same time.
- */
- init_thr_alarm(10);
-}
-#else
-
-bool have_signal;
-
-void onsignal(int signo)
-{
- have_signal= TRUE;
-}
-
-void set_signals(sigset_t *set)
-{
- signal(SIGINT, onsignal);
- signal(SIGTERM, onsignal);
- have_signal= FALSE;
-}
-
-int my_sigwait(const sigset_t *set, int *sig)
-{
- while (!have_signal)
- {
- Sleep(100);
- }
- return 0;
-}
-
-#endif
-
-/**********************************************************************
- }}}
-**********************************************************************/
-
-
-/**********************************************************************
- {{{ Implementation of checking the actual thread model.
-***********************************************************************/
-
-namespace { /* no-indent */
-
-class ThreadModelChecker: public Thread
-{
-public:
- ThreadModelChecker()
- :main_pid(getpid())
- { }
-
-public:
- inline bool is_linux_threads() const
- {
- return linux_threads;
- }
-
-protected:
- virtual void run()
- {
- linux_threads= main_pid != getpid();
- }
-
-private:
- pid_t main_pid;
- bool linux_threads;
-};
-
-bool check_if_linux_threads(bool *linux_threads)
-{
- ThreadModelChecker checker;
-
- if (checker.start() || checker.join())
- return TRUE;
-
- *linux_threads= checker.is_linux_threads();
-
- return FALSE;
-}
-
-}
-
-/**********************************************************************
- }}}
-***********************************************************************/
-
-
-/**********************************************************************
- Manager implementation
-***********************************************************************/
-
-Guardian *Manager::p_guardian;
-Instance_map *Manager::p_instance_map;
-Thread_registry *Manager::p_thread_registry;
-User_map *Manager::p_user_map;
-
-#ifndef __WIN__
-bool Manager::linux_threads;
-#endif // __WIN__
-
-
-/**
- Request shutdown of guardian and threads registered in Thread_registry.
-
- SYNOPSIS
- stop_all_threads()
-*/
-
-void Manager::stop_all_threads()
-{
- /*
- Let Guardian thread know that it should break it's processing cycle,
- once it wakes up.
- */
- p_guardian->request_shutdown();
-
- /* Stop all threads. */
- p_thread_registry->deliver_shutdown();
-
- /* Set error status in the thread registry. */
- p_thread_registry->set_error_status();
-}
-
-
-/**
- Initialize user map and load password file.
-
- SYNOPSIS
- init_user_map()
-
- RETURN
- FALSE on success
- TRUE on failure
-*/
-
-bool Manager::init_user_map(User_map *user_map)
-{
- int err_code;
- const char *err_msg;
-
- if (user_map->init())
- {
- log_error("Manager: can not initialize user list: out of memory.");
- return TRUE;
- }
-
- err_code= user_map->load(Options::Main::password_file_name, &err_msg);
-
- if (!err_code)
- return FALSE;
-
- if (err_code == ERR_PASSWORD_FILE_DOES_NOT_EXIST &&
- Options::Main::mysqld_safe_compatible)
- {
- /*
- The password file does not exist, but we are running in
- mysqld_safe-compatible mode. Continue, but complain in log.
- */
-
- log_info("Warning: password file does not exist, "
- "nobody will be able to connect to Instance Manager.");
-
- return FALSE;
- }
-
- log_error("Manager: %s.", (const char *) err_msg);
-
- return TRUE;
-}
-
-
-/**
- Main manager function.
-
- SYNOPSIS
- main()
-
- DESCRIPTION
- This is an entry point to the main instance manager process:
- start listener thread, write pid file and enter into signal handling.
- See also comments in mysqlmanager.cc to picture general Instance Manager
- architecture.
-
- RETURNS
- main() returns exit status (exit code).
-*/
-
-int Manager::main()
-{
- bool shutdown_complete= FALSE;
- pid_t manager_pid= getpid();
-
- log_info("Manager: initializing...");
-
-#ifndef __WIN__
- if (check_if_linux_threads(&linux_threads))
- {
- log_error("Manager: can not determine thread model.");
- return 1;
- }
-
- log_info("Manager: detected threads model: %s.",
- (const char *) (linux_threads ? "LINUX threads" : "POSIX threads"));
-#endif // __WIN__
-
- /*
- All objects created in the Manager object live as long as thread_registry
- lives, and thread_registry is alive until there are working threads.
-
- There are two main purposes of the Thread Registry:
- 1. Interrupt blocking I/O and signal condition variables in case of
- shutdown;
- 2. Wait for detached threads before shutting down the main thread.
-
- NOTE:
- 1. Handling shutdown can be done in more elegant manner by introducing
- Event (or Condition) object with support of logical operations.
- 2. Using Thread Registry to wait for detached threads is definitely not
- the best way, because when Thread Registry unregisters an thread, the
- thread is still alive. Accurate way to wait for threads to stop is
- not using detached threads and join all threads before shutdown.
- */
-
- Thread_registry thread_registry;
- User_map user_map;
- Instance_map instance_map;
- Guardian guardian(&thread_registry, &instance_map);
-
- Listener listener(&thread_registry, &user_map);
-
- p_instance_map= &instance_map;
- p_guardian= &guardian;
- p_thread_registry= &thread_registry;
- p_user_map= &user_map;
-
- /* Initialize instance map. */
-
- if (instance_map.init())
- {
- log_error("Manager: can not initialize instance list: out of memory.");
- return 1;
- }
-
- /* Initialize user db. */
-
- if (init_user_map(&user_map))
- return 1; /* logging has been already done. */
-
- /* Write Instance Manager pid file. */
-
- if (create_pid_file(Options::Main::pid_file_name, manager_pid))
- return 1; /* necessary logging has been already done. */
-
- log_info("Manager: pid file (%s) created.",
- (const char *) Options::Main::pid_file_name);
-
- /*
- Initialize signals and alarm-infrastructure.
-
- NOTE: To work nicely with LinuxThreads, the signal thread is the first
- thread in the process.
-
- NOTE: After init_thr_alarm() call it's possible to call thr_alarm()
- (from different threads), that results in sending ALARM signal to the
- alarm thread (which can be the main thread). That signal can interrupt
- blocking calls. In other words, a blocking call can be interrupted in
- the main thread after init_thr_alarm().
- */
-
- sigset_t mask;
- set_signals(&mask);
-
- /*
- Create the guardian thread. The newly started thread will block until
- we actually load instances.
-
- NOTE: Guardian should be shutdown first. Only then all other threads
- can be stopped. This should be done in this order because the guardian
- is responsible for shutting down all the guarded instances, and this
- is a long operation.
-
- NOTE: Guardian uses thr_alarm() when detects the current state of an
- instance (is_running()), but this does not interfere with
- flush_instances() call later in the code, because until
- flush_instances() completes in the main thread, Guardian thread is not
- permitted to process instances. And before flush_instances() has
- completed, there are no instances to guard.
- */
-
- if (guardian.start(Thread::DETACHED))
- {
- log_error("Manager: can not start Guardian thread.");
- goto err;
- }
-
- /* Load instances. */
-
- if (Manager::flush_instances())
- {
- log_error("Manager: can not init instances repository.");
- stop_all_threads();
- goto err;
- }
-
- /* Initialize the Listener. */
-
- if (listener.start(Thread::DETACHED))
- {
- log_error("Manager: can not start Listener thread.");
- stop_all_threads();
- goto err;
- }
-
- /*
- After the list of guarded instances have been initialized,
- Guardian should start them.
- */
-
- guardian.ping();
-
- /* Main loop. */
-
- log_info("Manager: started.");
-
- while (!shutdown_complete)
- {
- int signo;
- int status= 0;
-
- if ((status= my_sigwait(&mask, &signo)) != 0)
- {
- log_error("Manager: sigwait() failed");
- stop_all_threads();
- goto err;
- }
-
- /*
- The general idea in this loop is the following:
- - we are waiting for SIGINT, SIGTERM -- signals that mean we should
- shutdown;
- - as shutdown signal is caught, we stop Guardian thread (by calling
- Guardian::request_shutdown());
- - as Guardian is stopped, it sends SIGTERM to this thread
- (by calling Thread_registry::request_shutdown()), so that the
- my_sigwait() above returns;
- - as we catch the second SIGTERM, we send signals to all threads
- registered in Thread_registry (by calling
- Thread_registry::deliver_shutdown()) and waiting for threads to stop;
- */
-
-#ifndef __WIN__
-/*
- On some Darwin kernels SIGHUP is delivered along with most
- signals. This is why we skip it's processing on these
- platforms. For more details and test program see
- Bug #14164 IM tests fail on MacOS X (powermacg5)
-*/
-#ifdef IGNORE_SIGHUP_SIGQUIT
- if (SIGHUP == signo)
- continue;
-#endif
- if (THR_SERVER_ALARM == signo)
- process_alarm(signo);
- else
-#endif
- {
- log_info("Manager: got shutdown signal.");
-
- if (!guardian.is_stopped())
- {
- guardian.request_shutdown();
- }
- else
- {
- thread_registry.deliver_shutdown();
- shutdown_complete= TRUE;
- }
- }
- }
-
- log_info("Manager: finished.");
-
-err:
- /* delete the pid file */
- my_delete(Options::Main::pid_file_name, MYF(0));
-
-#ifndef __WIN__
- /* free alarm structures */
- end_thr_alarm(1);
-#endif
-
- return thread_registry.get_error_status() ? 1 : 0;
-}
-
-
-/**
- Re-read instance configuration file.
-
- SYNOPSIS
- flush_instances()
-
- DESCRIPTION
- This function will:
- - clear the current list of instances. This removes both
- running and stopped instances.
- - load a new instance configuration from the file.
- - pass on the new map to the guardian thread: it will start
- all instances that are marked `guarded' and not yet started.
-
- Note, as the check whether an instance is started is currently
- very simple (returns TRUE if there is a MySQL server running
- at the given port), this function has some peculiar
- side-effects:
- * if the port number of a running instance was changed, the
- old instance is forgotten, even if it was running. The new
- instance will be started at the new port.
- * if the configuration was changed in a way that two
- instances swapped their port numbers, the guardian thread
- will not notice that and simply report that both instances
- are configured successfully and running.
-
- In order to avoid such side effects one should never call
- FLUSH INSTANCES without prior stop of all running instances.
-
- RETURN
- 0 On success
- ER_OUT_OF_RESOURCES Not enough resources to complete the operation
- ER_THERE_IS_ACTIVE_INSTACE If there is an active instance
-*/
-
-int Manager::flush_instances()
-{
- p_instance_map->lock();
-
- if (p_instance_map->is_there_active_instance())
- {
- p_instance_map->unlock();
- return ER_THERE_IS_ACTIVE_INSTACE;
- }
-
- if (p_instance_map->reset())
- {
- p_instance_map->unlock();
- return ER_OUT_OF_RESOURCES;
- }
-
- if (p_instance_map->load())
- {
- p_instance_map->unlock();
-
- /* Don't init guardian if we failed to load instances. */
- return ER_OUT_OF_RESOURCES;
- }
-
- get_guardian()->init();
- get_guardian()->ping();
-
- p_instance_map->unlock();
-
- return 0;
-}
diff --git a/server-tools/instance-manager/manager.h b/server-tools/instance-manager/manager.h
deleted file mode 100644
index e6956884603..00000000000
--- a/server-tools/instance-manager/manager.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-#include <my_global.h>
-
-class Guardian;
-class Instance_map;
-class Thread_registry;
-class User_map;
-
-class Manager
-{
-public:
- static int main();
-
- static int flush_instances();
-
-public:
- /**
- These methods return a non-NULL value only for the duration
- of main().
- */
- static Instance_map *get_instance_map() { return p_instance_map; }
- static Guardian *get_guardian() { return p_guardian; }
- static Thread_registry *get_thread_registry() { return p_thread_registry; }
- static User_map *get_user_map() { return p_user_map; }
-
-public:
-#ifndef __WIN__
- static bool is_linux_threads() { return linux_threads; }
-#endif // __WIN__
-
-private:
- static void stop_all_threads();
- static bool init_user_map(User_map *user_map);
-
-private:
- static Guardian *p_guardian;
- static Instance_map *p_instance_map;
- static Thread_registry *p_thread_registry;
- static User_map *p_user_map;
-
-#ifndef __WIN__
- /*
- This flag is set if Instance Manager is running on the system using
- LinuxThreads.
- */
- static bool linux_threads;
-#endif // __WIN__
-};
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MANAGER_H
diff --git a/server-tools/instance-manager/messages.cc b/server-tools/instance-manager/messages.cc
deleted file mode 100644
index 201ebfd62fc..00000000000
--- a/server-tools/instance-manager/messages.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#include "messages.h"
-
-#include <my_global.h>
-#include <mysql_com.h>
-
-#include "mysqld_error.h"
-#include "mysql_manager_error.h"
-
-
-static const char *mysqld_error_message(unsigned sql_errno)
-{
- switch (sql_errno) {
- case ER_HANDSHAKE_ERROR:
- return "Bad handshake";
- case ER_OUT_OF_RESOURCES:
- return "Out of memory; Check if mysqld or some other process"
- " uses all available memory. If not you may have to use"
- " 'ulimit' to allow mysqld to use more memory or you can"
- " add more swap space";
- case ER_ACCESS_DENIED_ERROR:
- return "Access denied. Bad username/password pair";
- case ER_NOT_SUPPORTED_AUTH_MODE:
- return "Client does not support authentication protocol requested by"
- " server; consider upgrading MySQL client";
- case ER_UNKNOWN_COM_ERROR:
- return "Unknown command";
- case ER_SYNTAX_ERROR:
- return "You have an error in your command syntax. Check the manual that"
- " corresponds to your MySQL Instance Manager version for the right"
- " syntax to use";
- case ER_BAD_INSTANCE_NAME:
- return "Unknown instance name";
- case ER_INSTANCE_IS_NOT_STARTED:
- return "Cannot stop instance. Perhaps the instance is not started, or was"
- " started manually, so IM cannot find the pidfile.";
- case ER_INSTANCE_ALREADY_STARTED:
- return "The instance is already started";
- case ER_CANNOT_START_INSTANCE:
- return "Cannot start instance. Possible reasons are wrong instance options"
- " or resources shortage";
- case ER_OFFSET_ERROR:
- return "Cannot read negative number of bytes";
- case ER_STOP_INSTANCE:
- return "Cannot stop instance";
- case ER_READ_FILE:
- return "Cannot read requested part of the logfile";
- case ER_NO_SUCH_LOG:
- return "The instance has no such log enabled";
- case ER_OPEN_LOGFILE:
- return "Cannot open log file";
- case ER_GUESS_LOGFILE:
- return "Cannot guess the log filename. Try specifying full log name"
- " in the instance options";
- case ER_ACCESS_OPTION_FILE:
- return "Cannot open the option file to edit. Check permissions";
- case ER_DROP_ACTIVE_INSTANCE:
- return "Cannot drop an active instance. You should stop it first";
- case ER_CREATE_EXISTING_INSTANCE:
- return "Instance already exists";
- case ER_INSTANCE_MISCONFIGURED:
- return "Instance is misconfigured. Cannot start it";
- case ER_MALFORMED_INSTANCE_NAME:
- return "Malformed instance name.";
- case ER_INSTANCE_IS_ACTIVE:
- return "The instance is active. Stop the instance first";
- case ER_THERE_IS_ACTIVE_INSTACE:
- return "At least one instance is active. Stop all instances first";
- case ER_INCOMPATIBLE_OPTION:
- return "Instance Manager-specific options are prohibited from being used "
- "in the configuration of mysqld-compatible instances";
- case ER_CONF_FILE_DOES_NOT_EXIST:
- return "Configuration file does not exist";
- default:
- DBUG_ASSERT(0);
- return 0;
- }
-}
-
-
-const char *message(unsigned sql_errno)
-{
- return mysqld_error_message(sql_errno);
-}
-
-
-const char *errno_to_sqlstate(unsigned sql_errno)
-{
- return mysql_errno_to_sqlstate(sql_errno);
-}
diff --git a/server-tools/instance-manager/messages.h b/server-tools/instance-manager/messages.h
deleted file mode 100644
index 5d9383093bc..00000000000
--- a/server-tools/instance-manager/messages.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_MESSAGES_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_MESSAGES_H
-
-const char *message(unsigned sql_errno);
-
-const char *errno_to_sqlstate(unsigned sql_errno);
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MESSAGES_H
diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc
deleted file mode 100644
index 12ea0a3ea5a..00000000000
--- a/server-tools/instance-manager/mysql_connection.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "mysql_connection.h"
-
-#include <m_string.h>
-#include <m_string.h>
-#include <my_global.h>
-#include <mysql.h>
-#include <my_sys.h>
-#include <violite.h>
-
-#include "command.h"
-#include "log.h"
-#include "messages.h"
-#include "mysqld_error.h"
-#include "mysql_manager_error.h"
-#include "parse.h"
-#include "priv.h"
-#include "protocol.h"
-#include "thread_registry.h"
-#include "user_map.h"
-
-
-Mysql_connection::Mysql_connection(Thread_registry *thread_registry_arg,
- User_map *user_map_arg,
- struct st_vio *vio_arg, ulong
- connection_id_arg)
- :vio(vio_arg),
- connection_id(connection_id_arg),
- thread_registry(thread_registry_arg),
- user_map(user_map_arg)
-{
-}
-
-
-/*
- NET subsystem requieres its user to provide my_net_local_init extern
- C function (exactly as declared below). my_net_local_init is called by
- my_net_init and is supposed to set NET controlling variables.
- See also priv.h for variables description.
-*/
-
-C_MODE_START
-
-void my_net_local_init(NET *net)
-{
- net->max_packet= net_buffer_length;
- my_net_set_read_timeout(net, (uint)net_read_timeout);
- my_net_set_write_timeout(net, (uint)net_write_timeout);
- net->retry_count= net_retry_count;
- net->max_packet_size= max_allowed_packet;
-}
-
-C_MODE_END
-
-/*
- Unused stub hook required for linking the client API.
-*/
-
-C_MODE_START
-
-void slave_io_thread_detach_vio()
-{
-}
-
-C_MODE_END
-
-
-/*
- Every resource, which we can fail to acquire, is allocated in init().
- This function is complementary to cleanup().
-*/
-
-bool Mysql_connection::init()
-{
- /* Allocate buffers for network I/O */
- if (my_net_init(&net, vio))
- return TRUE;
-
- net.return_status= &status;
-
- /* Initialize random number generator */
- {
- ulong seed1= (ulong) &rand_st + rand();
- ulong seed2= (ulong) rand() + (ulong) time(0);
- randominit(&rand_st, seed1, seed2);
- }
-
- /* Fill scramble - server's random message used for handshake */
- create_random_string(scramble, SCRAMBLE_LENGTH, &rand_st);
-
- /* We don't support transactions, every query is atomic */
- status= SERVER_STATUS_AUTOCOMMIT;
-
- thread_registry->register_thread(&thread_info);
-
- return FALSE;
-}
-
-
-void Mysql_connection::cleanup()
-{
- net_end(&net);
- thread_registry->unregister_thread(&thread_info);
-}
-
-
-Mysql_connection::~Mysql_connection()
-{
- /* vio_delete closes the socket if necessary */
- vio_delete(vio);
-}
-
-
-void Mysql_connection::main()
-{
- log_info("Connection %lu: accepted.", (unsigned long) connection_id);
-
- if (check_connection())
- {
- log_info("Connection %lu: failed to authorize the user.",
- (unsigned long) connection_id);
-
- return;
- }
-
- log_info("Connection %lu: the user was authorized successfully.",
- (unsigned long) connection_id);
-
- vio_keepalive(vio, TRUE);
-
- while (!net.error && net.vio && !thread_registry->is_shutdown())
- {
- if (do_command())
- break;
- }
-}
-
-
-int Mysql_connection::check_connection()
-{
- ulong pkt_len=0; // to hold client reply length
-
- /* buffer for the first packet */ /* packet contains: */
- uchar buff[MAX_VERSION_LENGTH + 1 + // server version, 0-ended
- 4 + // connection id
- SCRAMBLE_LENGTH + 2 + // scramble (in 2 pieces)
- 18]; // server variables: flags,
- // charset number, status,
- uchar *pos= buff;
- ulong server_flags;
-
- memcpy(pos, mysqlmanager_version.str, mysqlmanager_version.length + 1);
- pos+= mysqlmanager_version.length + 1;
-
- int4store((uchar*) pos, connection_id);
- pos+= 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 (even though we don't support old clients,
- we must follow standard packet format.)
- */
- memcpy(pos, scramble, SCRAMBLE_LENGTH_323);
- pos+= SCRAMBLE_LENGTH_323;
- *pos++= '\0';
-
- server_flags= CLIENT_LONG_FLAG | CLIENT_PROTOCOL_41 |
- CLIENT_SECURE_CONNECTION;
-
- /*
- 18-bytes long section for various flags/variables
-
- Every flag occupies a bit in first half of ulong; int2store will
- gracefully pick up all flags.
- */
- int2store(pos, server_flags);
- pos+= 2;
- *pos++= (char) default_charset_info->number; // global mysys variable
- int2store(pos, status); // connection status
- pos+= 2;
- bzero(pos, 13); // not used now
- pos+= 13;
-
- /* second part of the scramble, null-terminated */
- memcpy(pos, scramble + SCRAMBLE_LENGTH_323,
- SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1);
- pos+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1;
-
- /* write connection message and read reply */
- enum { MIN_HANDSHAKE_SIZE= 2 };
- if (net_write_command(&net, protocol_version, (uchar*) "", 0,
- buff, pos - buff) ||
- (pkt_len= my_net_read(&net)) == packet_error ||
- pkt_len < MIN_HANDSHAKE_SIZE)
- {
- net_send_error(&net, ER_HANDSHAKE_ERROR);
- return 1;
- }
-
- client_capabilities= uint2korr(net.read_pos);
- if (!(client_capabilities & CLIENT_PROTOCOL_41))
- {
- net_send_error_323(&net, ER_NOT_SUPPORTED_AUTH_MODE);
- return 1;
- }
- client_capabilities|= ((ulong) uint2korr(net.read_pos + 2)) << 16;
-
- pos= net.read_pos + 32;
-
- /* At least one byte for username and one byte for password */
- if (pos >= net.read_pos + pkt_len + 2)
- {
- /*TODO add user and password handling in error messages*/
- net_send_error(&net, ER_HANDSHAKE_ERROR);
- return 1;
- }
-
- const char *user= (char*) pos;
- const char *password= strend(user)+1;
- ulong password_len= *password++;
- LEX_STRING user_name= { (char *) user, password - user - 2 };
-
- if (password_len != SCRAMBLE_LENGTH)
- {
- net_send_error(&net, ER_ACCESS_DENIED_ERROR);
- return 1;
- }
- if (user_map->authenticate(&user_name, password, scramble))
- {
- net_send_error(&net, ER_ACCESS_DENIED_ERROR);
- return 1;
- }
- net_send_ok(&net, connection_id, NULL);
- return 0;
-}
-
-
-int Mysql_connection::do_command()
-{
- char *packet;
- ulong packet_length;
-
- /* We start to count packets from 0 for each new command */
- net.pkt_nr= 0;
-
- if ((packet_length=my_net_read(&net)) == packet_error)
- {
- /* Check if we can continue without closing the connection */
- if (net.error != 3) // what is 3 - find out
- return 1;
- if (thread_registry->is_shutdown())
- return 1;
- net_send_error(&net, net.last_errno);
- net.error= 0;
- return 0;
- }
- else
- {
- if (thread_registry->is_shutdown())
- return 1;
- packet= (char*) net.read_pos;
- enum enum_server_command command= (enum enum_server_command)
- (uchar) *packet;
- log_info("Connection %lu: received packet (length: %lu; command: %d).",
- (unsigned long) connection_id,
- (unsigned long) packet_length,
- (int) command);
-
- return dispatch_command(command, packet + 1);
- }
-}
-
-int Mysql_connection::dispatch_command(enum enum_server_command command,
- const char *packet)
-{
- switch (command) {
- case COM_QUIT: // client exit
- log_info("Connection %lu: received QUIT command.",
- (unsigned long) connection_id);
- return 1;
-
- case COM_PING:
- log_info("Connection %lu: received PING command.",
- (unsigned long) connection_id);
- net_send_ok(&net, connection_id, NULL);
- return 0;
-
- case COM_QUERY:
- {
- log_info("Connection %lu: received QUERY command: '%s'.",
- (unsigned long) connection_id,
- (const char *) packet);
-
- if (Command *com= parse_command(packet))
- {
- int res= 0;
-
- log_info("Connection %lu: query parsed successfully.",
- (unsigned long) connection_id);
-
- res= com->execute(&net, connection_id);
- delete com;
- if (!res)
- {
- log_info("Connection %lu: query executed successfully",
- (unsigned long) connection_id);
- }
- else
- {
- log_info("Connection %lu: can not execute query (error: %d).",
- (unsigned long) connection_id,
- (int) res);
-
- net_send_error(&net, res);
- }
- }
- else
- {
- log_error("Connection %lu: can not parse query: out ot resources.",
- (unsigned long) connection_id);
-
- net_send_error(&net,ER_OUT_OF_RESOURCES);
- }
-
- return 0;
- }
-
- default:
- log_info("Connection %lu: received unsupported command (%d).",
- (unsigned long) connection_id,
- (int) command);
-
- net_send_error(&net, ER_UNKNOWN_COM_ERROR);
- return 0;
- }
-
- return 0; /* Just to make compiler happy. */
-}
-
-
-void Mysql_connection::run()
-{
- if (init())
- log_error("Connection %lu: can not init handler.",
- (unsigned long) connection_id);
- else
- {
- main();
- cleanup();
- }
-
- delete this;
-}
-
-/*
- vim: fdm=marker
-*/
diff --git a/server-tools/instance-manager/mysql_connection.h b/server-tools/instance-manager/mysql_connection.h
deleted file mode 100644
index 56bbf76e146..00000000000
--- a/server-tools/instance-manager/mysql_connection.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H
-
-#include "thread_registry.h"
-#include <mysql_com.h>
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-struct st_vio;
-class User_map;
-
-/*
- MySQL connection - handle one connection with mysql command line client
- See also comments in mysqlmanager.cc to picture general Instance Manager
- architecture.
- We use conventional technique to work with classes without exceptions:
- class acquires all vital resource in init(); Thus if init() succeed,
- a user must call cleanup(). All other methods are valid only between
- init() and cleanup().
-*/
-
-class Mysql_connection: public Thread
-{
-public:
- Mysql_connection(Thread_registry *thread_registry_arg,
- User_map *user_map_arg,
- struct st_vio *vio_arg,
- ulong connection_id_arg);
- virtual ~Mysql_connection();
-
-protected:
- virtual void run();
-
-private:
- struct st_vio *vio;
- ulong connection_id;
- Thread_info thread_info;
- Thread_registry *thread_registry;
- User_map *user_map;
- NET net;
- struct rand_struct rand_st;
- char scramble[SCRAMBLE_LENGTH + 1];
- uint status;
- ulong client_capabilities;
-private:
- /* The main loop implementation triad */
- bool init();
- void main();
- void cleanup();
-
- /* Names are conventionally the same as in mysqld */
- int check_connection();
- int do_command();
- int dispatch_command(enum enum_server_command command, const char *text);
-};
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_CONNECTION_H
diff --git a/server-tools/instance-manager/mysql_manager_error.h b/server-tools/instance-manager/mysql_manager_error.h
deleted file mode 100644
index e50e5d24f6d..00000000000
--- a/server-tools/instance-manager/mysql_manager_error.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 */
-
-/* Definefile for instance manager error messagenumbers */
-
-#define ER_BAD_INSTANCE_NAME 3000
-#define ER_INSTANCE_IS_NOT_STARTED 3001
-#define ER_INSTANCE_ALREADY_STARTED 3002
-#define ER_CANNOT_START_INSTANCE 3003
-#define ER_STOP_INSTANCE 3004
-#define ER_NO_SUCH_LOG 3005
-#define ER_OPEN_LOGFILE 3006
-#define ER_GUESS_LOGFILE 3007
-#define ER_ACCESS_OPTION_FILE 3008
-#define ER_OFFSET_ERROR 3009
-#define ER_READ_FILE 3010
-#define ER_DROP_ACTIVE_INSTANCE 3011
-#define ER_CREATE_EXISTING_INSTANCE 3012
-#define ER_INSTANCE_MISCONFIGURED 3013
-#define ER_MALFORMED_INSTANCE_NAME 3014
-#define ER_INSTANCE_IS_ACTIVE 3015
-#define ER_THERE_IS_ACTIVE_INSTACE 3016
-#define ER_INCOMPATIBLE_OPTION 3017
-#define ER_CONF_FILE_DOES_NOT_EXIST 3018
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_MYSQL_MANAGER_ERROR_H */
diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc
deleted file mode 100644
index 276d1ca3b49..00000000000
--- a/server-tools/instance-manager/mysqlmanager.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#include <my_global.h>
-#include <my_dir.h>
-#include <my_sys.h>
-
-#include <string.h>
-
-#ifndef __WIN__
-#include <pwd.h>
-#include <grp.h>
-#endif
-
-#include "angel.h"
-#include "log.h"
-#include "manager.h"
-#include "options.h"
-#include "user_management_commands.h"
-
-#ifdef __WIN__
-#include "IMService.h"
-#endif
-
-
-/*
- Instance Manager consists of two processes: the angel process (IM-angel),
- and the manager process (IM-main). Responsibilities of IM-angel is to
- monitor IM-main, and restart it in case of failure/shutdown. IM-angel is
- started only if startup option '--run-as-service' is provided.
-
- IM-main consists of several subsystems (thread sets):
-
- - the signal handling thread
-
- The signal thread handles user signals and propagates them to the
- other threads. All other threads are accounted in the signal handler
- thread Thread Registry.
-
- - the listener
-
- The listener listens to all sockets. There is a listening socket for
- each subsystem (TCP/IP, UNIX socket).
-
- - mysql subsystem
-
- Instance Manager acts like an ordinary MySQL Server, but with very
- restricted command set. Each MySQL client connection is handled in a
- separate thread. All MySQL client connections threads constitute
- mysql subsystem.
-*/
-
-static int main_impl(int argc, char *argv[]);
-
-#ifndef __WIN__
-static struct passwd *check_user();
-static bool switch_user();
-#endif
-
-
-/************************************************************************/
-/**
- The entry point.
-*************************************************************************/
-
-int main(int argc, char *argv[])
-{
- int return_value;
-
- puts("\n"
- "WARNING: This program is deprecated and will be removed in 6.0.\n");
-
- /* Initialize. */
-
- MY_INIT(argv[0]);
- log_init();
- umask(0117);
- srand((uint) time(0));
-
- /* Main function. */
-
- log_info("IM: started.");
-
- return_value= main_impl(argc, argv);
-
- log_info("IM: finished.");
-
- /* Cleanup. */
-
- Options::cleanup();
- my_end(0);
-
- return return_value;
-}
-
-
-/************************************************************************/
-/**
- Instance Manager main functionality.
-*************************************************************************/
-
-int main_impl(int argc, char *argv[])
-{
- int rc;
-
- if ((rc= Options::load(argc, argv)))
- return rc;
-
- if (Options::User_management::cmd)
- return Options::User_management::cmd->execute();
-
-#ifndef __WIN__
-
- if (switch_user())
- return 1;
-
- return Options::Daemon::run_as_service ?
- Angel::main() :
- Manager::main();
-
-#else
-
- return Options::Service::stand_alone ?
- Manager::main() :
- IMService::main();
-
-#endif
-}
-
-/**************************************************************************
- OS-specific functions implementation.
-**************************************************************************/
-
-#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
-
-/************************************************************************/
-/**
- Change to run as another user if started with --user.
-*************************************************************************/
-
-static struct passwd *check_user()
-{
- const char *user= Options::Daemon::user;
- struct passwd *user_info;
- uid_t user_id= geteuid();
-
- /* Don't bother if we aren't superuser */
- if (user_id)
- {
- if (user)
- {
- /* Don't give a warning, if real user is same as given with --user */
- user_info= getpwnam(user);
- if ((!user_info || user_id != user_info->pw_uid))
- log_info("One can only use the --user switch if running as root\n");
- }
- return NULL;
- }
- if (!user)
- {
- log_info("You are running mysqlmanager as root! This might introduce security problems. It is safer to use --user option istead.\n");
- return NULL;
- }
- if (!strcmp(user, "root"))
- return NULL; /* Avoid problem with dynamic libraries */
- if (!(user_info= getpwnam(user)))
- {
- /* Allow a numeric uid to be used */
- const char *pos;
- for (pos= user; my_isdigit(default_charset_info, *pos); pos++)
- {}
- if (*pos) /* Not numeric id */
- goto err;
- if (!(user_info= getpwuid(atoi(user))))
- goto err;
- else
- return user_info;
- }
- else
- return user_info;
-
-err:
- log_error("Can not start under user '%s'.",
- (const char *) user);
- return NULL;
-}
-
-
-/************************************************************************/
-/**
- Switch user.
-*************************************************************************/
-
-static bool switch_user()
-{
- struct passwd *user_info= check_user();
-
- if (!user_info)
- return FALSE;
-
-#ifdef HAVE_INITGROUPS
- initgroups(Options::Daemon::user, user_info->pw_gid);
-#endif
-
- if (setgid(user_info->pw_gid) == -1)
- {
- log_error("setgid() failed");
- return TRUE;
- }
-
- if (setuid(user_info->pw_uid) == -1)
- {
- log_error("setuid() failed");
- return TRUE;
- }
-
- return FALSE;
-}
-
-#endif
diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc
deleted file mode 100644
index ebca593bb03..00000000000
--- a/server-tools/instance-manager/options.cc
+++ /dev/null
@@ -1,558 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "options.h"
-
-#include <my_global.h>
-#include <my_sys.h>
-#include <my_getopt.h>
-#include <mysql_com.h>
-
-#include "exit_codes.h"
-#include "log.h"
-#include "portability.h"
-#include "priv.h"
-#include "user_management_commands.h"
-
-#define QUOTE2(x) #x
-#define QUOTE(x) QUOTE2(x)
-
-#ifdef __WIN__
-
-/* Define holders for default values. */
-
-static char win_dflt_config_file_name[FN_REFLEN];
-static char win_dflt_password_file_name[FN_REFLEN];
-static char win_dflt_pid_file_name[FN_REFLEN];
-
-static char win_dflt_mysqld_path[FN_REFLEN];
-
-/* Define and initialize Windows-specific options. */
-
-my_bool Options::Service::install_as_service;
-my_bool Options::Service::remove_service;
-my_bool Options::Service::stand_alone;
-
-const char *Options::Main::config_file= win_dflt_config_file_name;
-const char *Options::Main::password_file_name= win_dflt_password_file_name;
-const char *Options::Main::pid_file_name= win_dflt_pid_file_name;
-
-const char *Options::Main::default_mysqld_path= win_dflt_mysqld_path;
-
-static int setup_windows_defaults();
-
-#else /* UNIX */
-
-/* Define and initialize UNIX-specific options. */
-
-my_bool Options::Daemon::run_as_service= FALSE;
-const char *Options::Daemon::log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
-const char *Options::Daemon::user= NULL; /* No default value */
-const char *Options::Daemon::angel_pid_file_name= NULL;
-
-const char *Options::Main::config_file= QUOTE(DEFAULT_CONFIG_FILE);
-const char *
-Options::Main::password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME);
-const char *Options::Main::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
-const char *Options::Main::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
-
-const char *Options::Main::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
-
-#endif
-
-/* Remember if the config file was forced. */
-
-bool Options::Main::is_forced_default_file= FALSE;
-
-/* Define and initialize common options. */
-
-const char *Options::Main::bind_address= NULL; /* No default value */
-uint Options::Main::monitoring_interval= DEFAULT_MONITORING_INTERVAL;
-uint Options::Main::port_number= DEFAULT_PORT;
-my_bool Options::Main::mysqld_safe_compatible= FALSE;
-const char **Options::default_directories= NULL;
-
-/* Options::User_management */
-
-char *Options::User_management::user_name= NULL;
-char *Options::User_management::password= NULL;
-
-User_management_cmd *Options::User_management::cmd= NULL;
-
-/* Private members. */
-
-char **Options::saved_argv= NULL;
-
-#ifndef DBUG_OFF
-const char *Options::Debug::config_str= "d:t:i:O,im.trace";
-#endif
-
-static const char * const ANGEL_PID_FILE_SUFFIX= ".angel.pid";
-static const int ANGEL_PID_FILE_SUFFIX_LEN= (uint) strlen(ANGEL_PID_FILE_SUFFIX);
-
-/*
- List of options, accepted by the instance manager.
- List must be closed with empty option.
-*/
-
-enum options {
- OPT_USERNAME= 'u',
- OPT_PASSWORD= 'p',
- OPT_LOG= 256,
- OPT_PID_FILE,
- OPT_SOCKET,
- OPT_PASSWORD_FILE,
- OPT_MYSQLD_PATH,
-#ifdef __WIN__
- OPT_INSTALL_SERVICE,
- OPT_REMOVE_SERVICE,
- OPT_STAND_ALONE,
-#else
- OPT_RUN_AS_SERVICE,
- OPT_USER,
- OPT_ANGEL_PID_FILE,
-#endif
- OPT_MONITORING_INTERVAL,
- OPT_PORT,
- OPT_WAIT_TIMEOUT,
- OPT_BIND_ADDRESS,
- OPT_PRINT_PASSWORD_LINE,
- OPT_ADD_USER,
- OPT_DROP_USER,
- OPT_EDIT_USER,
- OPT_CLEAN_PASSWORD_FILE,
- OPT_CHECK_PASSWORD_FILE,
- OPT_LIST_USERS,
- OPT_MYSQLD_SAFE_COMPATIBLE
-};
-
-static struct my_option my_long_options[] =
-{
- { "help", '?', "Display this help and exit.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "add-user", OPT_ADD_USER,
- "Add a user to the password file",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
-#ifndef __WIN__
- { "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.",
- (uchar* *) &Options::Daemon::angel_pid_file_name,
- (uchar* *) &Options::Daemon::angel_pid_file_name,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-#endif
-
- { "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.",
- (uchar* *) &Options::Main::bind_address,
- (uchar* *) &Options::Main::bind_address,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "check-password-file", OPT_CHECK_PASSWORD_FILE,
- "Check the password file for consistency",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "clean-password-file", OPT_CLEAN_PASSWORD_FILE,
- "Clean the password file",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
-#ifndef DBUG_OFF
- {"debug", '#', "Debug log.",
- (uchar* *) &Options::Debug::config_str,
- (uchar* *) &Options::Debug::config_str,
- 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
-#endif
-
- { "default-mysqld-path", OPT_MYSQLD_PATH, "Where to look for MySQL"
- " Server binary.",
- (uchar* *) &Options::Main::default_mysqld_path,
- (uchar* *) &Options::Main::default_mysqld_path,
- 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "drop-user", OPT_DROP_USER,
- "Drop existing user from the password file",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "edit-user", OPT_EDIT_USER,
- "Edit existing user in the password file",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
-#ifdef __WIN__
- { "install", OPT_INSTALL_SERVICE, "Install as system service.",
- (uchar* *) &Options::Service::install_as_service,
- (uchar* *) &Options::Service::install_as_service,
- 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
-#endif
-
- { "list-users", OPT_LIST_USERS,
- "Print out a list of registered users",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
-#ifndef __WIN__
- { "log", OPT_LOG, "Path to log file. Used only with --run-as-service.",
- (uchar* *) &Options::Daemon::log_file_name,
- (uchar* *) &Options::Daemon::log_file_name,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-#endif
-
- { "monitoring-interval", OPT_MONITORING_INTERVAL, "Interval to monitor"
- " instances in seconds.",
- (uchar* *) &Options::Main::monitoring_interval,
- (uchar* *) &Options::Main::monitoring_interval,
- 0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL,
- 0, 0, 0, 0, 0 },
-
- { "mysqld-safe-compatible", OPT_MYSQLD_SAFE_COMPATIBLE,
- "Start Instance Manager in mysqld_safe compatible manner",
- (uchar* *) &Options::Main::mysqld_safe_compatible,
- (uchar* *) &Options::Main::mysqld_safe_compatible,
- 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
-
- { "print-password-line", OPT_PRINT_PASSWORD_LINE,
- "Print out a user entry as a line for the password file and exit.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "password", OPT_PASSWORD, "Password to update the password file",
- (uchar* *) &Options::User_management::password,
- (uchar* *) &Options::User_management::password,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "password-file", OPT_PASSWORD_FILE,
- "Look for Instance Manager users and passwords here.",
- (uchar* *) &Options::Main::password_file_name,
- (uchar* *) &Options::Main::password_file_name,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "pid-file", OPT_PID_FILE, "Pid file to use.",
- (uchar* *) &Options::Main::pid_file_name,
- (uchar* *) &Options::Main::pid_file_name,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "port", OPT_PORT, "Port number to use for connections",
- (uchar* *) &Options::Main::port_number,
- (uchar* *) &Options::Main::port_number,
- 0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 },
-
-#ifdef __WIN__
- { "remove", OPT_REMOVE_SERVICE, "Remove system service.",
- (uchar* *) &Options::Service::remove_service,
- (uchar* *) &Options::Service::remove_service,
- 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
-#else
- { "run-as-service", OPT_RUN_AS_SERVICE,
- "Daemonize and start angel process.",
- (uchar* *) &Options::Daemon::run_as_service,
- 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
-#endif
-
-#ifndef __WIN__
- { "socket", OPT_SOCKET, "Socket file to use for connection.",
- (uchar* *) &Options::Main::socket_file_name,
- (uchar* *) &Options::Main::socket_file_name,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-#endif
-
-#ifdef __WIN__
- { "standalone", OPT_STAND_ALONE, "Run the application in stand alone mode.",
- (uchar* *) &Options::Service::stand_alone,
- (uchar* *) &Options::Service::stand_alone,
- 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
-#else
- { "user", OPT_USER, "Username to start mysqlmanager",
- (uchar* *) &Options::Daemon::user,
- (uchar* *) &Options::Daemon::user,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-#endif
-
- { "username", OPT_USERNAME,
- "Username to update the password file",
- (uchar* *) &Options::User_management::user_name,
- (uchar* *) &Options::User_management::user_name,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "version", 'V', "Output version information and exit.", 0, 0, 0,
- GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
-
- { "wait-timeout", OPT_WAIT_TIMEOUT, "The number of seconds IM waits "
- "for activity on a connection before closing it.",
- (uchar* *) &net_read_timeout,
- (uchar* *) &net_read_timeout,
- 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0 },
-
- { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
-};
-
-static void version()
-{
- printf("%s Ver %s for %s on %s\n", my_progname,
- (const char *) mysqlmanager_version.str,
- SYSTEM_TYPE, MACHINE_TYPE);
-}
-
-
-static const char *default_groups[]= { "manager", 0 };
-
-
-static void usage()
-{
- version();
-
- printf("Copyright (C) 2003, 2004 MySQL AB\n"
- "This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
- "and you are welcome to modify and redistribute it under the GPL license\n");
- printf("Usage: %s [OPTIONS] \n", my_progname);
-
- my_print_help(my_long_options);
- printf("\nThe following options may be given as the first argument:\n"
- "--print-defaults Print the program argument list and exit\n"
- "--defaults-file=# Only read manager configuration and instance\n"
- " setings from the given file #. The same file\n"
- " will be used to modify configuration of instances\n"
- " with SET commands.\n");
- my_print_variables(my_long_options);
-}
-
-
-C_MODE_START
-
-static my_bool
-get_one_option(int optid,
- const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- switch(optid) {
- case 'V':
- version();
- exit(0);
- case OPT_PRINT_PASSWORD_LINE:
- case OPT_ADD_USER:
- case OPT_DROP_USER:
- case OPT_EDIT_USER:
- case OPT_CLEAN_PASSWORD_FILE:
- case OPT_CHECK_PASSWORD_FILE:
- case OPT_LIST_USERS:
- if (Options::User_management::cmd)
- {
- fprintf(stderr, "Error: only one password-management command "
- "can be specified at a time.\n");
- exit(ERR_INVALID_USAGE);
- }
-
- switch (optid) {
- case OPT_PRINT_PASSWORD_LINE:
- Options::User_management::cmd= new Print_password_line_cmd();
- break;
- case OPT_ADD_USER:
- Options::User_management::cmd= new Add_user_cmd();
- break;
- case OPT_DROP_USER:
- Options::User_management::cmd= new Drop_user_cmd();
- break;
- case OPT_EDIT_USER:
- Options::User_management::cmd= new Edit_user_cmd();
- break;
- case OPT_CLEAN_PASSWORD_FILE:
- Options::User_management::cmd= new Clean_db_cmd();
- break;
- case OPT_CHECK_PASSWORD_FILE:
- Options::User_management::cmd= new Check_db_cmd();
- break;
- case OPT_LIST_USERS:
- Options::User_management::cmd= new List_users_cmd();
- break;
- }
-
- break;
- case '?':
- usage();
- exit(0);
- case '#':
-#ifndef DBUG_OFF
- DBUG_SET(argument ? argument : Options::Debug::config_str);
- DBUG_SET_INITIAL(argument ? argument : Options::Debug::config_str);
-#endif
- break;
- }
- return 0;
-}
-
-C_MODE_END
-
-
-/*
- - Process argv of original program: get tid of --defaults-extra-file
- and print a message if met there.
- - call load_defaults to load configuration file section and save the pointer
- for free_defaults.
- - call handle_options to assign defaults and command-line arguments
- to the class members.
- if either of these function fail, return the error code.
-*/
-
-int Options::load(int argc, char **argv)
-{
- if (argc >= 2)
- {
- if (is_prefix(argv[1], "--defaults-file="))
- {
- Main::config_file= strchr(argv[1], '=') + 1;
- Main::is_forced_default_file= TRUE;
- }
- if (is_prefix(argv[1], "--defaults-extra-file=") ||
- is_prefix(argv[1], "--no-defaults"))
- {
- /* the log is not enabled yet */
- fprintf(stderr, "The --defaults-extra-file and --no-defaults options"
- " are not supported by\n"
- "Instance Manager. Program aborted.\n");
- return ERR_INVALID_USAGE;
- }
- }
-
-#ifdef __WIN__
- if (setup_windows_defaults())
- {
- fprintf(stderr, "Internal error: could not setup default values.\n");
- return ERR_OUT_OF_MEMORY;
- }
-#endif
-
- /* load_defaults will reset saved_argv with a new allocated list */
- saved_argv= argv;
-
- /* config-file options are prepended to command-line ones */
-
- log_info("Loading config file '%s'...",
- (const char *) Main::config_file);
-
- my_load_defaults(Main::config_file, default_groups, &argc,
- &saved_argv, &default_directories);
-
- if ((handle_options(&argc, &saved_argv, my_long_options, get_one_option)))
- return ERR_INVALID_USAGE;
-
- if (!User_management::cmd &&
- (User_management::user_name || User_management::password))
- {
- fprintf(stderr,
- "--username and/or --password options have been specified, "
- "but no password-management command has been given.\n");
- return ERR_INVALID_USAGE;
- }
-
-#ifndef __WIN__
- if (Options::Daemon::run_as_service)
- {
- if (Options::Daemon::angel_pid_file_name == NULL)
- {
- /*
- Calculate angel pid file on the IM pid file basis: replace the
- extension (everything after the last dot) of the pid file basename to
- '.angel.pid'.
- */
-
- char *local_angel_pid_file_name;
- char *base_name_ptr;
- char *ext_ptr;
-
- local_angel_pid_file_name=
- (char *) malloc(strlen(Options::Main::pid_file_name) +
- ANGEL_PID_FILE_SUFFIX_LEN);
-
- strcpy(local_angel_pid_file_name, Options::Main::pid_file_name);
-
- base_name_ptr= strrchr(local_angel_pid_file_name, '/');
-
- if (!base_name_ptr)
- base_name_ptr= local_angel_pid_file_name + 1;
-
- ext_ptr= strrchr(base_name_ptr, '.');
- if (ext_ptr)
- *ext_ptr= 0;
-
- strcat(local_angel_pid_file_name, ANGEL_PID_FILE_SUFFIX);
-
- Options::Daemon::angel_pid_file_name= local_angel_pid_file_name;
- }
- else
- {
- Options::Daemon::angel_pid_file_name=
- strdup(Options::Daemon::angel_pid_file_name);
- }
- }
-#endif
-
- return 0;
-}
-
-void Options::cleanup()
-{
- if (saved_argv)
- free_defaults(saved_argv);
-
- delete User_management::cmd;
-
-#ifndef __WIN__
- if (Options::Daemon::run_as_service)
- free((void *) Options::Daemon::angel_pid_file_name);
-#endif
-}
-
-#ifdef __WIN__
-
-static int setup_windows_defaults()
-{
- char module_full_name[FN_REFLEN];
- char dir_name[FN_REFLEN];
- char base_name[FN_REFLEN];
- char im_name[FN_REFLEN];
- char *base_name_ptr;
- char *ptr;
-
- /* Determine dirname and basename. */
-
- if (!GetModuleFileName(NULL, module_full_name, sizeof (module_full_name)) ||
- !GetFullPathName(module_full_name, sizeof (dir_name), dir_name,
- &base_name_ptr))
- {
- return 1;
- }
-
- strmake(base_name, base_name_ptr, FN_REFLEN);
- *base_name_ptr= 0;
-
- strmake(im_name, base_name, FN_REFLEN);
- ptr= strrchr(im_name, '.');
-
- if (!ptr)
- return 1;
-
- *ptr= 0;
-
- /* Initialize the defaults. */
-
- strxmov(win_dflt_config_file_name, dir_name, DFLT_CONFIG_FILE_NAME, NullS);
- strxmov(win_dflt_mysqld_path, dir_name, DFLT_MYSQLD_PATH, NullS);
- strxmov(win_dflt_password_file_name, dir_name, im_name, DFLT_PASSWD_FILE_EXT,
- NullS);
- strxmov(win_dflt_pid_file_name, dir_name, im_name, DFLT_PID_FILE_EXT, NullS);
-
- return 0;
-}
-
-#endif
diff --git a/server-tools/instance-manager/options.h b/server-tools/instance-manager/options.h
deleted file mode 100644
index 5d4df51faae..00000000000
--- a/server-tools/instance-manager/options.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Copyright (C) 2003-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
-
-/*
- Options - all possible command-line options for the Instance Manager grouped
- in one struct.
-*/
-
-#include <my_global.h>
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-class User_management_cmd;
-
-struct Options
-{
- /*
- NOTE: handle_options() expects value of my_bool type for GET_BOOL
- accessor (i.e. bool must not be used).
- */
-
- struct User_management
- {
- static User_management_cmd *cmd;
-
- static char *user_name;
- static char *password;
- };
-
- struct Main
- {
- /* this is not an option parsed by handle_options(). */
- static bool is_forced_default_file;
-
- static const char *pid_file_name;
-#ifndef __WIN__
- static const char *socket_file_name;
-#endif
- static const char *password_file_name;
- static const char *default_mysqld_path;
- static uint monitoring_interval;
- static uint port_number;
- static const char *bind_address;
- static const char *config_file;
- static my_bool mysqld_safe_compatible;
- };
-
-#ifndef DBUG_OFF
- struct Debug
- {
- static const char *config_str;
- };
-#endif
-
-#ifndef __WIN__
-
- struct Daemon
- {
- static my_bool run_as_service;
- static const char *log_file_name;
- static const char *user;
- static const char *angel_pid_file_name;
- };
-
-#else
-
- struct Service
- {
- static my_bool install_as_service;
- static my_bool remove_service;
- static my_bool stand_alone;
- };
-
-#endif
-
-public:
- /* Array of paths to be passed to my_search_option_files() later */
- static const char **default_directories;
-
- static int load(int argc, char **argv);
- static void cleanup();
-
-private:
- Options(); /* Deny instantiation of this class. */
-
-private:
- /* argv pointer returned by load_defaults() to be used by free_defaults() */
- static char **saved_argv;
-};
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_OPTIONS_H
diff --git a/server-tools/instance-manager/parse.cc b/server-tools/instance-manager/parse.cc
deleted file mode 100644
index cd20e3bc7ab..00000000000
--- a/server-tools/instance-manager/parse.cc
+++ /dev/null
@@ -1,509 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 "parse.h"
-#include "commands.h"
-
-
-enum Token
-{
- TOK_CREATE= 0,
- TOK_DROP,
- TOK_ERROR, /* Encodes the "ERROR" word, it doesn't indicate error. */
- TOK_FILES,
- TOK_FLUSH,
- TOK_GENERAL,
- TOK_INSTANCE,
- TOK_INSTANCES,
- TOK_LOG,
- TOK_OPTIONS,
- TOK_SET,
- TOK_SLOW,
- TOK_START,
- TOK_STATUS,
- TOK_STOP,
- TOK_SHOW,
- TOK_UNSET,
- TOK_NOT_FOUND, // must be after all tokens
- TOK_END
-};
-
-
-struct tokens_st
-{
- uint length;
- const char *tok_name;
-};
-
-
-static struct tokens_st tokens[]= {
- {6, "CREATE"},
- {4, "DROP"},
- {5, "ERROR"},
- {5, "FILES"},
- {5, "FLUSH"},
- {7, "GENERAL"},
- {8, "INSTANCE"},
- {9, "INSTANCES"},
- {3, "LOG"},
- {7, "OPTIONS"},
- {3, "SET"},
- {4, "SLOW"},
- {5, "START"},
- {6, "STATUS"},
- {4, "STOP"},
- {4, "SHOW"},
- {5, "UNSET"}
-};
-
-/************************************************************************/
-
-Named_value_arr::Named_value_arr() :
- initialized(FALSE)
-{
-}
-
-
-bool Named_value_arr::init()
-{
- if (my_init_dynamic_array(&arr, sizeof(Named_value), 0, 32))
- return TRUE;
-
- initialized= TRUE;
-
- return FALSE;
-}
-
-
-Named_value_arr::~Named_value_arr()
-{
- if (!initialized)
- return;
-
- for (int i= 0; i < get_size(); ++i)
- get_element(i).free();
-
- delete_dynamic(&arr);
-}
-
-/************************************************************************/
-
-/*
- Returns token no if word corresponds to some token, otherwise returns
- TOK_NOT_FOUND
-*/
-
-inline Token find_token(const char *word, size_t word_len)
-{
- int i= 0;
- do
- {
- if (my_strnncoll(default_charset_info, (const uchar *) tokens[i].tok_name,
- tokens[i].length, (const uchar *) word, word_len) == 0)
- break;
- }
- while (++i < TOK_NOT_FOUND);
- return (Token) i;
-}
-
-
-Token get_token(const char **text, size_t *word_len)
-{
- get_word(text, word_len);
- if (*word_len)
- return find_token(*text, *word_len);
- return TOK_END;
-}
-
-
-Token shift_token(const char **text, size_t *word_len)
-{
- Token save= get_token(text, word_len);
- (*text)+= *word_len;
- return save;
-}
-
-
-int get_text_id(const char **text, LEX_STRING *token)
-{
- get_word(text, &token->length);
- if (token->length == 0)
- return 1;
- token->str= (char *) *text;
- return 0;
-}
-
-
-static bool parse_long(const LEX_STRING *token, long *value)
-{
- int err_code;
- char *end_ptr= token->str + token->length;
-
- *value= (long)my_strtoll10(token->str, &end_ptr, &err_code);
-
- return err_code != 0;
-}
-
-
-bool parse_option_value(const char *text, size_t *text_len, char **value)
-{
- char beginning_quote;
- const char *text_start_ptr;
- char *v;
- bool escape_mode= FALSE;
-
- if (!*text || (*text != '\'' && *text != '"'))
- return TRUE; /* syntax error: string expected. */
-
- beginning_quote= *text;
-
- ++text; /* skip the beginning quote. */
-
- text_start_ptr= text;
-
- if (!(v= Named_value::alloc_str(text)))
- return TRUE;
-
- *value= v;
-
- while (TRUE)
- {
- if (!*text)
- {
- Named_value::free_str(value);
- return TRUE; /* syntax error: missing terminating ' character. */
- }
-
- if (*text == '\n' || *text == '\r')
- {
- Named_value::free_str(value);
- return TRUE; /* syntax error: option value should be a single line. */
- }
-
- if (!escape_mode && *text == beginning_quote)
- break;
-
- if (escape_mode)
- {
- switch (*text)
- {
- case 'b': /* \b -- backspace */
- if (v > *value)
- --v;
- break;
-
- case 't': /* \t -- tab */
- *v= '\t';
- ++v;
- break;
-
- case 'n': /* \n -- newline */
- *v= '\n';
- ++v;
- break;
-
- case 'r': /* \r -- carriage return */
- *v= '\r';
- ++v;
- break;
-
- case '\\': /* \\ -- back slash */
- *v= '\\';
- ++v;
- break;
-
- case 's': /* \s -- space */
- *v= ' ';
- ++v;
- break;
-
- default: /* Unknown escape sequence. Treat as error. */
- Named_value::free_str(value);
- return TRUE;
- }
-
- escape_mode= FALSE;
- }
- else
- {
- if (*text == '\\')
- {
- escape_mode= TRUE;
- }
- else
- {
- *v= *text;
- ++v;
- }
- }
-
- ++text;
- }
-
- *v= 0;
-
- /* "2" below stands for beginning and ending quotes. */
- *text_len= text - text_start_ptr + 2;
-
- return FALSE;
-}
-
-
-void skip_spaces(const char **text)
-{
- while (**text && my_isspace(default_charset_info, **text))
- ++(*text);
-}
-
-
-Command *parse_command(const char *text)
-{
- size_t word_len;
- LEX_STRING instance_name;
- Command *command= 0;
-
- Token tok1= shift_token(&text, &word_len);
-
- switch (tok1) {
- case TOK_START: // fallthrough
- case TOK_STOP:
- case TOK_CREATE:
- case TOK_DROP:
- if (shift_token(&text, &word_len) != TOK_INSTANCE)
- goto syntax_error;
- get_word(&text, &word_len);
- if (word_len == 0)
- goto syntax_error;
- instance_name.str= (char *) text;
- instance_name.length= word_len;
- text+= word_len;
-
- if (tok1 == TOK_CREATE)
- {
- Create_instance *cmd= new Create_instance(&instance_name);
-
- if (!cmd)
- return NULL; /* Report ER_OUT_OF_RESOURCES. */
-
- if (cmd->init(&text))
- {
- delete cmd;
- goto syntax_error;
- }
-
- command= cmd;
- }
- else
- {
- /* it should be the end of command */
- get_word(&text, &word_len, NONSPACE);
- if (word_len)
- goto syntax_error;
- }
-
- switch (tok1) {
- case TOK_START:
- command= new Start_instance(&instance_name);
- break;
- case TOK_STOP:
- command= new Stop_instance(&instance_name);
- break;
- case TOK_CREATE:
- ; /* command already initialized. */
- break;
- case TOK_DROP:
- command= new Drop_instance(&instance_name);
- break;
- default: /* this is impossible, but nevertheless... */
- DBUG_ASSERT(0);
- }
- break;
- case TOK_FLUSH:
- if (shift_token(&text, &word_len) != TOK_INSTANCES)
- goto syntax_error;
-
- get_word(&text, &word_len, NONSPACE);
- if (word_len)
- goto syntax_error;
-
- command= new Flush_instances();
- break;
- case TOK_UNSET:
- case TOK_SET:
- {
- Abstract_option_cmd *cmd;
-
- if (tok1 == TOK_SET)
- cmd= new Set_option();
- else
- cmd= new Unset_option();
-
- if (!cmd)
- return NULL; /* Report ER_OUT_OF_RESOURCES. */
-
- if (cmd->init(&text))
- {
- delete cmd;
- goto syntax_error;
- }
-
- command= cmd;
-
- break;
- }
- case TOK_SHOW:
- switch (shift_token(&text, &word_len)) {
- case TOK_INSTANCES:
- get_word(&text, &word_len, NONSPACE);
- if (word_len)
- goto syntax_error;
- command= new Show_instances();
- break;
- case TOK_INSTANCE:
- switch (Token tok2= shift_token(&text, &word_len)) {
- case TOK_OPTIONS:
- case TOK_STATUS:
- if (get_text_id(&text, &instance_name))
- goto syntax_error;
- text+= instance_name.length;
- /* check that this is the end of the command */
- get_word(&text, &word_len, NONSPACE);
- if (word_len)
- goto syntax_error;
- if (tok2 == TOK_STATUS)
- command= new Show_instance_status(&instance_name);
- else
- command= new Show_instance_options(&instance_name);
- break;
- default:
- goto syntax_error;
- }
- break;
- default:
- instance_name.str= (char *) text - word_len;
- instance_name.length= word_len;
- if (instance_name.length)
- {
- Log_type log_type;
-
- long log_size;
- LEX_STRING log_size_str;
-
- long log_offset= 0;
- LEX_STRING log_offset_str= { NULL, 0 };
-
- switch (shift_token(&text, &word_len)) {
- case TOK_LOG:
- switch (Token tok3= shift_token(&text, &word_len)) {
- case TOK_FILES:
- get_word(&text, &word_len, NONSPACE);
- /* check that this is the end of the command */
- if (word_len)
- goto syntax_error;
- command= new Show_instance_log_files(&instance_name);
- break;
- case TOK_ERROR:
- case TOK_GENERAL:
- case TOK_SLOW:
- /* define a log type */
- switch (tok3) {
- case TOK_ERROR:
- log_type= IM_LOG_ERROR;
- break;
- case TOK_GENERAL:
- log_type= IM_LOG_GENERAL;
- break;
- case TOK_SLOW:
- log_type= IM_LOG_SLOW;
- break;
- default:
- goto syntax_error;
- }
- /* get the size of the log we want to retrieve */
- if (get_text_id(&text, &log_size_str))
- goto syntax_error;
- text+= log_size_str.length;
-
- /* this parameter is required */
- if (!log_size_str.length)
- goto syntax_error;
-
- /* the next token should be comma, or nothing */
- get_word(&text, &word_len);
- switch (*text) {
- case ',':
- text++; /* swallow the comma */
- /* read the next word */
- get_word(&text, &word_len);
- if (!word_len)
- goto syntax_error;
- log_offset_str.str= (char *) text;
- log_offset_str.length= word_len;
- text+= word_len;
- get_word(&text, &word_len, NONSPACE);
- /* check that this is the end of the command */
- if (word_len)
- goto syntax_error;
- break;
- case '\0':
- break; /* this is ok */
- default:
- goto syntax_error;
- }
-
- /* Parse size parameter. */
-
- if (parse_long(&log_size_str, &log_size))
- goto syntax_error;
-
- if (log_size <= 0)
- goto syntax_error;
-
- /* Parse offset parameter (if specified). */
-
- if (log_offset_str.length)
- {
- if (parse_long(&log_offset_str, &log_offset))
- goto syntax_error;
-
- if (log_offset <= 0)
- goto syntax_error;
- }
-
- command= new Show_instance_log(&instance_name,
- log_type, log_size, log_offset);
- break;
- default:
- goto syntax_error;
- }
- break;
- default:
- goto syntax_error;
- }
- }
- else
- goto syntax_error;
- break;
- }
- break;
- default:
-syntax_error:
- command= new Syntax_error();
- }
-
- DBUG_ASSERT(command);
-
- return command;
-}
diff --git a/server-tools/instance-manager/parse.h b/server-tools/instance-manager/parse.h
deleted file mode 100644
index 9c50ace5948..00000000000
--- a/server-tools/instance-manager/parse.h
+++ /dev/null
@@ -1,212 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 <my_sys.h>
-#include <m_string.h>
-
-class Command;
-
-enum Log_type
-{
- IM_LOG_ERROR= 0,
- IM_LOG_GENERAL,
- IM_LOG_SLOW
-};
-
-Command *parse_command(const char *text);
-
-bool parse_option_value(const char *text, size_t *text_len, char **value);
-
-void skip_spaces(const char **text);
-
-/* define kinds of the word seek method */
-enum enum_seek_method { ALPHANUM= 1, NONSPACE, OPTION_NAME };
-
-/************************************************************************/
-
-class Named_value
-{
-public:
- /*
- The purpose of these methods is just to have one method for
- allocating/deallocating memory for strings for Named_value.
- */
-
- static inline char *alloc_str(const LEX_STRING *str);
- static inline char *alloc_str(const char *str);
- static inline void free_str(char **str);
-
-public:
- inline Named_value();
- inline Named_value(char *name_arg, char *value_arg);
-
- inline char *get_name();
- inline char *get_value();
-
- inline void free();
-
-private:
- char *name;
- char *value;
-};
-
-inline char *Named_value::alloc_str(const LEX_STRING *str)
-{
- return my_strndup(str->str, str->length, MYF(0));
-}
-
-inline char *Named_value::alloc_str(const char *str)
-{
- return my_strdup(str, MYF(0));
-}
-
-inline void Named_value::free_str(char **str)
-{
- my_free(*str, MYF(MY_ALLOW_ZERO_PTR));
- *str= NULL;
-}
-
-inline Named_value::Named_value()
- :name(NULL), value(NULL)
-{ }
-
-inline Named_value::Named_value(char *name_arg, char *value_arg)
- :name(name_arg), value(value_arg)
-{ }
-
-inline char *Named_value::get_name()
-{
- return name;
-}
-
-inline char *Named_value::get_value()
-{
- return value;
-}
-
-void Named_value::free()
-{
- free_str(&name);
- free_str(&value);
-}
-
-/************************************************************************/
-
-class Named_value_arr
-{
-public:
- Named_value_arr();
- ~Named_value_arr();
-
- bool init();
-
- inline int get_size() const;
- inline Named_value get_element(int idx) const;
- inline void remove_element(int idx);
- inline bool add_element(Named_value *option);
- inline bool replace_element(int idx, Named_value *option);
-
-private:
- bool initialized;
- DYNAMIC_ARRAY arr;
-};
-
-
-inline int Named_value_arr::get_size() const
-{
- return arr.elements;
-}
-
-
-inline Named_value Named_value_arr::get_element(int idx) const
-{
- DBUG_ASSERT(0 <= idx && (uint) idx < arr.elements);
-
- Named_value option;
- get_dynamic((DYNAMIC_ARRAY *) &arr, (uchar*) &option, idx);
-
- return option;
-}
-
-
-inline void Named_value_arr::remove_element(int idx)
-{
- DBUG_ASSERT(0 <= idx && (uint) idx < arr.elements);
-
- get_element(idx).free();
-
- delete_dynamic_element(&arr, idx);
-}
-
-
-inline bool Named_value_arr::add_element(Named_value *option)
-{
- return insert_dynamic(&arr, (uchar*) option);
-}
-
-
-inline bool Named_value_arr::replace_element(int idx, Named_value *option)
-{
- DBUG_ASSERT(0 <= idx && (uint) idx < arr.elements);
-
- get_element(idx).free();
-
- return set_dynamic(&arr, (uchar*) option, idx);
-}
-
-/************************************************************************/
-
-/*
- tries to find next word in the text
- if found, returns the beginning and puts word length to word_len argument.
- if not found returns pointer to first non-space or to '\0', word_len == 0
-*/
-
-inline void get_word(const char **text, size_t *word_len,
- enum_seek_method seek_method= ALPHANUM)
-{
- const char *word_end;
-
- /* skip space */
- while (my_isspace(default_charset_info, **text))
- ++(*text);
-
- word_end= *text;
-
- switch (seek_method) {
- case ALPHANUM:
- while (my_isalnum(default_charset_info, *word_end))
- ++word_end;
- break;
- case NONSPACE:
- while (!my_isspace(default_charset_info, *word_end) &&
- (*word_end != '\0'))
- ++word_end;
- break;
- case OPTION_NAME:
- while (my_isalnum(default_charset_info, *word_end) ||
- *word_end == '-' ||
- *word_end == '_')
- ++word_end;
- break;
- }
-
- *word_len= (uint) (word_end - *text);
-}
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_H */
diff --git a/server-tools/instance-manager/parse_output.cc b/server-tools/instance-manager/parse_output.cc
deleted file mode 100644
index 3511589acd6..00000000000
--- a/server-tools/instance-manager/parse_output.cc
+++ /dev/null
@@ -1,407 +0,0 @@
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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 "parse_output.h"
-
-#include <my_global.h>
-#include <my_sys.h>
-#include <m_string.h>
-
-#include <stdio.h>
-
-#include "parse.h"
-#include "portability.h"
-
-/**************************************************************************
- Private module implementation.
-**************************************************************************/
-
-namespace { /* no-indent */
-
-/*************************************************************************/
-
-void trim_space(const char **text, uint *word_len)
-{
- const char *start= *text;
- while (*start != 0 && *start == ' ')
- start++;
- *text= start;
-
- int len= strlen(start);
- const char *end= start + len - 1;
- while (end > start && my_isspace(&my_charset_latin1, *end))
- end--;
- *word_len= (end - start)+1;
-}
-
-/*************************************************************************/
-
-/**
- @brief A facade to the internal workings of optaining the output from an
- executed system process.
-*/
-
-class Mysqld_output_parser
-{
-public:
- Mysqld_output_parser()
- { }
-
- virtual ~Mysqld_output_parser()
- { }
-
-public:
- bool parse(const char *command,
- const char *option_name_str,
- uint option_name_length,
- char *option_value_buf,
- size_t option_value_buf_size,
- enum_option_type option_type);
-
-protected:
- /**
- @brief Run a process and attach stdout- and stdin-pipes to it.
-
- @param command The path to the process to be executed
-
- @return Error status.
- @retval TRUE An error occurred
- @retval FALSE Operation was a success
- */
-
- virtual bool run_command(const char *command)= 0;
-
-
- /**
- @brief Read a sequence of bytes from the executed process' stdout pipe.
-
- The sequence is terminated by either '\0', LF or CRLF tokens. The
- terminating token is excluded from the result.
-
- @param line_buffer A pointer to a character buffer
- @param line_buffer_size The size of the buffer in bytes
-
- @return Error status.
- @retval TRUE An error occured
- @retval FALSE Operation was a success
- */
-
- virtual bool read_line(char *line_buffer,
- uint line_buffer_size)= 0;
-
-
- /**
- @brief Release any resources needed after a execution and parsing.
- */
-
- virtual bool cleanup()= 0;
-};
-
-/*************************************************************************/
-
-bool Mysqld_output_parser::parse(const char *command,
- const char *option_name_str,
- uint option_name_length,
- char *option_value_buf,
- size_t option_value_buf_size,
- enum_option_type option_type)
-{
- /* should be enough to store the string from the output */
- const int LINE_BUFFER_SIZE= 512;
- char line_buffer[LINE_BUFFER_SIZE];
-
- if (run_command(command))
- return TRUE;
-
- while (true)
- {
- if (read_line(line_buffer, LINE_BUFFER_SIZE))
- {
- cleanup();
- return TRUE;
- }
-
- uint found_word_len= 0;
- char *linep= line_buffer;
-
- line_buffer[sizeof(line_buffer) - 1]= '\0'; /* safety */
-
- /* Find the word(s) we are looking for in the line. */
-
- linep= strstr(linep, option_name_str);
-
- if (!linep)
- continue;
-
- linep+= option_name_length;
-
- switch (option_type)
- {
- case GET_VALUE:
- trim_space((const char**) &linep, &found_word_len);
-
- if (option_value_buf_size <= found_word_len)
- {
- cleanup();
- return TRUE;
- }
-
- strmake(option_value_buf, linep, found_word_len);
-
- break;
-
- case GET_LINE:
- strmake(option_value_buf, linep, option_value_buf_size - 1);
-
- break;
- }
-
- cleanup();
-
- return FALSE;
- }
-}
-
-/**************************************************************************
- Platform-specific implementation: UNIX.
-**************************************************************************/
-
-#ifndef __WIN__
-
-class Mysqld_output_parser_unix : public Mysqld_output_parser
-{
-public:
- Mysqld_output_parser_unix() :
- m_stdout(NULL)
- { }
-
-protected:
- virtual bool run_command(const char *command);
-
- virtual bool read_line(char *line_buffer,
- uint line_buffer_size);
-
- virtual bool cleanup();
-
-private:
- FILE *m_stdout;
-};
-
-bool Mysqld_output_parser_unix::run_command(const char *command)
-{
- if (!(m_stdout= popen(command, "r")))
- return TRUE;
-
- /*
- We want fully buffered stream. We also want system to allocate
- appropriate buffer.
- */
-
- setvbuf(m_stdout, NULL, _IOFBF, 0);
-
- return FALSE;
-}
-
-bool Mysqld_output_parser_unix::read_line(char *line_buffer,
- uint line_buffer_size)
-{
- char *retbuff = fgets(line_buffer, line_buffer_size, m_stdout);
- /* Remove any tailing new line charaters */
- if (line_buffer[line_buffer_size-1] == LF)
- line_buffer[line_buffer_size-1]= '\0';
- return (retbuff == NULL);
-}
-
-bool Mysqld_output_parser_unix::cleanup()
-{
- if (m_stdout)
- pclose(m_stdout);
-
- return FALSE;
-}
-
-#else /* Windows */
-
-/**************************************************************************
- Platform-specific implementation: Windows.
-**************************************************************************/
-
-class Mysqld_output_parser_win : public Mysqld_output_parser
-{
-public:
- Mysqld_output_parser_win() :
- m_internal_buffer(NULL),
- m_internal_buffer_offset(0),
- m_internal_buffer_size(0)
- { }
-
-protected:
- virtual bool run_command(const char *command);
- virtual bool read_line(char *line_buffer,
- uint line_buffer_size);
- virtual bool cleanup();
-
-private:
- HANDLE m_h_child_stdout_wr;
- HANDLE m_h_child_stdout_rd;
- uint m_internal_buffer_offset;
- uint m_internal_buffer_size;
- char *m_internal_buffer;
-};
-
-bool Mysqld_output_parser_win::run_command(const char *command)
-{
- BOOL op_status;
-
- SECURITY_ATTRIBUTES sa_attr;
- sa_attr.nLength= sizeof(SECURITY_ATTRIBUTES);
- sa_attr.bInheritHandle= TRUE;
- sa_attr.lpSecurityDescriptor= NULL;
-
- op_status= CreatePipe(&m_h_child_stdout_rd,
- &m_h_child_stdout_wr,
- &sa_attr,
- 0 /* Use system-default buffer size. */);
-
- if (!op_status)
- return TRUE;
-
- SetHandleInformation(m_h_child_stdout_rd, HANDLE_FLAG_INHERIT, 0);
-
- STARTUPINFO si_start_info;
- ZeroMemory(&si_start_info, sizeof(STARTUPINFO));
- si_start_info.cb= sizeof(STARTUPINFO);
- si_start_info.hStdError= m_h_child_stdout_wr;
- si_start_info.hStdOutput= m_h_child_stdout_wr;
- si_start_info.dwFlags|= STARTF_USESTDHANDLES;
-
- PROCESS_INFORMATION pi_proc_info;
-
- op_status= CreateProcess(NULL, /* Application name. */
- (char*)command, /* Command line. */
- NULL, /* Process security attributes. */
- NULL, /* Primary thread security attr.*/
- TRUE, /* Handles are inherited. */
- 0, /* Creation flags. */
- NULL, /* Use parent's environment. */
- NULL, /* Use parent's curr. directory. */
- &si_start_info, /* STARTUPINFO pointer. */
- &pi_proc_info); /* Rec. PROCESS_INFORMATION. */
-
- if (!op_status)
- {
- CloseHandle(m_h_child_stdout_rd);
- CloseHandle(m_h_child_stdout_wr);
-
- return TRUE;
- }
-
- /* Close unnessary handles. */
-
- CloseHandle(pi_proc_info.hProcess);
- CloseHandle(pi_proc_info.hThread);
-
- return FALSE;
-}
-
-bool Mysqld_output_parser_win::read_line(char *line_buffer,
- uint line_buffer_size)
-{
- DWORD dw_read_count= m_internal_buffer_size;
- bzero(line_buffer,line_buffer_size);
- char *buff_ptr= line_buffer;
- char ch;
-
- while ((unsigned)(buff_ptr - line_buffer) < line_buffer_size)
- {
- do
- {
- ReadFile(m_h_child_stdout_rd, &ch,
- 1, &dw_read_count, NULL);
- } while ((ch == CR || ch == LF) && buff_ptr == line_buffer);
-
- if (dw_read_count == 0)
- return TRUE;
-
- if (ch == CR || ch == LF)
- break;
-
- *buff_ptr++ = ch;
- }
-
- return FALSE;
-}
-
-bool Mysqld_output_parser_win::cleanup()
-{
- /* Close all handles. */
-
- CloseHandle(m_h_child_stdout_wr);
- CloseHandle(m_h_child_stdout_rd);
-
- return FALSE;
-}
-#endif
-
-/*************************************************************************/
-
-} /* End of private module implementation. */
-
-/*************************************************************************/
-
-/**
- @brief Parse output of the given command
-
- @param command The command to execute.
- @param option_name_str Option name.
- @param option_name_length Length of the option name.
- @param[out] option_value_buf The buffer to store option value.
- @param option_value_buf_size Size of the option value buffer.
- @param option_type Type of the option:
- - GET_LINE if we want to get all the
- line after the option name;
- - GET_VALUE otherwise.
-
- Execute the process by running "command". Find the "option name" and
- return the next word if "option_type" is GET_VALUE. Return the rest of
- the parsed string otherwise.
-
- @note This function has a separate windows implementation.
-
- @return The error status.
- @retval FALSE Ok, the option name has been found.
- @retval TRUE Error occured or the option name is not found.
-*/
-
-bool parse_output_and_get_value(const char *command,
- const char *option_name_str,
- uint option_name_length,
- char *option_value_buf,
- size_t option_value_buf_size,
- enum_option_type option_type)
-{
-#ifndef __WIN__
- Mysqld_output_parser_unix parser;
-#else /* __WIN__ */
- Mysqld_output_parser_win parser;
-#endif
-
- return parser.parse(command,
- option_name_str,
- option_name_length,
- option_value_buf,
- option_value_buf_size,
- option_type);
-}
diff --git a/server-tools/instance-manager/parse_output.h b/server-tools/instance-manager/parse_output.h
deleted file mode 100644
index 41618f643a3..00000000000
--- a/server-tools/instance-manager/parse_output.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H
-/* Copyright (C) 2004 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; 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>
-
-enum enum_option_type
-{
- GET_VALUE = 1,
- GET_LINE
-};
-
-bool parse_output_and_get_value(const char *command,
- const char *option_name_str,
- uint option_name_length,
- char *option_value_buf,
- size_t option_value_buf_size,
- enum_option_type option_type);
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PARSE_OUTPUT_H */
diff --git a/server-tools/instance-manager/portability.h b/server-tools/instance-manager/portability.h
deleted file mode 100644
index 990e6140a9e..00000000000
--- a/server-tools/instance-manager/portability.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Copyright (C) 2005-2006 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- 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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H
-
-#if (defined(_SCO_DS) || defined(UNIXWARE_7)) && !defined(SHUT_RDWR)
-/*
- SHUT_* functions are defined only if
- "(defined(_XOPEN_SOURCE) && _XOPEN_SOURCE_EXTENDED - 0 >= 1)"
-*/
-#define SHUT_RDWR 2
-#endif
-
-#ifdef __WIN__
-
-#define vsnprintf _vsnprintf
-#define snprintf _snprintf
-
-#define SIGKILL 9
-
-/*TODO: fix this */
-#define PROTOCOL_VERSION 10
-
-#define DFLT_CONFIG_FILE_NAME "my.ini"
-#define DFLT_MYSQLD_PATH "mysqld"
-#define DFLT_PASSWD_FILE_EXT ".passwd"
-#define DFLT_PID_FILE_EXT ".pid"
-#define DFLT_SOCKET_FILE_EXT ".sock"
-
-typedef int pid_t;
-
-#undef popen
-#define popen(A,B) _popen(A,B)
-
-#define NEWLINE "\r\n"
-#define NEWLINE_LEN 2
-
-const char CR = '\r';
-const char LF = '\n';
-
-#else /* ! __WIN__ */
-
-#define NEWLINE "\n"
-#define NEWLINE_LEN 1
-
-const char LF = '\n';
-
-#endif /* __WIN__ */
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PORTABILITY_H */
-
-
diff --git a/server-tools/instance-manager/priv.cc b/server-tools/instance-manager/priv.cc
deleted file mode 100644
index 74263934924..00000000000
--- a/server-tools/instance-manager/priv.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#include "priv.h"
-
-#include <my_global.h>
-#include <mysql_com.h>
-#include <my_sys.h>
-
-#include "log.h"
-
-/*
- The following string must be less then 80 characters, as
- mysql_connection.cc relies on it
-*/
-const LEX_STRING mysqlmanager_version= { C_STRING_WITH_LEN("1.0-beta") };
-
-const unsigned char protocol_version= PROTOCOL_VERSION;
-
-unsigned long net_buffer_length= 16384;
-
-unsigned long max_allowed_packet= 16384;
-
-unsigned long net_read_timeout= NET_WAIT_TIMEOUT; // same as in mysqld
-
-unsigned long net_write_timeout= 60; // same as in mysqld
-
-unsigned long net_retry_count= 10; // same as in mysqld
-
-/* needed by net_serv.cc */
-unsigned int test_flags= 0;
-unsigned long bytes_sent = 0L, bytes_received = 0L;
-unsigned long mysqld_net_retry_count = 10L;
-unsigned long open_files_limit;
-
-
-
-bool create_pid_file(const char *pid_file_name, int pid)
-{
- FILE *pid_file;
-
- if (!(pid_file= my_fopen(pid_file_name, O_WRONLY | O_CREAT | O_BINARY,
- MYF(0))))
- {
- log_error("Can not create pid file '%s': %s (errno: %d)",
- (const char *) pid_file_name,
- (const char *) strerror(errno),
- (int) errno);
- return TRUE;
- }
-
- if (fprintf(pid_file, "%d\n", (int) pid) <= 0)
- {
- log_error("Can not write to pid file '%s': %s (errno: %d)",
- (const char *) pid_file_name,
- (const char *) strerror(errno),
- (int) errno);
- return TRUE;
- }
-
- my_fclose(pid_file, MYF(0));
-
- return FALSE;
-}
diff --git a/server-tools/instance-manager/priv.h b/server-tools/instance-manager/priv.h
deleted file mode 100644
index 1c2124c0e77..00000000000
--- a/server-tools/instance-manager/priv.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H
-
-#include <my_global.h>
-#include <m_string.h>
-#include <my_pthread.h>
-
-#include <sys/types.h>
-
-#ifndef __WIN__
-#include <unistd.h>
-#endif
-
-#include "portability.h"
-
-/* IM-wide platform-independent defines */
-#define SERVER_DEFAULT_PORT MYSQL_PORT
-#define DEFAULT_MONITORING_INTERVAL 20
-#define DEFAULT_PORT 2273
-/* three-week timeout should be enough */
-#define LONG_TIMEOUT ((ulong) 3600L*24L*21L)
-
-const int MEM_ROOT_BLOCK_SIZE= 512;
-
-/* The maximal length of option name and option value. */
-const int MAX_OPTION_LEN= 1024;
-
-/*
- The maximal length of whole option string:
- --<option name>=<option value>
-*/
-const int MAX_OPTION_STR_LEN= 2 + MAX_OPTION_LEN + 1 + MAX_OPTION_LEN + 1;
-
-const int MAX_VERSION_LENGTH= 160;
-
-const int MAX_INSTANCE_NAME_SIZE= FN_REFLEN;
-
-extern const LEX_STRING mysqlmanager_version;
-
-/* MySQL client-server protocol version: substituted from configure */
-extern const unsigned char protocol_version;
-
-/*
- These variables are used in MySQL subsystem to work with mysql clients
- To be moved to a config file/options one day.
-*/
-
-
-/* Buffer length for TCP/IP and socket communication */
-extern unsigned long net_buffer_length;
-
-
-/* Maximum allowed incoming/ougoung packet length */
-extern unsigned long max_allowed_packet;
-
-
-/*
- Number of seconds to wait for more data from a connection before aborting
- the read
-*/
-extern unsigned long net_read_timeout;
-
-
-/*
- Number of seconds to wait for a block to be written to a connection
- before aborting the write.
-*/
-extern unsigned long net_write_timeout;
-
-
-/*
- If a read on a communication port is interrupted, retry this many times
- before giving up.
-*/
-extern unsigned long net_retry_count;
-
-extern unsigned int test_flags;
-extern unsigned long bytes_sent, bytes_received;
-extern unsigned long mysqld_net_retry_count;
-extern unsigned long open_files_limit;
-
-bool create_pid_file(const char *pid_file_name, int pid);
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_PRIV_H
diff --git a/server-tools/instance-manager/protocol.cc b/server-tools/instance-manager/protocol.cc
deleted file mode 100644
index 8d71fcb8026..00000000000
--- a/server-tools/instance-manager/protocol.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#include "protocol.h"
-
-#include "messages.h"
-
-#include <mysql_com.h>
-#include <m_string.h>
-
-
-static uchar eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
-static const char ERROR_PACKET_CODE= (char) 255;
-
-
-int net_send_ok(struct st_net *net, unsigned long connection_id,
- const char *message)
-{
- /*
- The format of a packet
- 1 packet type code
- 1-9 affected rows count
- 1-9 connection id
- 2 thread return status
- 2 warning count
- 1-9 + message length message to send (isn't stored if no message)
- */
- Buffer buff;
- uchar *pos= buff.buffer;
-
- /* check that we have space to hold mandatory fields */
- buff.reserve(0, 23);
-
- enum { OK_PACKET_CODE= 0 };
- *pos++= OK_PACKET_CODE;
- pos= net_store_length(pos, (ulonglong) 0);
- pos= net_store_length(pos, (ulonglong) connection_id);
- int2store(pos, *net->return_status);
- pos+= 2;
- /* We don't support warnings, so store 0 for total warning count */
- int2store(pos, 0);
- pos+= 2;
-
- size_t position= pos - buff.buffer; /* we might need it for message */
-
- if (message != NULL)
- {
- buff.reserve(position, 9 + strlen(message));
- store_to_protocol_packet(&buff, message, &position);
- }
-
- return my_net_write(net, buff.buffer, position) || net_flush(net);
-}
-
-
-int net_send_error(struct st_net *net, uint sql_errno)
-{
- const char *err= message(sql_errno);
- char buff[1 + // packet type code
- 2 + // sql error number
- 1 + SQLSTATE_LENGTH + // sql state
- MYSQL_ERRMSG_SIZE]; // message
- char *pos= buff;
-
- *pos++= ERROR_PACKET_CODE;
- int2store(pos, sql_errno);
- pos+= 2;
- /* The first # is to make the protocol backward compatible */
- *pos++= '#';
- memcpy(pos, errno_to_sqlstate(sql_errno), SQLSTATE_LENGTH);
- pos+= SQLSTATE_LENGTH;
- pos= strmake(pos, err, MYSQL_ERRMSG_SIZE - 1) + 1;
- return (my_net_write(net, (uchar*) buff, (size_t) (pos - buff)) ||
- net_flush(net));
-}
-
-
-int net_send_error_323(struct st_net *net, uint sql_errno)
-{
- const char *err= message(sql_errno);
- char buff[1 + // packet type code
- 2 + // sql error number
- MYSQL_ERRMSG_SIZE]; // message
- char *pos= buff;
-
- *pos++= ERROR_PACKET_CODE;
- int2store(pos, sql_errno);
- pos+= 2;
- pos= strmake(pos, err, MYSQL_ERRMSG_SIZE - 1) + 1;
- return (my_net_write(net, (uchar*) buff, (size_t) (pos - buff)) ||
- net_flush(net));
-}
-
-char *net_store_length(char *pkg, uint length)
-{
- uchar *packet=(uchar*) pkg;
- if (length < 251)
- {
- *packet=(uchar) length;
- return (char*) packet+1;
- }
- *packet++=252;
- int2store(packet,(uint) length);
- return (char*) packet+2;
-}
-
-
-int store_to_protocol_packet(Buffer *buf, const char *string, size_t *position,
- size_t string_len)
-{
- uint currpos;
-
- /* reserve max amount of bytes needed to store length */
- if (buf->reserve(*position, 9))
- goto err;
- currpos= (net_store_length(buf->buffer + *position,
- (ulonglong) string_len) - buf->buffer);
- if (buf->append(currpos, string, string_len))
- goto err;
- *position= *position + string_len + (currpos - *position);
-
- return 0;
-err:
- return 1;
-}
-
-
-int store_to_protocol_packet(Buffer *buf, const char *string,
- size_t *position)
-{
- size_t string_len;
-
- string_len= strlen(string);
- return store_to_protocol_packet(buf, string, position, string_len);
-}
-
-
-int send_eof(struct st_net *net)
-{
- uchar buff[1 + /* eof packet code */
- 2 + /* warning count */
- 2]; /* server status */
-
- buff[0]=254;
- int2store(buff+1, 0);
- int2store(buff+3, 0);
- return my_net_write(net, buff, sizeof(buff));
-}
-
-
-int send_fields(struct st_net *net, LIST *fields)
-{
- LIST *tmp= fields;
- Buffer send_buff;
- uchar small_buff[4];
- size_t position= 0;
- LEX_STRING *field;
-
- /* send the number of fileds */
- net_store_length(small_buff, (uint) list_length(fields));
- if (my_net_write(net, small_buff, (uint) 1))
- goto err;
-
- while (tmp)
- {
- position= 0;
- field= (LEX_STRING *) tmp->data;
-
- store_to_protocol_packet(&send_buff,
- (char*) "", &position); /* catalog name */
- store_to_protocol_packet(&send_buff,
- (char*) "", &position); /* db name */
- store_to_protocol_packet(&send_buff,
- (char*) "", &position); /* table name */
- store_to_protocol_packet(&send_buff,
- (char*) "", &position); /* table name alias */
- store_to_protocol_packet(&send_buff,
- field->str, &position); /* column name */
- store_to_protocol_packet(&send_buff,
- field->str, &position); /* column name alias */
- send_buff.reserve(position, 12);
- if (send_buff.is_error())
- goto err;
- send_buff.buffer[position++]= 12;
- int2store(send_buff.buffer + position, 1); /* charsetnr */
- int4store(send_buff.buffer + position + 2,
- field->length); /* field length */
- send_buff.buffer[position+6]= (char) MYSQL_TYPE_STRING; /* type */
- int2store(send_buff.buffer + position + 7, 0); /* flags */
- send_buff.buffer[position + 9]= (char) 0; /* decimals */
- send_buff.buffer[position + 10]= 0;
- send_buff.buffer[position + 11]= 0;
- position+= 12;
- if (my_net_write(net, send_buff.buffer, (uint) position+1))
- goto err;
- tmp= list_rest(tmp);
- }
-
- if (my_net_write(net, eof_buff, 1))
- goto err;
- return 0;
-
-err:
- return 1;
-}
diff --git a/server-tools/instance-manager/protocol.h b/server-tools/instance-manager/protocol.h
deleted file mode 100644
index b06ae4dfdb2..00000000000
--- a/server-tools/instance-manager/protocol.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H
-
-#include "buffer.h"
-
-#include <my_list.h>
-
-/* default field length to be used in various field-realted functions */
-enum { DEFAULT_FIELD_LENGTH= 20 };
-
-struct st_net;
-
-int net_send_ok(struct st_net *net, unsigned long connection_id,
- const char *message);
-
-int net_send_error(struct st_net *net, unsigned sql_errno);
-
-int net_send_error_323(struct st_net *net, unsigned sql_errno);
-
-int send_fields(struct st_net *net, LIST *fields);
-
-char *net_store_length(char *pkg, uint length);
-
-int store_to_protocol_packet(Buffer *buf, const char *string,
- size_t *position);
-
-int store_to_protocol_packet(Buffer *buf, const char *string, size_t *position,
- size_t string_len);
-
-int send_eof(struct st_net *net);
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_PROTOCOL_H */
diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc
deleted file mode 100644
index 489caa0aaa8..00000000000
--- a/server-tools/instance-manager/thread_registry.cc
+++ /dev/null
@@ -1,419 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "thread_registry.h"
-#include <thr_alarm.h>
-#include <signal.h>
-#include "log.h"
-
-#ifndef __WIN__
-/* Kick-off signal handler */
-
-enum { THREAD_KICK_OFF_SIGNAL= SIGUSR2 };
-
-extern "C" void handle_signal(int);
-
-void handle_signal(int __attribute__((unused)) sig_no)
-{
-}
-#endif
-
-/* Thread_info initializer methods */
-
-void Thread_info::init(bool send_signal_on_shutdown_arg)
-{
- thread_id= pthread_self();
- send_signal_on_shutdown= send_signal_on_shutdown_arg;
-}
-
-/*
- TODO: think about moving signal information (now it's shutdown_in_progress)
- to Thread_info. It will reduce contention and allow signal deliverence to
- a particular thread, not to the whole worker crew
-*/
-
-Thread_registry::Thread_registry() :
- shutdown_in_progress(FALSE)
- ,sigwait_thread_pid(pthread_self())
- ,error_status(FALSE)
-{
- pthread_mutex_init(&LOCK_thread_registry, 0);
- pthread_cond_init(&COND_thread_registry_is_empty, 0);
-
- /* head is used by-value to simplify nodes inserting */
- head.next= head.prev= &head;
-}
-
-
-Thread_registry::~Thread_registry()
-{
- /* Check that no one uses the repository. */
- pthread_mutex_lock(&LOCK_thread_registry);
-
- for (Thread_info *ti= head.next; ti != &head; ti= ti->next)
- {
- log_error("Thread_registry: unregistered thread: %lu.",
- (unsigned long) ti->thread_id);
- }
-
- /* All threads must unregister */
- DBUG_ASSERT(head.next == &head);
-
- pthread_mutex_unlock(&LOCK_thread_registry);
- pthread_cond_destroy(&COND_thread_registry_is_empty);
- pthread_mutex_destroy(&LOCK_thread_registry);
-}
-
-
-/*
- Set signal handler for kick-off thread, and insert a thread info to the
- repository. New node is appended to the end of the list; head.prev always
- points to the last node.
-*/
-
-void Thread_registry::register_thread(Thread_info *info,
- bool send_signal_on_shutdown)
-{
- info->init(send_signal_on_shutdown);
-
- DBUG_PRINT("info", ("Thread_registry: registering thread %lu...",
- (unsigned long) info->thread_id));
-
-#ifndef __WIN__
- struct sigaction sa;
- sa.sa_handler= handle_signal;
- sa.sa_flags= 0;
- sigemptyset(&sa.sa_mask);
- sigaction(THREAD_KICK_OFF_SIGNAL, &sa, 0);
-#endif
- info->current_cond= 0;
-
- pthread_mutex_lock(&LOCK_thread_registry);
- info->next= &head;
- info->prev= head.prev;
- head.prev->next= info;
- head.prev= info;
- pthread_mutex_unlock(&LOCK_thread_registry);
-}
-
-
-/*
- Unregister a thread from the repository and free Thread_info structure.
- Every registered thread must unregister. Unregistering should be the last
- thing a thread is doing, otherwise it could have no time to finalize.
-*/
-
-void Thread_registry::unregister_thread(Thread_info *info)
-{
- DBUG_PRINT("info", ("Thread_registry: unregistering thread %lu...",
- (unsigned long) info->thread_id));
-
- pthread_mutex_lock(&LOCK_thread_registry);
- info->prev->next= info->next;
- info->next->prev= info->prev;
-
- if (head.next == &head)
- {
- DBUG_PRINT("info", ("Thread_registry: thread registry is empty!"));
- pthread_cond_signal(&COND_thread_registry_is_empty);
- }
-
- pthread_mutex_unlock(&LOCK_thread_registry);
-}
-
-
-/*
- Check whether shutdown is in progress, and if yes, return immediately.
- Else set info->current_cond and call pthread_cond_wait. When
- pthread_cond_wait returns, unregister current cond and check the shutdown
- status again.
- RETURN VALUE
- return value from pthread_cond_wait
-*/
-
-int Thread_registry::cond_wait(Thread_info *info, pthread_cond_t *cond,
- pthread_mutex_t *mutex)
-{
- pthread_mutex_lock(&LOCK_thread_registry);
- if (shutdown_in_progress)
- {
- pthread_mutex_unlock(&LOCK_thread_registry);
- return 0;
- }
- info->current_cond= cond;
- pthread_mutex_unlock(&LOCK_thread_registry);
- /* sic: race condition here, cond can be signaled in deliver_shutdown */
- int rc= pthread_cond_wait(cond, mutex);
- pthread_mutex_lock(&LOCK_thread_registry);
- info->current_cond= 0;
- pthread_mutex_unlock(&LOCK_thread_registry);
- return rc;
-}
-
-
-int Thread_registry::cond_timedwait(Thread_info *info, pthread_cond_t *cond,
- pthread_mutex_t *mutex,
- struct timespec *wait_time)
-{
- int rc;
- pthread_mutex_lock(&LOCK_thread_registry);
- if (shutdown_in_progress)
- {
- pthread_mutex_unlock(&LOCK_thread_registry);
- return 0;
- }
- info->current_cond= cond;
- pthread_mutex_unlock(&LOCK_thread_registry);
- /* sic: race condition here, cond can be signaled in deliver_shutdown */
- if ((rc= pthread_cond_timedwait(cond, mutex, wait_time)) == ETIME)
- rc= ETIMEDOUT; // For easier usage
- pthread_mutex_lock(&LOCK_thread_registry);
- info->current_cond= 0;
- pthread_mutex_unlock(&LOCK_thread_registry);
- return rc;
-}
-
-
-/*
- Deliver shutdown message to the workers crew.
- As it's impossible to avoid all race conditions, signal latecomers
- again.
-*/
-
-void Thread_registry::deliver_shutdown()
-{
- pthread_mutex_lock(&LOCK_thread_registry);
- shutdown_in_progress= TRUE;
-
-#ifndef __WIN__
- /* to stop reading from the network we need to flush alarm queue */
- end_thr_alarm(0);
- /*
- We have to deliver final alarms this way, as the main thread has already
- stopped alarm processing.
- */
- process_alarm(THR_SERVER_ALARM);
-#endif
-
- /*
- sic: race condition here, the thread may not yet fall into
- pthread_cond_wait.
- */
-
- interrupt_threads();
-
- wait_for_threads_to_unregister();
-
- /*
- If previous signals did not reach some threads, they must be sleeping
- in pthread_cond_wait or in a blocking syscall. Wake them up:
- every thread shall check signal variables after each syscall/cond_wait,
- so this time everybody should be informed (presumably each worker can
- get CPU during shutdown_time.)
- */
-
- interrupt_threads();
-
- /* Get the last chance to threads to stop. */
-
- wait_for_threads_to_unregister();
-
-#ifndef DBUG_OFF
- /*
- Print out threads, that didn't stopped. Thread_registry destructor will
- probably abort the program if there is still any alive thread.
- */
-
- if (head.next != &head)
- {
- DBUG_PRINT("info", ("Thread_registry: non-stopped threads:"));
-
- for (Thread_info *info= head.next; info != &head; info= info->next)
- DBUG_PRINT("info", (" - %lu", (unsigned long) info->thread_id));
- }
- else
- {
- DBUG_PRINT("info", ("Thread_registry: all threads stopped."));
- }
-#endif // DBUG_OFF
-
- pthread_mutex_unlock(&LOCK_thread_registry);
-}
-
-
-void Thread_registry::request_shutdown()
-{
- pthread_kill(sigwait_thread_pid, SIGTERM);
-}
-
-
-void Thread_registry::interrupt_threads()
-{
- for (Thread_info *info= head.next; info != &head; info= info->next)
- {
- if (!info->send_signal_on_shutdown)
- continue;
-
- pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL);
- if (info->current_cond)
- pthread_cond_signal(info->current_cond);
- }
-}
-
-
-void Thread_registry::wait_for_threads_to_unregister()
-{
- struct timespec shutdown_time;
-
- set_timespec(shutdown_time, 1);
-
- DBUG_PRINT("info", ("Thread_registry: joining threads..."));
-
- while (true)
- {
- if (head.next == &head)
- {
- DBUG_PRINT("info", ("Thread_registry: emptied."));
- return;
- }
-
- int error= pthread_cond_timedwait(&COND_thread_registry_is_empty,
- &LOCK_thread_registry,
- &shutdown_time);
-
- if (error == ETIMEDOUT || error == ETIME)
- {
- DBUG_PRINT("info", ("Thread_registry: threads shutdown timed out."));
- return;
- }
- }
-}
-
-
-/*********************************************************************
- class Thread
-*********************************************************************/
-
-#if defined(__ia64__) || defined(__ia64)
-/*
- We can live with 32K, but reserve 64K. Just to be safe.
- On ia64 we need to reserve double of the size.
-*/
-#define IM_THREAD_STACK_SIZE (128*1024L)
-#else
-#define IM_THREAD_STACK_SIZE (64*1024)
-#endif
-
-/*
- Change the stack size and start a thread. Return an error if either
- pthread_attr_setstacksize or pthread_create fails.
- Arguments are the same as for pthread_create().
-*/
-
-static
-int set_stacksize_and_create_thread(pthread_t *thread, pthread_attr_t *attr,
- void *(*start_routine)(void *), void *arg)
-{
- int rc= 0;
-
-#ifndef __WIN__
-#ifndef PTHREAD_STACK_MIN
-#define PTHREAD_STACK_MIN 32768
-#endif
- /*
- Set stack size to be safe on the platforms with too small
- default thread stack.
- */
- rc= pthread_attr_setstacksize(attr,
- (size_t) (PTHREAD_STACK_MIN +
- IM_THREAD_STACK_SIZE));
-#endif
- if (!rc)
- rc= pthread_create(thread, attr, start_routine, arg);
- return rc;
-}
-
-
-Thread::~Thread()
-{
-}
-
-
-void *Thread::thread_func(void *arg)
-{
- Thread *thread= (Thread *) arg;
- my_thread_init();
-
- thread->run();
-
- my_thread_end();
- return NULL;
-}
-
-
-bool Thread::start(enum_thread_type thread_type)
-{
- pthread_attr_t attr;
- int rc;
-
- pthread_attr_init(&attr);
-
- if (thread_type == DETACHED)
- {
- detached = TRUE;
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- }
- else
- {
- detached = FALSE;
- }
-
- rc= set_stacksize_and_create_thread(&id, &attr, Thread::thread_func, this);
- pthread_attr_destroy(&attr);
-
- return rc != 0;
-}
-
-
-bool Thread::join()
-{
- DBUG_ASSERT(!detached);
-
- return pthread_join(id, NULL) != 0;
-}
-
-
-int Thread_registry::get_error_status()
-{
- int ret_error_status;
-
- pthread_mutex_lock(&LOCK_thread_registry);
- ret_error_status= error_status;
- pthread_mutex_unlock(&LOCK_thread_registry);
-
- return ret_error_status;
-}
-
-
-void Thread_registry::set_error_status()
-{
- pthread_mutex_lock(&LOCK_thread_registry);
- error_status= TRUE;
- pthread_mutex_unlock(&LOCK_thread_registry);
-}
diff --git a/server-tools/instance-manager/thread_registry.h b/server-tools/instance-manager/thread_registry.h
deleted file mode 100644
index d04c8442e44..00000000000
--- a/server-tools/instance-manager/thread_registry.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_THREAD_REGISTRY_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_THREAD_REGISTRY_H
-
-/*
- A multi-threaded application shall nicely work with signals.
-
- This means it shall, first of all, shut down nicely on ``quit'' signals:
- stop all running threads, cleanup and exit.
-
- Note, that a thread can't be shut down nicely if it doesn't want to be.
- That's why to perform clean shutdown, all threads constituting a process
- must observe certain rules. Here we use the rules, described in Butenhof
- book 'Programming with POSIX threads', namely:
- - all user signals are handled in 'signal thread' in synchronous manner
- (by means of sigwait). To guarantee that the signal thread is the only who
- can receive user signals, all threads block them, and signal thread is
- the only who calls sigwait() with an apporpriate sigmask.
- To propogate a signal to the workers the signal thread sets
- a variable, corresponding to the signal. Additionally the signal thread
- sends each worker an internal signal (by means of pthread_kill) to kick it
- out from possible blocking syscall, and possibly pthread_cond_signal if
- some thread is blocked in pthread_cond_[timed]wait.
- - a worker handles only internal 'kick' signal (the handler does nothing).
- In case when a syscall returns 'EINTR' the worker checks all
- signal-related variables and behaves accordingly.
- Also these variables shall be checked from time to time in long
- CPU-bounded operations, and before/after pthread_cond_wait. (It's supposed
- that a worker thread either waits in a syscall/conditional variable, or
- computes something.)
- - to guarantee signal deliverence, there should be some kind of feedback,
- e. g. all workers shall account in the signal thread Thread Repository and
- unregister from it on exit.
-
- Configuration reload (on SIGHUP) and thread timeouts/alarms can be handled
- in manner, similar to ``quit'' signals.
-*/
-
-#include <my_global.h>
-#include <my_pthread.h>
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-/**
- Thread_info - repository entry for each worker thread
- All entries comprise double-linked list like:
- 0 -- entry -- entry -- entry - 0
- Double-linked list is used to unregister threads easy.
-*/
-
-class Thread_info
-{
-public:
- Thread_info() {}
- friend class Thread_registry;
-private:
- void init(bool send_signal_on_shutdown);
-private:
- pthread_cond_t *current_cond;
- Thread_info *prev, *next;
- pthread_t thread_id;
- bool send_signal_on_shutdown;
-};
-
-
-/**
- A base class for a detached thread.
-*/
-
-class Thread
-{
-public:
- enum enum_thread_type
- {
- DETACHED,
- JOINABLE
- };
-public:
- Thread()
- { }
-
-public:
- inline bool is_detached() const;
-
- bool start(enum_thread_type thread_type = JOINABLE);
- bool join();
-
-protected:
- virtual void run()= 0;
- virtual ~Thread();
-
-private:
- pthread_t id;
- bool detached;
-
-private:
- static void *thread_func(void *arg);
-
-private:
- Thread(const Thread & /* rhs */); /* not implemented */
- Thread &operator=(const Thread & /* rhs */); /* not implemented */
-};
-
-inline bool Thread::is_detached() const
-{
- return detached;
-}
-
-
-/**
- Thread_registry - contains handles for each worker thread to deliver
- signal information to workers.
-*/
-
-class Thread_registry
-{
-public:
- Thread_registry();
- ~Thread_registry();
-
- void register_thread(Thread_info *info, bool send_signal_on_shutdown= TRUE);
- void unregister_thread(Thread_info *info);
- void deliver_shutdown();
- void request_shutdown();
- inline bool is_shutdown();
- int cond_wait(Thread_info *info, pthread_cond_t *cond,
- pthread_mutex_t *mutex);
- int cond_timedwait(Thread_info *info, pthread_cond_t *cond,
- pthread_mutex_t *mutex, struct timespec *wait_time);
- int get_error_status();
- void set_error_status();
-
-private:
- void interrupt_threads();
- void wait_for_threads_to_unregister();
-
-private:
- Thread_info head;
- bool shutdown_in_progress;
- pthread_mutex_t LOCK_thread_registry;
- pthread_cond_t COND_thread_registry_is_empty;
- pthread_t sigwait_thread_pid;
- bool error_status;
-
-private:
- Thread_registry(const Thread_registry &);
- Thread_registry &operator =(const Thread_registry &);
-};
-
-
-inline bool Thread_registry::is_shutdown()
-{
- pthread_mutex_lock(&LOCK_thread_registry);
- bool res= shutdown_in_progress;
- pthread_mutex_unlock(&LOCK_thread_registry);
- return res;
-}
-
-
-#endif /* INCLUDES_MYSQL_INSTANCE_MANAGER_THREAD_REGISTRY_H */
diff --git a/server-tools/instance-manager/user_management_commands.cc b/server-tools/instance-manager/user_management_commands.cc
deleted file mode 100644
index 2eb0ae30aa5..00000000000
--- a/server-tools/instance-manager/user_management_commands.cc
+++ /dev/null
@@ -1,421 +0,0 @@
-/* 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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "user_management_commands.h"
-
-#include "exit_codes.h"
-#include "options.h"
-#include "user_map.h"
-
-/*************************************************************************
- Module-specific (internal) functions.
-*************************************************************************/
-
-/*
- The function returns user name. The user name is retrieved from command-line
- options (if specified) or from console.
-
- NOTE
- This function must not be used in user-management command implementations.
- Use get_user_name() instead.
-
- SYNOPSIS
- get_user_name_impl()
-
- RETURN
- NULL on error
- valid pointer on success
-*/
-
-static char *get_user_name_impl()
-{
- static char user_name_buf[1024];
- char *ptr;
-
- if (Options::User_management::user_name)
- return Options::User_management::user_name;
-
- printf("Enter user name: ");
- fflush(stdout);
-
- if (!fgets(user_name_buf, sizeof (user_name_buf), stdin))
- return NULL;
-
- if ((ptr= strchr(user_name_buf, '\n')))
- *ptr= 0;
-
- if ((ptr= strchr(user_name_buf, '\r')))
- *ptr= 0;
-
- return user_name_buf;
-}
-
-
-/*
- The function is intended to provide user name for user-management
- operations. It also checks that length of the specified user name is correct
- (not empty, not exceeds USERNAME_LENGTH). Report to stderr if something is
- wrong.
-
- SYNOPSIS
- get_user_name()
- user_name [OUT] on success contains user name
-
- RETURN
- TRUE on error
- FALSE on success
-*/
-
-static bool get_user_name(LEX_STRING *user_name)
-{
- char *user_name_str= get_user_name_impl();
-
- if (!user_name_str)
- {
- fprintf(stderr, "Error: unable to read user name from stdin.\n");
- return TRUE;
- }
-
- user_name->str= user_name_str;
- user_name->length= strlen(user_name->str);
-
- if (user_name->length == 0)
- {
- fprintf(stderr, "Error: user name can not be empty.\n");
- return TRUE;
- }
-
- if (user_name->length > USERNAME_LENGTH)
- {
- fprintf(stderr, "Error: user name must not exceed %d characters.\n",
- (int) USERNAME_LENGTH);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/*
- The function is intended to provide password for user-management operations.
- The password is retrieved from command-line options (if specified) or from
- console.
-
- SYNOPSIS
- get_password()
-
- RETURN
- NULL on error
- valid pointer on success
-*/
-
-static const char *get_password()
-{
- if (Options::User_management::password)
- return Options::User_management::password;
-
- const char *passwd1= get_tty_password("Enter password: ");
- const char *passwd2= get_tty_password("Re-type password: ");
-
- if (strcmp(passwd1, passwd2))
- {
- fprintf(stderr, "Error: passwords do not match.\n");
- return 0;
- }
-
- return passwd1;
-}
-
-
-/*
- Load password file into user map.
-
- SYNOPSIS
- load_password_file()
- user_map target user map
-
- RETURN
- See exit_codes.h for possible values.
-*/
-
-static int load_password_file(User_map *user_map)
-{
- int err_code;
- const char *err_msg;
-
- if (user_map->init())
- {
- fprintf(stderr, "Error: can not initialize user map.\n");
- return ERR_OUT_OF_MEMORY;
- }
-
- if ((err_code= user_map->load(Options::Main::password_file_name, &err_msg)))
- fprintf(stderr, "Error: %s.\n", (const char *) err_msg);
-
- return err_code;
-}
-
-
-/*
- Save user map into password file.
-
- SYNOPSIS
- save_password_file()
- user_map user map
-
- RETURN
- See exit_codes.h for possible values.
-*/
-
-static int save_password_file(User_map *user_map)
-{
- int err_code;
- const char *err_msg;
-
- if ((err_code= user_map->save(Options::Main::password_file_name, &err_msg)))
- fprintf(stderr, "Error: %s.\n", (const char *) err_msg);
-
- return err_code;
-}
-
-/*************************************************************************
- Print_password_line_cmd
-*************************************************************************/
-
-int Print_password_line_cmd::execute()
-{
- LEX_STRING user_name;
- const char *password;
-
- printf("Creating record for new user.\n");
-
- if (get_user_name(&user_name))
- return ERR_CAN_NOT_READ_USER_NAME;
-
- if (!(password= get_password()))
- return ERR_CAN_NOT_READ_PASSWORD;
-
- {
- User user(&user_name, password);
-
- printf("%s:%s\n",
- (const char *) user.user,
- (const char *) user.scrambled_password);
- }
-
- return ERR_OK;
-}
-
-
-/*************************************************************************
- Add_user_cmd
-*************************************************************************/
-
-int Add_user_cmd::execute()
-{
- LEX_STRING user_name;
- const char *password;
-
- User_map user_map;
- User *new_user;
-
- int err_code;
-
- if (get_user_name(&user_name))
- return ERR_CAN_NOT_READ_USER_NAME;
-
- /* Load the password file. */
-
- if ((err_code= load_password_file(&user_map)) != ERR_OK)
- return err_code;
-
- /* Check that the user does not exist. */
-
- if (user_map.find_user(&user_name))
- {
- fprintf(stderr, "Error: user '%s' already exists.\n",
- (const char *) user_name.str);
- return ERR_USER_ALREADY_EXISTS;
- }
-
- /* Add the user. */
-
- if (!(password= get_password()))
- return ERR_CAN_NOT_READ_PASSWORD;
-
- if (!(new_user= new User(&user_name, password)))
- return ERR_OUT_OF_MEMORY;
-
- if (user_map.add_user(new_user))
- {
- delete new_user;
- return ERR_OUT_OF_MEMORY;
- }
-
- /* Save the password file. */
-
- return save_password_file(&user_map);
-}
-
-
-/*************************************************************************
- Drop_user_cmd
-*************************************************************************/
-
-int Drop_user_cmd::execute()
-{
- LEX_STRING user_name;
-
- User_map user_map;
- User *user;
-
- int err_code;
-
- if (get_user_name(&user_name))
- return ERR_CAN_NOT_READ_USER_NAME;
-
- /* Load the password file. */
-
- if ((err_code= load_password_file(&user_map)) != ERR_OK)
- return err_code;
-
- /* Find the user. */
-
- user= user_map.find_user(&user_name);
-
- if (!user)
- {
- fprintf(stderr, "Error: user '%s' does not exist.\n",
- (const char *) user_name.str);
- return ERR_USER_NOT_FOUND;
- }
-
- /* Remove the user (ignore possible errors). */
-
- user_map.remove_user(user);
-
- /* Save the password file. */
-
- return save_password_file(&user_map);
-}
-
-
-/*************************************************************************
- Edit_user_cmd
-*************************************************************************/
-
-int Edit_user_cmd::execute()
-{
- LEX_STRING user_name;
- const char *password;
-
- User_map user_map;
- User *user;
-
- int err_code;
-
- if (get_user_name(&user_name))
- return ERR_CAN_NOT_READ_USER_NAME;
-
- /* Load the password file. */
-
- if ((err_code= load_password_file(&user_map)) != ERR_OK)
- return err_code;
-
- /* Find the user. */
-
- user= user_map.find_user(&user_name);
-
- if (!user)
- {
- fprintf(stderr, "Error: user '%s' does not exist.\n",
- (const char *) user_name.str);
- return ERR_USER_NOT_FOUND;
- }
-
- /* Modify user's password. */
-
- if (!(password= get_password()))
- return ERR_CAN_NOT_READ_PASSWORD;
-
- user->set_password(password);
-
- /* Save the password file. */
-
- return save_password_file(&user_map);
-}
-
-
-/*************************************************************************
- Clean_db_cmd
-*************************************************************************/
-
-int Clean_db_cmd::execute()
-{
- User_map user_map;
-
- if (user_map.init())
- {
- fprintf(stderr, "Error: can not initialize user map.\n");
- return ERR_OUT_OF_MEMORY;
- }
-
- return save_password_file(&user_map);
-}
-
-
-/*************************************************************************
- Check_db_cmd
-*************************************************************************/
-
-int Check_db_cmd::execute()
-{
- User_map user_map;
-
- return load_password_file(&user_map);
-}
-
-
-/*************************************************************************
- List_users_cmd
-*************************************************************************/
-
-int List_users_cmd::execute()
-{
- User_map user_map;
-
- int err_code;
-
- /* Load the password file. */
-
- if ((err_code= load_password_file(&user_map)))
- return err_code;
-
- /* Print out registered users. */
-
- {
- User_map::Iterator it(&user_map);
- User *user;
-
- while ((user= it.next()))
- fprintf(stderr, "%s\n", (const char *) user->user);
- }
-
- return ERR_OK;
-}
diff --git a/server-tools/instance-manager/user_management_commands.h b/server-tools/instance-manager/user_management_commands.h
deleted file mode 100644
index c925e6ae363..00000000000
--- a/server-tools/instance-manager/user_management_commands.h
+++ /dev/null
@@ -1,167 +0,0 @@
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MANAGEMENT_CMD_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MANAGEMENT_CMD_H
-
-/*
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-/*
- This header contains declarations of classes inteded to support
- user-management commands (such as add user, get list of users, etc).
-
- The general idea is to have one interface (pure abstract class) for such a
- command. Each concrete user-management command is implemented in concrete
- class, derived from the common interface.
-*/
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-/*************************************************************************
- User_management_cmd -- base class for User-management commands.
-*************************************************************************/
-
-class User_management_cmd
-{
-public:
- User_management_cmd()
- { }
-
- virtual ~User_management_cmd()
- { }
-
-public:
- /*
- Executes user-management command.
-
- SYNOPSIS
- execute()
-
- RETURN
- See exit_codes.h for possible values.
- */
-
- virtual int execute() = 0;
-};
-
-
-/*************************************************************************
- Print_password_line_cmd: support for --print-password-line command-line
- option.
-*************************************************************************/
-
-class Print_password_line_cmd: public User_management_cmd
-{
-public:
- Print_password_line_cmd()
- { }
-
-public:
- virtual int execute();
-};
-
-
-/*************************************************************************
- Add_user_cmd: support for --add-user command-line option.
-*************************************************************************/
-
-class Add_user_cmd: public User_management_cmd
-{
-public:
- Add_user_cmd()
- { }
-
-public:
- virtual int execute();
-};
-
-
-/*************************************************************************
- Drop_user_cmd: support for --drop-user command-line option.
-*************************************************************************/
-
-class Drop_user_cmd: public User_management_cmd
-{
-public:
- Drop_user_cmd()
- { }
-
-public:
- virtual int execute();
-};
-
-
-/*************************************************************************
- Edit_user_cmd: support for --edit-user command-line option.
-*************************************************************************/
-
-class Edit_user_cmd: public User_management_cmd
-{
-public:
- Edit_user_cmd()
- { }
-
-public:
- virtual int execute();
-};
-
-
-/*************************************************************************
- Clean_db_cmd: support for --clean-db command-line option.
-*************************************************************************/
-
-class Clean_db_cmd: public User_management_cmd
-{
-public:
- Clean_db_cmd()
- { }
-
-public:
- virtual int execute();
-};
-
-
-/*************************************************************************
- Check_db_cmd: support for --check-db command-line option.
-*************************************************************************/
-
-class Check_db_cmd: public User_management_cmd
-{
-public:
- Check_db_cmd()
- { }
-
-public:
- virtual int execute();
-};
-
-
-/*************************************************************************
- List_users_cmd: support for --list-users command-line option.
-*************************************************************************/
-
-class List_users_cmd: public User_management_cmd
-{
-public:
- List_users_cmd()
- { }
-
-public:
- virtual int execute();
-};
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MANAGEMENT_CMD_H
diff --git a/server-tools/instance-manager/user_map.cc b/server-tools/instance-manager/user_map.cc
deleted file mode 100644
index 49c35c16ca9..00000000000
--- a/server-tools/instance-manager/user_map.cc
+++ /dev/null
@@ -1,395 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
-#pragma implementation
-#endif
-
-#include "user_map.h"
-#include "exit_codes.h"
-#include "log.h"
-#include "portability.h"
-
-User::User(const LEX_STRING *user_name_arg, const char *password)
-{
- user_length= (uint8) (strmake(user, user_name_arg->str,
- USERNAME_LENGTH + 1) - user);
- set_password(password);
-}
-
-int User::init(const char *line)
-{
- const char *name_begin, *name_end, *password;
- int password_length;
-
- if (line[0] == '\'' || line[0] == '"')
- {
- name_begin= line + 1;
- name_end= strchr(name_begin, line[0]);
- if (name_end == 0 || name_end[1] != ':')
- {
- log_error("Invalid format (unmatched quote) of user line (%s).",
- (const char *) line);
- return 1;
- }
- password= name_end + 2;
- }
- else
- {
- name_begin= line;
- name_end= strchr(name_begin, ':');
- if (name_end == 0)
- {
- log_error("Invalid format (no delimiter) of user line (%s).",
- (const char *) line);
- return 1;
- }
- password= name_end + 1;
- }
-
- user_length= (uint8) (name_end - name_begin);
- if (user_length > USERNAME_LENGTH)
- {
- log_error("User name is too long (%d). Max length: %d. "
- "User line: '%s'.",
- (int) user_length,
- (int) USERNAME_LENGTH,
- (const char *) line);
- return 1;
- }
-
- password_length= (int) strlen(password);
- if (password_length > SCRAMBLED_PASSWORD_CHAR_LENGTH)
- {
- log_error("Password is too long (%d). Max length: %d."
- "User line: '%s'.",
- (int) password_length,
- (int) SCRAMBLED_PASSWORD_CHAR_LENGTH,
- (const char *) line);
- return 1;
- }
-
- memcpy(user, name_begin, user_length);
- user[user_length]= 0;
-
- memcpy(scrambled_password, password, password_length);
- scrambled_password[password_length]= 0;
-
- get_salt_from_password(salt, password);
-
- log_info("Loaded user '%s'.", (const char *) user);
-
- return 0;
-}
-
-
-C_MODE_START
-
-static uchar* get_user_key(const uchar* u, size_t* len,
- my_bool __attribute__((unused)) t)
-{
- const User *user= (const User *) u;
- *len= user->user_length;
- return (uchar *) user->user;
-}
-
-static void delete_user(void *u)
-{
- User *user= (User *) u;
- delete user;
-}
-
-C_MODE_END
-
-
-void User_map::Iterator::reset()
-{
- cur_idx= 0;
-}
-
-
-User *User_map::Iterator::next()
-{
- if (cur_idx < user_map->hash.records)
- return (User *) hash_element(&user_map->hash, cur_idx++);
-
- return NULL;
-}
-
-
-int User_map::init()
-{
- enum { START_HASH_SIZE= 16 };
- if (hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
- get_user_key, delete_user, 0))
- return 1;
-
- initialized= TRUE;
-
- return 0;
-}
-
-
-User_map::User_map()
- :initialized(FALSE)
-{
-}
-
-
-User_map::~User_map()
-{
- if (initialized)
- hash_free(&hash);
-}
-
-
-/*
- Load password database.
-
- SYNOPSIS
- load()
- password_file_name [IN] password file path
- err_msg [OUT] error message
-
- DESCRIPTION
- Load all users from the password file. Must be called once right after
- construction. In case of failure, puts error message to the log file and
- returns specific error code.
-
- RETURN
- 0 on success
- !0 on error
-*/
-
-int User_map::load(const char *password_file_name, const char **err_msg)
-{
- static const int ERR_MSG_BUF_SIZE = 255;
- static char err_msg_buf[ERR_MSG_BUF_SIZE];
-
- FILE *file;
- char line[USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH +
- 2 + /* for possible quotes */
- 1 + /* for ':' */
- 2 + /* for newline */
- 1]; /* for trailing zero */
- User *user;
-
- if (my_access(password_file_name, F_OK) != 0)
- {
- if (err_msg)
- {
- snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
- "password file (%s) does not exist",
- (const char *) password_file_name);
- *err_msg= err_msg_buf;
- }
-
- return ERR_PASSWORD_FILE_DOES_NOT_EXIST;
- }
-
- if ((file= my_fopen(password_file_name, O_RDONLY | O_BINARY, MYF(0))) == 0)
- {
- if (err_msg)
- {
- snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
- "can not open password file (%s): %s",
- (const char *) password_file_name,
- (const char *) strerror(errno));
- *err_msg= err_msg_buf;
- }
-
- return ERR_IO_ERROR;
- }
-
- log_info("Loading the password database...");
-
- while (fgets(line, sizeof(line), file))
- {
- char *user_line= line;
-
- /*
- We need to skip EOL-symbols also from the beginning of the line, because
- if the previous line was ended by \n\r sequence, we get \r in our line.
- */
-
- while (user_line[0] == '\r' || user_line[0] == '\n')
- ++user_line;
-
- /* Skip EOL-symbols in the end of the line. */
-
- {
- char *ptr;
-
- if ((ptr= strchr(user_line, '\n')))
- *ptr= 0;
-
- if ((ptr= strchr(user_line, '\r')))
- *ptr= 0;
- }
-
- /* skip comments and empty lines */
- if (!user_line[0] || user_line[0] == '#')
- continue;
-
- if ((user= new User) == 0)
- {
- my_fclose(file, MYF(0));
-
- if (err_msg)
- {
- snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
- "out of memory while parsing password file (%s)",
- (const char *) password_file_name);
- *err_msg= err_msg_buf;
- }
-
- return ERR_OUT_OF_MEMORY;
- }
-
- if (user->init(user_line))
- {
- delete user;
- my_fclose(file, MYF(0));
-
- if (err_msg)
- {
- snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
- "password file (%s) corrupted",
- (const char *) password_file_name);
- *err_msg= err_msg_buf;
- }
-
- return ERR_PASSWORD_FILE_CORRUPTED;
- }
-
- if (my_hash_insert(&hash, (uchar *) user))
- {
- delete user;
- my_fclose(file, MYF(0));
-
- if (err_msg)
- {
- snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
- "out of memory while parsing password file (%s)",
- (const char *) password_file_name);
- *err_msg= err_msg_buf;
- }
-
- return ERR_OUT_OF_MEMORY;
- }
- }
-
- log_info("The password database loaded successfully.");
-
- my_fclose(file, MYF(0));
-
- if (err_msg)
- *err_msg= NULL;
-
- return ERR_OK;
-}
-
-
-int User_map::save(const char *password_file_name, const char **err_msg)
-{
- static const int ERR_MSG_BUF_SIZE = 255;
- static char err_msg_buf[ERR_MSG_BUF_SIZE];
-
- FILE *file;
-
- if ((file= my_fopen(password_file_name, O_WRONLY | O_TRUNC | O_BINARY,
- MYF(0))) == 0)
- {
- if (err_msg)
- {
- snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
- "can not open password file (%s) for writing: %s",
- (const char *) password_file_name,
- (const char *) strerror(errno));
- *err_msg= err_msg_buf;
- }
-
- return ERR_IO_ERROR;
- }
-
- {
- User_map::Iterator it(this);
- User *user;
-
- while ((user= it.next()))
- {
- if (fprintf(file, "%s:%s\n", (const char *) user->user,
- (const char *) user->scrambled_password) < 0)
- {
- if (err_msg)
- {
- snprintf(err_msg_buf, ERR_MSG_BUF_SIZE,
- "can not write to password file (%s): %s",
- (const char *) password_file_name,
- (const char *) strerror(errno));
- *err_msg= err_msg_buf;
- }
-
- my_fclose(file, MYF(0));
-
- return ERR_IO_ERROR;
- }
- }
- }
-
- my_fclose(file, MYF(0));
-
- return ERR_OK;
-}
-
-
-/*
- Check if user exists and password is correct
- RETURN VALUE
- 0 - user found and password OK
- 1 - password mismatch
- 2 - user not found
-*/
-
-int User_map::authenticate(const LEX_STRING *user_name,
- const char *scrambled_password,
- const char *scramble) const
-{
- const User *user= find_user(user_name);
- return user ? check_scramble(scrambled_password, scramble, user->salt) : 2;
-}
-
-
-User *User_map::find_user(const LEX_STRING *user_name)
-{
- return (User*) hash_search(&hash, (uchar*) user_name->str, user_name->length);
-}
-
-const User *User_map::find_user(const LEX_STRING *user_name) const
-{
- return const_cast<User_map *> (this)->find_user(user_name);
-}
-
-
-bool User_map::add_user(User *user)
-{
- return my_hash_insert(&hash, (uchar*) user) == 0 ? FALSE : TRUE;
-}
-
-
-bool User_map::remove_user(User *user)
-{
- return hash_delete(&hash, (uchar*) user) == 0 ? FALSE : TRUE;
-}
diff --git a/server-tools/instance-manager/user_map.h b/server-tools/instance-manager/user_map.h
deleted file mode 100644
index 6168f2b04fa..00000000000
--- a/server-tools/instance-manager/user_map.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Copyright (C) 2004-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 */
-
-#ifndef INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MAP_H
-#define INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MAP_H
-
-#include <my_global.h>
-#include <my_sys.h>
-#include <mysql_com.h>
-#include <m_string.h>
-#include <hash.h>
-
-#if defined(__GNUC__) && defined(USE_PRAGMA_INTERFACE)
-#pragma interface
-#endif
-
-struct User
-{
- User()
- {}
-
- User(const LEX_STRING *user_name_arg, const char *password);
-
- int init(const char *line);
-
- inline void set_password(const char *password)
- {
- make_scrambled_password(scrambled_password, password);
- }
-
- char user[USERNAME_LENGTH + 1];
- char scrambled_password[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1];
- uint8 user_length;
- uint8 salt[SCRAMBLE_LENGTH];
-};
-
-/*
- User_map -- all users and passwords
-*/
-
-class User_map
-{
-public:
- /* User_map iterator */
-
- class Iterator
- {
- public:
- Iterator(User_map *user_map_arg) :
- user_map(user_map_arg), cur_idx(0)
- { }
-
- public:
- void reset();
-
- User *next();
-
- private:
- User_map *user_map;
- uint cur_idx;
- };
-
-public:
- User_map();
- ~User_map();
-
- int init();
- int load(const char *password_file_name, const char **err_msg);
- int save(const char *password_file_name, const char **err_msg);
- int authenticate(const LEX_STRING *user_name,
- const char *scrambled_password,
- const char *scramble) const;
-
- const User *find_user(const LEX_STRING *user_name) const;
- User *find_user(const LEX_STRING *user_name);
-
- bool add_user(User *user);
- bool remove_user(User *user);
-
-private:
- User_map(const User_map &);
- User_map &operator =(const User_map &);
-
-private:
- HASH hash;
- bool initialized;
-
- friend class Iterator;
-};
-
-#endif // INCLUDES_MYSQL_INSTANCE_MANAGER_USER_MAP_H
diff --git a/sql-common/client.c b/sql-common/client.c
index 84029b449af..3ee6c600387 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -145,9 +145,12 @@ int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
uint timeout)
{
#if defined(__WIN__) || defined(__NETWARE__)
- return connect(fd, (struct sockaddr*) name, namelen);
+ DBUG_ENTER("my_connect");
+ DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
#else
int flags, res, s_err;
+ DBUG_ENTER("my_connect");
+ DBUG_PRINT("enter", ("fd: %d timeout: %u", fd, timeout));
/*
If they passed us a timeout of zero, we should behave
@@ -155,24 +158,26 @@ int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
*/
if (timeout == 0)
- return connect(fd, (struct sockaddr*) name, namelen);
+ DBUG_RETURN(connect(fd, (struct sockaddr*) name, namelen));
flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */
#ifdef O_NONBLOCK
fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */
#endif
+ DBUG_PRINT("info", ("connecting non-blocking"));
res= connect(fd, (struct sockaddr*) name, namelen);
+ DBUG_PRINT("info", ("connect result: %d errno: %d", res, errno));
s_err= errno; /* Save the error... */
fcntl(fd, F_SETFL, flags);
if ((res != 0) && (s_err != EINPROGRESS))
{
errno= s_err; /* Restore it */
- return(-1);
+ DBUG_RETURN(-1);
}
if (res == 0) /* Connected quickly! */
- return(0);
- return wait_for_data(fd, timeout);
+ DBUG_RETURN(0);
+ DBUG_RETURN(wait_for_data(fd, timeout));
#endif
}
@@ -191,26 +196,58 @@ static int wait_for_data(my_socket fd, uint timeout)
#ifdef HAVE_POLL
struct pollfd ufds;
int res;
+ DBUG_ENTER("wait_for_data");
+ DBUG_PRINT("info", ("polling"));
ufds.fd= fd;
ufds.events= POLLIN | POLLPRI;
if (!(res= poll(&ufds, 1, (int) timeout*1000)))
{
+ DBUG_PRINT("info", ("poll timed out"));
errno= EINTR;
- return -1;
+ DBUG_RETURN(-1);
}
+ DBUG_PRINT("info",
+ ("poll result: %d errno: %d revents: 0x%02d events: 0x%02d",
+ res, errno, ufds.revents, ufds.events));
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
- return -1;
- return 0;
+ DBUG_RETURN(-1);
+ /*
+ At this point, we know that something happened on the socket.
+ But this does not means that everything is alright.
+ The connect might have failed. We need to retrieve the error code
+ from the socket layer. We must return success only if we are sure
+ that it was really a success. Otherwise we might prevent the caller
+ from trying another address to connect to.
+ */
+ {
+ int s_err;
+ socklen_t s_len= sizeof(s_err);
+
+ DBUG_PRINT("info", ("Get SO_ERROR from non-blocked connected socket."));
+ res= getsockopt(fd, SOL_SOCKET, SO_ERROR, &s_err, &s_len);
+ DBUG_PRINT("info", ("getsockopt res: %d s_err: %d", res, s_err));
+ if (res)
+ DBUG_RETURN(res);
+ /* getsockopt() was successful, check the retrieved status value. */
+ if (s_err)
+ {
+ errno= s_err;
+ DBUG_RETURN(-1);
+ }
+ /* Status from connect() is zero. Socket is successfully connected. */
+ }
+ DBUG_RETURN(0);
#else
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
fd_set sfds;
struct timeval tv;
time_t start_time, now_time;
int res, s_err;
+ DBUG_ENTER("wait_for_data");
if (fd >= FD_SETSIZE) /* Check if wrong error */
- return 0; /* Can't use timeout */
+ DBUG_RETURN(0); /* Can't use timeout */
/*
Our connection is "in progress." We can use the select() call to wait
@@ -250,11 +287,11 @@ static int wait_for_data(my_socket fd, uint timeout)
break;
#endif
if (res == 0) /* timeout */
- return -1;
+ DBUG_RETURN(-1);
now_time= my_time(0);
timeout-= (uint) (now_time - start_time);
if (errno != EINTR || (int) timeout <= 0)
- return -1;
+ DBUG_RETURN(-1);
}
/*
@@ -265,14 +302,14 @@ static int wait_for_data(my_socket fd, uint timeout)
s_err=0;
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
- return(-1);
+ DBUG_RETURN(-1);
if (s_err)
{ /* getsockopt could succeed */
errno = s_err;
- return(-1); /* but return an error... */
+ DBUG_RETURN(-1); /* but return an error... */
}
- return (0); /* ok */
+ DBUG_RETURN(0); /* ok */
#endif /* HAVE_POLL */
}
#endif /* defined(__WIN__) || defined(__NETWARE__) */
@@ -1313,7 +1350,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->flags= uint2korr(pos+7);
field->decimals= (uint) pos[9];
- if (INTERNAL_NUM_FIELD(field))
+ if (IS_NUM(field->type))
field->flags|= NUM_FLAG;
if (default_value && row->data[7])
{
@@ -1354,7 +1391,7 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
field->flags= (uint) (uchar) row->data[4][0];
field->decimals=(uint) (uchar) row->data[4][1];
}
- if (INTERNAL_NUM_FIELD(field))
+ if (IS_NUM(field->type))
field->flags|= NUM_FLAG;
if (default_value && row->data[5])
{
@@ -1877,7 +1914,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
init_sigpipe_variables
DBUG_ENTER("mysql_real_connect");
- DBUG_PRINT("enter",("host: %s db: %s user: %s",
+ DBUG_PRINT("enter",("host: %s db: %s user: %s (client)",
host ? host : "(Null)",
db ? db : "(Null)",
user ? user : "(Null)"));
@@ -1927,6 +1964,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
unix_socket=mysql->options.unix_socket;
mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
+ DBUG_PRINT("info", ("Connecting"));
/*
Part 0: Grab a socket and connect it to the server
@@ -1936,6 +1974,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) &&
(!host || !strcmp(host,LOCAL_HOST)))
{
+ DBUG_PRINT("info", ("Using shared memory"));
if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
INVALID_HANDLE_VALUE)
{
@@ -2034,6 +2073,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
}
}
#endif
+ DBUG_PRINT("info", ("net->vio: %p protocol: %d",
+ net->vio, mysql->options.protocol));
if (!net->vio &&
(!mysql->options.protocol ||
mysql->options.protocol == MYSQL_PROTOCOL_TCP))
@@ -2105,6 +2146,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length));
DBUG_PRINT("info",("Trying %s...",
(my_inet_ntoa(sock_addr.sin_addr, ipaddr), ipaddr)));
+ /*
+ Here we rely on my_connect() to return success only if the
+ connect attempt was really successful. Otherwise we would stop
+ trying another address, believing we were successful.
+ */
status= my_connect(sock, (struct sockaddr *) &sock_addr,
sizeof(sock_addr), mysql->options.connect_timeout);
}
@@ -2163,6 +2209,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
/*
Part 1: Connection established, read and parse first packet
*/
+ DBUG_PRINT("info", ("Read first packet."));
if ((pkt_length=cli_safe_read(mysql)) == packet_error)
{
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 6f162f4d84d..49ae232c31c 100755
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -15,9 +15,9 @@
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
SET(CMAKE_CXX_FLAGS_DEBUG
- "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi")
+ "${CMAKE_CXX_FLAGS_DEBUG} -DUSE_SYMDIR /Zi")
SET(CMAKE_C_FLAGS_DEBUG
- "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX -DUSE_SYMDIR /Zi")
+ "${CMAKE_C_FLAGS_DEBUG} -DUSE_SYMDIR /Zi")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /MAP /MAPINFO:EXPORTS")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
@@ -75,6 +75,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
+ sql_signal.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
@@ -95,7 +96,6 @@ SET_TARGET_PROPERTIES(mysqld PROPERTIES ENABLE_EXPORTS TRUE)
SET (MYSQLD_CORE_LIBS mysys zlib dbug strings yassl taocrypt vio regex sql)
TARGET_LINK_LIBRARIES(mysqld ${MYSQLD_CORE_LIBS} ${MYSQLD_STATIC_ENGINE_LIBS})
-TARGET_LINK_LIBRARIES(mysqld ws2_32.lib)
IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)
@@ -128,7 +128,7 @@ ADD_CUSTOM_COMMAND(
# Gen_lex_hash
ADD_EXECUTABLE(gen_lex_hash gen_lex_hash.cc)
-TARGET_LINK_LIBRARIES(gen_lex_hash debug dbug mysqlclient wsock32)
+TARGET_LINK_LIBRARIES(gen_lex_hash dbug mysqlclient)
GET_TARGET_PROPERTY(GEN_LEX_HASH_EXE gen_lex_hash LOCATION)
ADD_CUSTOM_COMMAND(
OUTPUT ${PROJECT_SOURCE_DIR}/sql/lex_hash.h
@@ -151,4 +151,4 @@ SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def)
ADD_DEPENDENCIES(udf_example strings GenError)
-TARGET_LINK_LIBRARIES(udf_example strings wsock32)
+TARGET_LINK_LIBRARIES(udf_example strings)
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 5263e62a439..600a6117ebf 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -110,7 +110,7 @@ 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 sql_signal.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -154,7 +154,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
event_queue.cc event_db_repository.cc events.cc \
sql_plugin.cc sql_binlog.cc \
sql_builtin.cc sql_tablespace.cc partition_info.cc \
- sql_servers.cc event_parse_data.cc
+ sql_servers.cc event_parse_data.cc sql_signal.cc
nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c
diff --git a/sql/authors.h b/sql/authors.h
index dfe3b143e2f..bb5156742e5 100644
--- a/sql/authors.h
+++ b/sql/authors.h
@@ -36,6 +36,7 @@ struct show_table_authors_st {
struct show_table_authors_st show_table_authors[]= {
{ "Brian (Krow) Aker", "Seattle, WA, USA",
"Architecture, archive, federated, bunch of little stuff :)" },
+ { "Marc Alff", "Denver, CO, USA", "Signal, Resignal" },
{ "Venu Anuganti", "", "Client/server protocol (4.1)" },
{ "David Axmark", "Uppsala, Sweden",
"Small stuff long time ago, Monty ripped it out!" },
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 8c0025f9ed4..daaa6be0520 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -74,7 +74,7 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
{
MYSQL_ERROR *err;
DBUG_ENTER("evex_print_warnings");
- if (!thd->warn_list.elements)
+ if (thd->warning_info->is_empty())
DBUG_VOID_RETURN;
char msg_buf[10 * STRING_BUFFER_USUAL_SIZE];
@@ -90,17 +90,18 @@ Event_worker_thread::print_warnings(THD *thd, Event_job_data *et)
prefix.append(et->name.str, et->name.length, system_charset_info);
prefix.append("] ", 2);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
while ((err= it++))
{
String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);
/* set it to 0 or we start adding at the end. That's the trick ;) */
err_msg.length(0);
err_msg.append(prefix);
- err_msg.append(err->msg, strlen(err->msg), system_charset_info);
- DBUG_ASSERT(err->level < 3);
- (sql_print_message_handlers[err->level])("%*s", err_msg.length(),
- err_msg.c_ptr());
+ err_msg.append(err->get_message_text(),
+ err->get_message_octet_length(), system_charset_info);
+ DBUG_ASSERT(err->get_level() < 3);
+ (sql_print_message_handlers[err->get_level()])("%*s", err_msg.length(),
+ err_msg.c_ptr());
}
DBUG_VOID_RETURN;
}
diff --git a/sql/field.cc b/sql/field.cc
index 9f46552d5bd..64b156fbdcb 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1116,7 +1116,7 @@ int Field_num::check_int(CHARSET_INFO *cs, const char *str, int length,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"integer", tmp.c_ptr(), field_name,
- (ulong) table->in_use->row_count);
+ (ulong) table->in_use->warning_info->current_row_for_warning());
return 1;
}
/* Test if we have garbage at the end of the given string. */
@@ -2678,11 +2678,11 @@ int Field_new_decimal::store(const char *from, uint length,
String from_as_str;
from_as_str.copy(from, length, &my_charset_bin);
- push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", from_as_str.c_ptr(), field_name,
- (ulong) table->in_use->row_count);
+ (ulong) table->in_use->warning_info->current_row_for_warning());
DBUG_RETURN(err);
}
@@ -2705,7 +2705,7 @@ int Field_new_decimal::store(const char *from, uint length,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", from_as_str.c_ptr(), field_name,
- (ulong) table->in_use->row_count);
+ (ulong) table->in_use->warning_info->current_row_for_warning());
my_decimal_set_zero(&decimal_value);
break;
@@ -5358,7 +5358,7 @@ bool Field_time::get_date(MYSQL_TIME *ltime, uint fuzzydate)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE), field_name,
- thd->row_count);
+ thd->warning_info->current_row_for_warning());
return 1;
}
tmp=(long) sint3korr(ptr);
@@ -6352,21 +6352,20 @@ check_string_copy_error(Field_str *field,
{
const char *pos;
char tmp[32];
-
+ THD *thd= field->table->in_use;
+
if (!(pos= well_formed_error_pos) &&
!(pos= cannot_convert_error_pos))
return FALSE;
convert_to_printable(tmp, sizeof(tmp), pos, (end - pos), cs, 6);
- push_warning_printf(field->table->in_use,
- field->table->in_use->abort_on_warning ?
- MYSQL_ERROR::WARN_LEVEL_ERROR :
+ push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+ ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"string", tmp, field->field_name,
- (ulong) field->table->in_use->row_count);
+ thd->warning_info->current_row_for_warning());
return TRUE;
}
@@ -6400,7 +6399,7 @@ Field_longstr::report_if_important_data(const char *ptr, const char *end,
if (test_if_important_data(field_charset, ptr, end))
{
if (table->in_use->abort_on_warning)
- set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
return 2;
@@ -9030,7 +9029,7 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs)
set_rec_bits((1 << bit_len) - 1, bit_ptr, bit_ofs, bit_len);
memset(ptr, 0xff, bytes_in_rec);
if (table->in_use->really_abort_on_warning())
- set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
@@ -9441,7 +9440,7 @@ int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs)
if (bits)
*ptr&= ((1 << bits) - 1); /* set first uchar */
if (table->in_use->really_abort_on_warning())
- set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1);
else
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
@@ -10314,7 +10313,7 @@ Field::set_warning(MYSQL_ERROR::enum_warning_level level, uint code,
{
thd->cuted_fields+= cuted_increment;
push_warning_printf(thd, level, code, ER(code), field_name,
- thd->row_count);
+ thd->warning_info->current_row_for_warning());
return 0;
}
return level >= MYSQL_ERROR::WARN_LEVEL_WARN;
diff --git a/sql/field.h b/sql/field.h
index a9299256f88..ffcf665d45f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1934,9 +1934,12 @@ public:
virtual bool str_needs_quotes() { return TRUE; }
my_decimal *val_decimal(my_decimal *);
int cmp(const uchar *a, const uchar *b)
- {
- DBUG_ASSERT(ptr == a);
- return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len));
+ {
+ DBUG_ASSERT(ptr == a || ptr == b);
+ if (ptr == a)
+ return Field_bit::key_cmp(b, bytes_in_rec+test(bit_len));
+ else
+ return Field_bit::key_cmp(a, bytes_in_rec+test(bit_len)) * -1;
}
int cmp_binary_offset(uint row_offset)
{ return cmp_offset(row_offset); }
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 264e5649ea9..90194fa00e7 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -265,11 +265,11 @@ static int ndb_to_mysql_error(const NdbError *ndberr)
- Used by replication to see if the error was temporary
*/
if (ndberr->status == NdbError::TemporaryError)
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_TEMPORARY_ERRMSG, ER(ER_GET_TEMPORARY_ERRMSG),
ndberr->code, ndberr->message, "NDB");
else
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndberr->code, ndberr->message, "NDB");
return error;
@@ -536,7 +536,7 @@ static void set_ndb_err(THD *thd, const NdbError &err)
{
char buf[FN_REFLEN];
ndb_error_string(thd_ndb->m_error_code, buf, sizeof(buf));
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
thd_ndb->m_error_code, buf, "NDB");
}
@@ -5308,7 +5308,7 @@ int ha_ndbcluster::create(const char *name,
{
if (create_info->storage_media == HA_SM_MEMORY)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
@@ -5363,7 +5363,7 @@ int ha_ndbcluster::create(const char *name,
case ROW_TYPE_FIXED:
if (field_type_forces_var_part(field->type()))
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
@@ -5703,7 +5703,7 @@ int ha_ndbcluster::create_index(const char *name, KEY *key_info,
case ORDERED_INDEX:
if (key_info->algorithm == HA_KEY_ALG_HASH)
{
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
@@ -9606,11 +9606,11 @@ char* ha_ndbcluster::get_tablespace_name(THD *thd, char* name, uint name_len)
}
err:
if (ndberr.status == NdbError::TemporaryError)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_TEMPORARY_ERRMSG, ER(ER_GET_TEMPORARY_ERRMSG),
ndberr.code, ndberr.message, "NDB");
else
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndberr.code, ndberr.message, "NDB");
return 0;
@@ -9904,7 +9904,7 @@ uint ha_ndbcluster::set_up_partition_info(partition_info *part_info,
{
if (!current_thd->variables.new_mode)
{
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index d9a9738ce72..b9b9e7acbf2 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -272,13 +272,13 @@ static void run_query(THD *thd, char *buf, char *end,
Thd_ndb *thd_ndb= get_thd_ndb(thd);
for (i= 0; no_print_error[i]; i++)
if ((thd_ndb->m_error_code == no_print_error[i]) ||
- (thd->main_da.sql_errno() == (unsigned) no_print_error[i]))
+ (thd->stmt_da->sql_errno() == (unsigned) no_print_error[i]))
break;
if (!no_print_error[i])
sql_print_error("NDB: %s: error %s %d(ndb: %d) %d %d",
buf,
- thd->main_da.message(),
- thd->main_da.sql_errno(),
+ thd->stmt_da->message(),
+ thd->stmt_da->sql_errno(),
thd_ndb->m_error_code,
(int) thd->is_error(), thd->is_slave_error);
}
@@ -293,7 +293,7 @@ static void run_query(THD *thd, char *buf, char *end,
is called from ndbcluster_reset_logs(), which is called from
mysql_flush().
*/
- thd->main_da.reset_diagnostics_area();
+ thd->stmt_da->reset_diagnostics_area();
thd->options= save_thd_options;
thd->set_query(save_thd_query, save_thd_query_length);
@@ -963,6 +963,21 @@ struct Cluster_schema
uint32 any_value;
};
+static void print_could_not_discover_error(THD *thd,
+ const Cluster_schema *schema)
+{
+ sql_print_error("NDB Binlog: Could not discover table '%s.%s' from "
+ "binlog schema event '%s' from node %d. "
+ "my_errno: %d",
+ schema->db, schema->name, schema->query,
+ schema->node_id, my_errno);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
+ MYSQL_ERROR *err;
+ while ((err= it++))
+ sql_print_warning("NDB Binlog: (%d)%s", err->get_sql_errno(),
+ err->get_message_text());
+}
+
/*
Transfer schema table data into corresponding struct
*/
@@ -1198,7 +1213,7 @@ ndbcluster_update_slock(THD *thd,
}
if (ndb_error)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndb_error->code,
ndb_error->message,
@@ -1521,7 +1536,7 @@ err:
}
end:
if (ndb_error)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndb_error->code,
ndb_error->message,
@@ -1971,15 +1986,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
}
else if (ndb_create_table_from_engine(thd, schema->db, schema->name))
{
- sql_print_error("NDB Binlog: Could not discover table '%s.%s' from "
- "binlog schema event '%s' from node %d. "
- "my_errno: %d",
- schema->db, schema->name, schema->query,
- schema->node_id, my_errno);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
- MYSQL_ERROR *err;
- while ((err= it++))
- sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg);
+ print_could_not_discover_error(thd, schema);
}
pthread_mutex_unlock(&LOCK_open);
log_query= 1;
@@ -2262,14 +2269,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
}
else if (ndb_create_table_from_engine(thd, schema->db, schema->name))
{
- sql_print_error("NDB Binlog: Could not discover table '%s.%s' from "
- "binlog schema event '%s' from node %d. my_errno: %d",
- schema->db, schema->name, schema->query,
- schema->node_id, my_errno);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
- MYSQL_ERROR *err;
- while ((err= it++))
- sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg);
+ print_could_not_discover_error(thd, schema);
}
pthread_mutex_unlock(&LOCK_open);
}
@@ -2344,8 +2344,8 @@ static int open_ndb_binlog_index(THD *thd, TABLE_LIST *tables,
sql_print_error("NDB Binlog: Opening ndb_binlog_index: killed");
else
sql_print_error("NDB Binlog: Opening ndb_binlog_index: %d, '%s'",
- thd->main_da.sql_errno(),
- thd->main_da.message());
+ thd->stmt_da->sql_errno(),
+ thd->stmt_da->message());
thd->proc_info= save_proc_info;
return -1;
}
@@ -2741,7 +2741,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
"with BLOB attribute and no PK is not supported",
share->key);
if (push_warning)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ndbcluster_hton_name,
@@ -2785,7 +2785,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
failed, print a warning
*/
if (push_warning > 1)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
dict->getNdbError().code,
dict->getNdbError().message, "NDB");
@@ -2813,7 +2813,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
dict->dropEvent(my_event.getName()))
{
if (push_warning > 1)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
dict->getNdbError().code,
dict->getNdbError().message, "NDB");
@@ -2832,7 +2832,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
if (dict->createEvent(my_event))
{
if (push_warning > 1)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
dict->getNdbError().code,
dict->getNdbError().message, "NDB");
@@ -2845,7 +2845,7 @@ ndbcluster_create_event(Ndb *ndb, const NDBTAB *ndbtab,
DBUG_RETURN(-1);
}
#ifdef NDB_BINLOG_EXTRA_WARNINGS
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
0, "NDB Binlog: Removed trailing event",
"NDB");
@@ -2956,7 +2956,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
{
sql_print_error("NDB Binlog: Creating NdbEventOperation failed for"
" %s",event_name);
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
ndb->getNdbError().code,
ndb->getNdbError().message,
@@ -3005,7 +3005,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
sql_print_error("NDB Binlog: Creating NdbEventOperation"
" blob field %u handles failed (code=%d) for %s",
j, op->getNdbError().code, event_name);
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
op->getNdbError().code,
op->getNdbError().message,
@@ -3044,7 +3044,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab,
retries= 0;
if (retries == 0)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
op->getNdbError().code, op->getNdbError().message,
"NDB");
@@ -3112,7 +3112,7 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name,
if (dict->getNdbError().code != 4710)
{
/* drop event failed for some reason, issue a warning */
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
dict->getNdbError().code,
dict->getNdbError().message, "NDB");
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 5b053ab9cac..cc041d91809 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -849,9 +849,12 @@ int ha_partition::rename_partitions(const char *path)
#define ANALYZE_PARTS 2
#define CHECK_PARTS 3
#define REPAIR_PARTS 4
+#define ASSIGN_KEYCACHE_PARTS 5
+#define PRELOAD_KEYS_PARTS 6
static const char *opt_op_name[]= {NULL,
- "optimize", "analyze", "check", "repair" };
+ "optimize", "analyze", "check", "repair",
+ "assign_to_keycache", "preload_keys"};
/*
Optimize table
@@ -936,7 +939,44 @@ int ha_partition::repair(THD *thd, HA_CHECK_OPT *check_opt)
DBUG_RETURN(handle_opt_partitions(thd, check_opt, REPAIR_PARTS));
}
+/**
+ Assign to keycache
+
+ @param thd Thread object
+ @param check_opt Check/analyze/repair/optimize options
+
+ @return
+ @retval >0 Error
+ @retval 0 Success
+*/
+
+int ha_partition::assign_to_keycache(THD *thd, HA_CHECK_OPT *check_opt)
+{
+ DBUG_ENTER("ha_partition::assign_to_keycache");
+
+ DBUG_RETURN(handle_opt_partitions(thd, check_opt, ASSIGN_KEYCACHE_PARTS));
+}
+
+
+/**
+ Preload to keycache
+ @param thd Thread object
+ @param check_opt Check/analyze/repair/optimize options
+
+ @return
+ @retval >0 Error
+ @retval 0 Success
+*/
+
+int ha_partition::preload_keys(THD *thd, HA_CHECK_OPT *check_opt)
+{
+ DBUG_ENTER("ha_partition::preload_keys");
+
+ DBUG_RETURN(handle_opt_partitions(thd, check_opt, PRELOAD_KEYS_PARTS));
+}
+
+
/*
Handle optimize/analyze/check/repair of one partition
@@ -967,6 +1007,10 @@ static int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
error= file->ha_check(thd, check_opt);
else if (flag == REPAIR_PARTS)
error= file->ha_repair(thd, check_opt);
+ else if (flag == ASSIGN_KEYCACHE_PARTS)
+ error= file->assign_to_keycache(thd, check_opt);
+ else if (flag == PRELOAD_KEYS_PARTS)
+ error= file->preload_keys(thd, check_opt);
else
{
DBUG_ASSERT(FALSE);
@@ -1064,7 +1108,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
it should only do named partitions, otherwise all partitions
*/
if (!(thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION) ||
- part_elem->part_state == PART_CHANGED)
+ part_elem->part_state == PART_ADMIN)
{
if (m_is_sub_partitioned)
{
@@ -1096,6 +1140,12 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
"Subpartition %s returned error",
sub_elem->partition_name);
}
+ /* reset part_state for the remaining partitions */
+ do
+ {
+ if (part_elem->part_state == PART_ADMIN)
+ part_elem->part_state= PART_NORMAL;
+ } while (part_elem= part_it++);
DBUG_RETURN(error);
}
} while (++j < no_subparts);
@@ -1122,9 +1172,16 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
opt_op_name[flag], "Partition %s returned error",
part_elem->partition_name);
}
+ /* reset part_state for the remaining partitions */
+ do
+ {
+ if (part_elem->part_state == PART_ADMIN)
+ part_elem->part_state= PART_NORMAL;
+ } while (part_elem= part_it++);
DBUG_RETURN(error);
}
}
+ part_elem->part_state= PART_NORMAL;
}
} while (++i < no_parts);
DBUG_RETURN(FALSE);
@@ -3221,6 +3278,9 @@ int ha_partition::delete_row(const uchar *buf)
Called from sql_delete.cc by mysql_delete().
Called from sql_select.cc by JOIN::reinit().
Called from sql_union.cc by st_select_lex_unit::exec().
+
+ Also used for handle ALTER TABLE t TRUNCATE PARTITION ...
+ NOTE: auto increment value will be truncated in that partition as well!
*/
int ha_partition::delete_all_rows()
@@ -3233,11 +3293,84 @@ int ha_partition::delete_all_rows()
if (thd->lex->sql_command == SQLCOM_TRUNCATE)
{
+ Alter_info *alter_info= &thd->lex->alter_info;
HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
+ /* TRUNCATE also means resetting auto_increment */
lock_auto_increment();
ha_data->next_auto_inc_val= 0;
ha_data->auto_inc_initialized= FALSE;
unlock_auto_increment();
+ if (alter_info->flags & ALTER_ADMIN_PARTITION)
+ {
+ /* ALTER TABLE t TRUNCATE PARTITION ... */
+ List_iterator<partition_element> part_it(m_part_info->partitions);
+ int saved_error= 0;
+ uint no_parts= m_part_info->no_parts;
+ uint no_subparts= m_part_info->no_subparts;
+ uint i= 0;
+ uint no_parts_set= alter_info->partition_names.elements;
+ uint no_parts_found= set_part_state(alter_info, m_part_info,
+ PART_ADMIN);
+ if (no_parts_set != no_parts_found &&
+ (!(alter_info->flags & ALTER_ALL_PARTITION)))
+ DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
+
+ /*
+ Cannot return HA_ERR_WRONG_COMMAND here without correct pruning
+ since that whould delete the whole table row by row in sql_delete.cc
+ */
+ bitmap_clear_all(&m_part_info->used_partitions);
+ do
+ {
+ partition_element *part_elem= part_it++;
+ if (part_elem->part_state == PART_ADMIN)
+ {
+ if (m_is_sub_partitioned)
+ {
+ List_iterator<partition_element>
+ subpart_it(part_elem->subpartitions);
+ partition_element *sub_elem;
+ uint j= 0, part;
+ do
+ {
+ sub_elem= subpart_it++;
+ part= i * no_subparts + j;
+ bitmap_set_bit(&m_part_info->used_partitions, part);
+ if (!saved_error)
+ {
+ DBUG_PRINT("info", ("truncate subpartition %u (%s)",
+ part, sub_elem->partition_name));
+ if ((error= m_file[part]->ha_delete_all_rows()))
+ saved_error= error;
+ /* If not reset_auto_increment is supported, just accept it */
+ if (!saved_error &&
+ (error= m_file[part]->ha_reset_auto_increment(0)) &&
+ error != HA_ERR_WRONG_COMMAND)
+ saved_error= error;
+ }
+ } while (++j < no_subparts);
+ }
+ else
+ {
+ DBUG_PRINT("info", ("truncate partition %u (%s)", i,
+ part_elem->partition_name));
+ bitmap_set_bit(&m_part_info->used_partitions, i);
+ if (!saved_error)
+ {
+ if ((error= m_file[i]->ha_delete_all_rows()) && !saved_error)
+ saved_error= error;
+ /* If not reset_auto_increment is supported, just accept it */
+ if (!saved_error &&
+ (error= m_file[i]->ha_reset_auto_increment(0)) &&
+ error != HA_ERR_WRONG_COMMAND)
+ saved_error= error;
+ }
+ }
+ part_elem->part_state= PART_NORMAL;
+ }
+ } while (++i < no_parts);
+ DBUG_RETURN(saved_error);
+ }
truncate= TRUE;
}
file= m_file;
@@ -5912,12 +6045,14 @@ enum row_type ha_partition::get_row_type() const
void ha_partition::print_error(int error, myf errflag)
{
+ THD *thd= ha_thd();
DBUG_ENTER("ha_partition::print_error");
/* Should probably look for my own errors first */
DBUG_PRINT("enter", ("error: %d", error));
- if (error == HA_ERR_NO_PARTITION_FOUND)
+ if (error == HA_ERR_NO_PARTITION_FOUND &&
+ thd->lex->sql_command != SQLCOM_TRUNCATE)
m_part_info->print_no_partition_found(table);
else
m_file[m_last_part]->print_error(error, errflag);
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index f47dfe8f621..ea1ef4d05fc 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1071,12 +1071,13 @@ public:
virtual int backup(TD* thd, HA_CHECK_OPT *check_opt);
virtual int restore(THD* thd, HA_CHECK_OPT *check_opt);
- virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt);
- virtual int preload_keys(THD *thd, HA_CHECK_OPT *check_opt);
virtual int dump(THD* thd, int fd = -1);
virtual int net_read_dump(NET* net);
virtual uint checksum() const;
*/
+ /* Enabled keycache for performance reasons, WL#4571 */
+ virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt);
+ virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
/*
-------------------------------------------------------------------------
diff --git a/sql/handler.cc b/sql/handler.cc
index 24ada69ff87..6aa6450cbb8 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1313,7 +1313,7 @@ int ha_rollback_trans(THD *thd, bool all)
trans->ha_list= 0;
trans->no_2pc=0;
if (is_real_trans && thd->transaction_rollback_request)
- thd->transaction.xid_state.rm_error= thd->main_da.sql_errno();
+ thd->transaction.xid_state.rm_error= thd->stmt_da->sql_errno();
if (all)
thd->variables.tx_isolation=thd->session_tx_isolation;
}
@@ -1944,23 +1944,28 @@ const char *get_canonical_filename(handler *file, const char *path,
struct Ha_delete_table_error_handler: public Internal_error_handler
{
public:
- virtual bool handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
char buff[MYSQL_ERRMSG_SIZE];
};
bool
Ha_delete_table_error_handler::
-handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
-{
+handle_condition(THD *,
+ uint,
+ const char*,
+ MYSQL_ERROR::enum_warning_level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
+{
+ *cond_hdl= NULL;
/* Grab the error message */
- strmake(buff, message, sizeof(buff)-1);
+ strmake(buff, msg, sizeof(buff)-1);
return TRUE;
}
@@ -2019,7 +2024,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
XXX: should we convert *all* errors to warnings here?
What if the error is fatal?
*/
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, error,
ha_delete_table_error_handler.buff);
}
delete file;
@@ -2772,6 +2777,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_TABLE_NEEDS_UPGRADE:
textno=ER_TABLE_NEEDS_UPGRADE;
break;
+ case HA_ERR_NO_PARTITION_FOUND:
+ textno=ER_WRONG_PARTITION_NAME;
+ break;
case HA_ERR_TABLE_READONLY:
textno= ER_OPEN_AS_READONLY;
break;
diff --git a/sql/item.cc b/sql/item.cc
index 26df3a45971..e56364beee3 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -4782,7 +4782,6 @@ String *Item::check_well_formed_result(String *str, bool send_error)
{
THD *thd= current_thd;
char hexbuf[7];
- enum MYSQL_ERROR::enum_warning_level level;
uint diff= str->length() - wlen;
set_if_smaller(diff, 3);
octet2hex(hexbuf, str->ptr() + wlen, diff);
@@ -4795,16 +4794,14 @@ String *Item::check_well_formed_result(String *str, bool send_error)
if ((thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
- level= MYSQL_ERROR::WARN_LEVEL_ERROR;
null_value= 1;
str= 0;
}
else
{
- level= MYSQL_ERROR::WARN_LEVEL_WARN;
str->length(wlen);
}
- push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_INVALID_CHARACTER_STRING,
ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf);
}
return str;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 7991d9adf82..2f80d16b928 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -927,10 +927,10 @@ protected:
};
-class Create_func_format : public Create_func_arg2
+class Create_func_format : public Create_native_func
{
public:
- virtual Item *create(THD *thd, Item *arg1, Item *arg2);
+ virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
static Create_func_format s_singleton;
@@ -3352,9 +3352,34 @@ Create_func_floor::create(THD *thd, Item *arg1)
Create_func_format Create_func_format::s_singleton;
Item*
-Create_func_format::create(THD *thd, Item *arg1, Item *arg2)
+Create_func_format::create_native(THD *thd, LEX_STRING name,
+ List<Item> *item_list)
{
- return new (thd->mem_root) Item_func_format(arg1, arg2);
+ Item *func= NULL;
+ int arg_count= item_list ? item_list->elements : 0;
+
+ switch (arg_count) {
+ case 2:
+ {
+ Item *param_1= item_list->pop();
+ Item *param_2= item_list->pop();
+ func= new (thd->mem_root) Item_func_format(param_1, param_2);
+ break;
+ }
+ case 3:
+ {
+ Item *param_1= item_list->pop();
+ Item *param_2= item_list->pop();
+ Item *param_3= item_list->pop();
+ func= new (thd->mem_root) Item_func_format(param_1, param_2, param_3);
+ break;
+ }
+ default:
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+ break;
+ }
+
+ return func;
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index c775848cff2..cf499aaf93c 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -599,7 +599,7 @@ void Item_func::signal_divide_by_null()
{
THD *thd= current_thd;
if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_DIVISION_BY_ZERO,
ER(ER_DIVISION_BY_ZERO));
null_value= 1;
}
@@ -1054,7 +1054,7 @@ my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
return dec;
err:
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE),
name, 1);
@@ -3667,7 +3667,7 @@ longlong Item_func_benchmark::val_int()
{
char buff[22];
llstr(((longlong) loop_count), buff);
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
"count", buff, "benchmark");
}
@@ -5810,12 +5810,12 @@ Item_func_sp::func_name() const
}
-int my_missing_function_error(const LEX_STRING &token, const char *func_name)
+void my_missing_function_error(const LEX_STRING &token, const char *func_name)
{
if (token.length && is_lex_native_function (&token))
- return my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
+ my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
else
- return my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name);
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 39c4b8e7033..d4ef55e5609 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -528,11 +528,11 @@ String *Item_func_des_encrypt::val_str(String *str)
return &tmp_value;
error:
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
code, ER(code),
"des_encrypt");
#else
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
"des_encrypt","--with-openssl");
#endif /* HAVE_OPENSSL */
@@ -605,12 +605,12 @@ String *Item_func_des_decrypt::val_str(String *str)
return &tmp_value;
error:
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
code, ER(code),
"des_decrypt");
wrong_key:
#else
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED),
"des_decrypt","--with-openssl");
#endif /* HAVE_OPENSSL */
@@ -2040,9 +2040,22 @@ String *Item_func_soundex::val_str(String *str)
const int FORMAT_MAX_DECIMALS= 30;
-Item_func_format::Item_func_format(Item *org, Item *dec)
-: Item_str_func(org, dec)
+
+MY_LOCALE *Item_func_format::get_locale(Item *item)
{
+ DBUG_ASSERT(arg_count == 3);
+ String tmp, *locale_name= args[2]->val_str(&tmp);
+ MY_LOCALE *lc;
+ if (!locale_name ||
+ !(lc= my_locale_by_name(locale_name->c_ptr_safe())))
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_UNKNOWN_LOCALE,
+ ER(ER_UNKNOWN_LOCALE),
+ locale_name ? locale_name->c_ptr_safe() : "NULL");
+ lc= &my_locale_en_US;
+ }
+ return lc;
}
void Item_func_format::fix_length_and_dec()
@@ -2052,6 +2065,10 @@ void Item_func_format::fix_length_and_dec()
collation.set(default_charset());
max_length= (char_length + max_sep_count + decimals) *
collation.collation->mbmaxlen;
+ if (arg_count == 3)
+ locale= args[2]->basic_const_item() ? get_locale(args[2]) : NULL;
+ else
+ locale= &my_locale_en_US; /* Two arguments */
}
@@ -2063,13 +2080,12 @@ void Item_func_format::fix_length_and_dec()
String *Item_func_format::val_str(String *str)
{
- uint32 length;
uint32 str_length;
/* Number of decimal digits */
int dec;
/* Number of characters used to represent the decimals, including '.' */
uint32 dec_length;
- int diff;
+ MY_LOCALE *lc;
DBUG_ASSERT(fixed == 1);
dec= (int) args[1]->val_int();
@@ -2079,6 +2095,8 @@ String *Item_func_format::val_str(String *str)
return NULL;
}
+ lc= locale ? locale : get_locale(args[2]);
+
dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS);
dec_length= dec ? dec+1 : 0;
null_value=0;
@@ -2093,8 +2111,6 @@ String *Item_func_format::val_str(String *str)
my_decimal_round(E_DEC_FATAL_ERROR, res, dec, false, &rnd_dec);
my_decimal2string(E_DEC_FATAL_ERROR, &rnd_dec, 0, 0, 0, str);
str_length= str->length();
- if (rnd_dec.sign())
- str_length--;
}
else
{
@@ -2107,31 +2123,51 @@ String *Item_func_format::val_str(String *str)
if (isnan(nr))
return str;
str_length=str->length();
- if (nr < 0)
- str_length--; // Don't count sign
- }
- /* We need this test to handle 'nan' values */
- if (str_length >= dec_length+4)
- {
- char *tmp,*pos;
- length= str->length()+(diff=((int)(str_length- dec_length-1))/3);
- str= copy_if_not_alloced(&tmp_str,str,length);
- str->length(length);
- tmp= (char*) str->ptr()+length - dec_length-1;
- for (pos= (char*) str->ptr()+length-1; pos != tmp; pos--)
- pos[0]= pos[-diff];
- while (diff)
+ }
+ /* We need this test to handle 'nan' and short values */
+ if (lc->grouping[0] > 0 &&
+ str_length >= dec_length + 1 + lc->grouping[0])
+ {
+ char buf[DECIMAL_MAX_STR_LENGTH * 2]; /* 2 - in the worst case when grouping=1 */
+ int count;
+ const char *grouping= lc->grouping;
+ char sign_length= *str->ptr() == '-' ? 1 : 0;
+ const char *src= str->ptr() + str_length - dec_length - 1;
+ const char *src_begin= str->ptr() + sign_length;
+ char *dst= buf + sizeof(buf);
+
+ /* Put the fractional part */
+ if (dec)
+ {
+ dst-= (dec + 1);
+ *dst= lc->decimal_point;
+ memcpy(dst + 1, src + 2, dec);
+ }
+
+ /* Put the integer part with grouping */
+ for (count= *grouping; src >= src_begin; count--)
{
- *pos= *(pos - diff);
- pos--;
- *pos= *(pos - diff);
- pos--;
- *pos= *(pos - diff);
- pos--;
- pos[0]=',';
- pos--;
- diff--;
+ /*
+ When *grouping==0x80 (which means "end of grouping")
+ count will be initialized to -1 and
+ we'll never get into this "if" anymore.
+ */
+ if (!count)
+ {
+ *--dst= lc->thousand_sep;
+ if (grouping[1])
+ grouping++;
+ count= *grouping;
+ }
+ DBUG_ASSERT(dst > buf);
+ *--dst= *src--;
}
+
+ if (sign_length) /* Put '-' */
+ *--dst= *str->ptr();
+
+ /* Put the rest of the integer part without grouping */
+ str->copy(dst, buf + sizeof(buf) - dst, &my_charset_latin1);
}
return str;
}
@@ -3237,7 +3273,7 @@ longlong Item_func_uncompressed_length::val_int()
*/
if (res->length() <= 4)
{
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ZLIB_Z_DATA_ERROR,
ER(ER_ZLIB_Z_DATA_ERROR));
null_value= 1;
@@ -3314,7 +3350,7 @@ String *Item_func_compress::val_str(String *str)
(const Bytef*)res->ptr(), res->length())) != Z_OK)
{
code= err==Z_MEM_ERROR ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_BUF_ERROR;
- push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
+ push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,code,ER(code));
null_value= 1;
return 0;
}
@@ -3352,7 +3388,7 @@ String *Item_func_uncompress::val_str(String *str)
/* If length is less than 4 bytes, data is corrupt */
if (res->length() <= 4)
{
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ZLIB_Z_DATA_ERROR,
ER(ER_ZLIB_Z_DATA_ERROR));
goto err;
@@ -3362,7 +3398,7 @@ String *Item_func_uncompress::val_str(String *str)
new_size= uint4korr(res->ptr()) & 0x3FFFFFFF;
if (new_size > current_thd->variables.max_allowed_packet)
{
- push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_BIG_FOR_UNCOMPRESS,
ER(ER_TOO_BIG_FOR_UNCOMPRESS),
current_thd->variables.max_allowed_packet);
@@ -3380,7 +3416,7 @@ String *Item_func_uncompress::val_str(String *str)
code= ((err == Z_BUF_ERROR) ? ER_ZLIB_Z_BUF_ERROR :
((err == Z_MEM_ERROR) ? ER_ZLIB_Z_MEM_ERROR : ER_ZLIB_Z_DATA_ERROR));
- push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_ERROR,code,ER(code));
+ push_warning(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,code,ER(code));
err:
null_value= 1;
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 2cdb45100ae..87d8c7bd438 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -498,8 +498,13 @@ public:
class Item_func_format :public Item_str_func
{
String tmp_str;
+ MY_LOCALE *locale;
public:
- Item_func_format(Item *org, Item *dec);
+ Item_func_format(Item *org, Item *dec): Item_str_func(org, dec) {}
+ Item_func_format(Item *org, Item *dec, Item *lang):
+ Item_str_func(org, dec, lang) {}
+
+ MY_LOCALE *get_locale(Item *item);
String *val_str(String *);
void fix_length_and_dec();
const char *func_name() const { return "format"; }
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 08a48c6ce2f..c8576722c69 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -374,6 +374,7 @@ Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
args= NULL;
}
mark_as_sum_func();
+ init_aggregator();
list.empty(); // Fields are used
}
@@ -405,6 +406,10 @@ Item_sum::Item_sum(THD *thd, Item_sum *item):
}
memcpy(args, item->args, sizeof(Item*)*arg_count);
memcpy(orig_args, item->orig_args, sizeof(Item*)*arg_count);
+ init_aggregator();
+ with_distinct= item->with_distinct;
+ if (item->aggr)
+ set_aggregator(item->aggr->Aggrtype());
}
@@ -550,13 +555,513 @@ void Item_sum::update_used_tables ()
}
-Item *Item_sum::set_arg(int i, THD *thd, Item *new_val)
+Item *Item_sum::set_arg(uint i, THD *thd, Item *new_val)
{
thd->change_item_tree(args + i, new_val);
return new_val;
}
+int Item_sum::set_aggregator(Aggregator::Aggregator_type aggregator)
+{
+ switch (aggregator)
+ {
+ case Aggregator::DISTINCT_AGGREGATOR:
+ aggr= new Aggregator_distinct(this);
+ break;
+
+ case Aggregator::SIMPLE_AGGREGATOR:
+ aggr= new Aggregator_simple(this);
+ break;
+ };
+ return aggr ? FALSE : TRUE;
+}
+
+
+void Item_sum::cleanup()
+{
+ if (aggr)
+ {
+ delete aggr;
+ aggr= NULL;
+ }
+ Item_result_field::cleanup();
+ forced_const= FALSE;
+}
+
+
+/**
+ Compare keys consisting of single field that cannot be compared as binary.
+
+ Used by the Unique class to compare keys. Will do correct comparisons
+ for all field types.
+
+ @param arg Pointer to the relevant Field class instance
+ @param key1 left key image
+ @param key2 right key image
+ @return comparison result
+ @retval < 0 if key1 < key2
+ @retval = 0 if key1 = key2
+ @retval > 0 if key1 > key2
+*/
+
+static int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2)
+{
+ Field *f= (Field*) arg;
+ return f->cmp(key1, key2);
+}
+
+
+/**
+ Correctly compare composite keys.
+
+ Used by the Unique class to compare keys. Will do correct comparisons
+ for composite keys with various field types.
+
+ @param arg Pointer to the relevant Aggregator_distinct instance
+ @param key1 left key image
+ @param key2 right key image
+ @return comparison result
+ @retval <0 if key1 < key2
+ @retval =0 if key1 = key2
+ @retval >0 if key1 > key2
+*/
+
+int Aggregator_distinct::composite_key_cmp(void* arg, uchar* key1, uchar* key2)
+{
+ Aggregator_distinct *aggr= (Aggregator_distinct *) arg;
+ Field **field = aggr->table->field;
+ Field **field_end= field + aggr->table->s->fields;
+ uint32 *lengths=aggr->field_lengths;
+ for (; field < field_end; ++field)
+ {
+ Field* f = *field;
+ int len = *lengths++;
+ int res = f->cmp(key1, key2);
+ if (res)
+ return res;
+ key1 += len;
+ key2 += len;
+ }
+ return 0;
+}
+
+
+static enum enum_field_types
+calc_tmp_field_type(enum enum_field_types table_field_type,
+ Item_result result_type)
+{
+ /* Adjust tmp table type according to the chosen aggregation type */
+ switch (result_type) {
+ case STRING_RESULT:
+ case REAL_RESULT:
+ if (table_field_type != MYSQL_TYPE_FLOAT)
+ table_field_type= MYSQL_TYPE_DOUBLE;
+ break;
+ case INT_RESULT:
+ table_field_type= MYSQL_TYPE_LONGLONG;
+ /* fallthrough */
+ case DECIMAL_RESULT:
+ if (table_field_type != MYSQL_TYPE_LONGLONG)
+ table_field_type= MYSQL_TYPE_NEWDECIMAL;
+ break;
+ case ROW_RESULT:
+ default:
+ DBUG_ASSERT(0);
+ }
+ return table_field_type;
+}
+
+
+/***************************************************************************/
+
+C_MODE_START
+
+/* Declarations for auxilary C-callbacks */
+
+static int simple_raw_key_cmp(void* arg, const void* key1, const void* key2)
+{
+ return memcmp(key1, key2, *(uint *) arg);
+}
+
+
+static int item_sum_distinct_walk(void *element, element_count num_of_dups,
+ void *item)
+{
+ return ((Aggregator_distinct*) (item))->unique_walk_function(element);
+}
+
+C_MODE_END
+
+/***************************************************************************/
+/**
+ Called before feeding the first row. Used to allocate/setup
+ the internal structures used for aggregation.
+
+ @param thd Thread descriptor
+ @return status
+ @retval FALSE success
+ @retval TRUE faliure
+
+ Prepares Aggregator_distinct to process the incoming stream.
+ Creates the temporary table and the Unique class if needed.
+ Called by Item_sum::aggregator_setup()
+*/
+
+bool Aggregator_distinct::setup(THD *thd)
+{
+ endup_done= FALSE;
+ /*
+ Setup can be called twice for ROLLUP items. This is a bug.
+ Please add DBUG_ASSERT(tree == 0) here when it's fixed.
+ */
+ if (tree || table || tmp_table_param)
+ return FALSE;
+
+ if (item_sum->setup(thd))
+ return TRUE;
+ if (item_sum->sum_func() == Item_sum::COUNT_FUNC ||
+ item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC)
+ {
+ List<Item> list;
+ SELECT_LEX *select_lex= thd->lex->current_select;
+
+ if (!(tmp_table_param= new TMP_TABLE_PARAM))
+ return TRUE;
+
+ /* Create a table with an unique key over all parameters */
+ for (uint i=0; i < item_sum->get_arg_count() ; i++)
+ {
+ Item *item=item_sum->get_arg(i);
+ if (list.push_back(item))
+ return TRUE; // End of memory
+ if (item->const_item() && item->is_null())
+ always_null=1;
+ }
+ if (always_null)
+ return FALSE;
+ count_field_types(select_lex,tmp_table_param,list,0);
+ tmp_table_param->force_copy_fields= item_sum->force_copy_fields;
+ DBUG_ASSERT(table == 0);
+ /*
+ Make create_tmp_table() convert BIT columns to BIGINT.
+ This is needed because BIT fields store parts of their data in table's
+ null bits, and we don't have methods to compare two table records, which
+ is needed by Unique which is used when HEAP table is used.
+ */
+ {
+ List_iterator_fast<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (item->type() == Item::FIELD_ITEM &&
+ ((Item_field*)item)->field->type() == FIELD_TYPE_BIT)
+ item->marker=4;
+ }
+ }
+ if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
+ 0,
+ (select_lex->options | thd->options),
+ HA_POS_ERROR, (char*)"")))
+ return TRUE;
+ table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
+ table->no_rows=1;
+
+ if (table->s->db_type() == heap_hton)
+ {
+ /*
+ No blobs, otherwise it would have been MyISAM: set up a compare
+ function and its arguments to use with Unique.
+ */
+ qsort_cmp2 compare_key;
+ void* cmp_arg;
+ Field **field= table->field;
+ Field **field_end= field + table->s->fields;
+ bool all_binary= TRUE;
+
+ for (tree_key_length= 0; field < field_end; ++field)
+ {
+ Field *f= *field;
+ enum enum_field_types type= f->type();
+ tree_key_length+= f->pack_length();
+ if ((type == MYSQL_TYPE_VARCHAR) ||
+ (!f->binary() && (type == MYSQL_TYPE_STRING ||
+ type == MYSQL_TYPE_VAR_STRING)))
+ {
+ all_binary= FALSE;
+ break;
+ }
+ }
+ if (all_binary)
+ {
+ cmp_arg= (void*) &tree_key_length;
+ compare_key= (qsort_cmp2) simple_raw_key_cmp;
+ }
+ else
+ {
+ if (table->s->fields == 1)
+ {
+ /*
+ If we have only one field, which is the most common use of
+ count(distinct), it is much faster to use a simpler key
+ compare method that can take advantage of not having to worry
+ about other fields.
+ */
+ compare_key= (qsort_cmp2) simple_str_key_cmp;
+ cmp_arg= (void*) table->field[0];
+ /* tree_key_length has been set already */
+ }
+ else
+ {
+ uint32 *length;
+ compare_key= (qsort_cmp2) composite_key_cmp;
+ cmp_arg= (void*) this;
+ field_lengths= (uint32*) thd->alloc(table->s->fields * sizeof(uint32));
+ for (tree_key_length= 0, length= field_lengths, field= table->field;
+ field < field_end; ++field, ++length)
+ {
+ *length= (*field)->pack_length();
+ tree_key_length+= *length;
+ }
+ }
+ }
+ DBUG_ASSERT(tree == 0);
+ tree= new Unique(compare_key, cmp_arg, tree_key_length,
+ thd->variables.max_heap_table_size);
+ /*
+ The only time tree_key_length could be 0 is if someone does
+ count(distinct) on a char(0) field - stupid thing to do,
+ but this has to be handled - otherwise someone can crash
+ the server with a DoS attack
+ */
+ if (! tree)
+ return TRUE;
+ }
+ return FALSE;
+ }
+ else
+ {
+ List<Create_field> field_list;
+ Create_field field_def; /* field definition */
+ Item *arg;
+ DBUG_ENTER("Item_sum_distinct::setup");
+ /* It's legal to call setup() more than once when in a subquery */
+ if (tree)
+ return FALSE;
+
+ /*
+ Virtual table and the tree are created anew on each re-execution of
+ PS/SP. Hence all further allocations are performed in the runtime
+ mem_root.
+ */
+ if (field_list.push_back(&field_def))
+ return TRUE;
+
+ item_sum->null_value= item_sum->maybe_null= 1;
+ item_sum->quick_group= 0;
+
+ DBUG_ASSERT(item_sum->get_arg(0)->fixed);
+
+ arg = item_sum->get_arg(0);
+ if (arg->const_item())
+ {
+ (void) arg->val_int();
+ if (arg->null_value)
+ always_null=1;
+ }
+
+ if (always_null)
+ return FALSE;
+
+ enum enum_field_types field_type;
+
+ field_type= calc_tmp_field_type(arg->field_type(),
+ arg->result_type());
+ field_def.init_for_tmp_table(field_type,
+ arg->max_length,
+ arg->decimals,
+ arg->maybe_null,
+ arg->unsigned_flag);
+
+ if (! (table= create_virtual_tmp_table(thd, field_list)))
+ return TRUE;
+
+ /* XXX: check that the case of CHAR(0) works OK */
+ tree_key_length= table->s->reclength - table->s->null_bytes;
+
+ /*
+ Unique handles all unique elements in a tree until they can't fit
+ in. Then the tree is dumped to the temporary file. We can use
+ simple_raw_key_cmp because the table contains numbers only; decimals
+ are converted to binary representation as well.
+ */
+ tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
+ thd->variables.max_heap_table_size);
+
+ DBUG_RETURN(tree == 0);
+ }
+}
+
+
+/**
+ Invalidate calculated value and clear the distinct rows.
+
+ Frees space used by the internal data structures.
+ Removes the accumulated distinct rows. Invalidates the calculated result.
+*/
+
+void Aggregator_distinct::clear()
+{
+ endup_done= FALSE;
+ item_sum->clear();
+ if (tree)
+ tree->reset();
+ /* tree and table can be both null only if always_null */
+ if (item_sum->sum_func() == Item_sum::COUNT_FUNC ||
+ item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC)
+ {
+ if (!tree && table)
+ {
+ table->file->extra(HA_EXTRA_NO_CACHE);
+ table->file->ha_delete_all_rows();
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ }
+ }
+ else
+ {
+ item_sum->null_value= 1;
+ }
+}
+
+
+/**
+ Process incoming row.
+
+ Add it to Unique/temp hash table if it's unique. Skip the row if
+ not unique.
+ Prepare Aggregator_distinct to process the incoming stream.
+ Create the temporary table and the Unique class if needed.
+ Called by Item_sum::aggregator_add().
+ To actually get the result value in item_sum's buffers
+ Aggregator_distinct::endup() must be called.
+
+ @return status
+ @retval FALSE success
+ @retval TRUE failure
+*/
+
+bool Aggregator_distinct::add()
+{
+ if (always_null)
+ return 0;
+
+ if (item_sum->sum_func() == Item_sum::COUNT_FUNC ||
+ item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC)
+ {
+ int error;
+ copy_fields(tmp_table_param);
+ copy_funcs(tmp_table_param->items_to_copy);
+
+ for (Field **field=table->field ; *field ; field++)
+ if ((*field)->is_real_null(0))
+ return 0; // Don't count NULL
+
+ if (tree)
+ {
+ /*
+ The first few bytes of record (at least one) are just markers
+ for deleted and NULLs. We want to skip them since they will
+ bloat the tree without providing any valuable info. Besides,
+ key_length used to initialize the tree didn't include space for them.
+ */
+ return tree->unique_add(table->record[0] + table->s->null_bytes);
+ }
+ if ((error= table->file->ha_write_row(table->record[0])) &&
+ table->file->is_fatal_error(error, HA_CHECK_DUP))
+ return TRUE;
+ return FALSE;
+ }
+ else
+ {
+ item_sum->get_arg(0)->save_in_field(table->field[0], FALSE);
+ if (table->field[0]->is_null())
+ return 0;
+ DBUG_ASSERT(tree);
+ item_sum->null_value= 0;
+ /*
+ '0' values are also stored in the tree. This doesn't matter
+ for SUM(DISTINCT), but is important for AVG(DISTINCT)
+ */
+ return tree->unique_add(table->field[0]->ptr);
+ }
+}
+
+
+/**
+ Calculate the aggregate function value.
+
+ Since Distinct_aggregator::add() just collects the distinct rows,
+ we must go over the distinct rows and feed them to the aggregation
+ function before returning its value.
+ This is what endup () does. It also sets the result validity flag
+ endup_done to TRUE so it will not recalculate the aggregate value
+ again if the Item_sum hasn't been reset.
+*/
+
+void Aggregator_distinct::endup()
+{
+ /* prevent consecutive recalculations */
+ if (endup_done)
+ return;
+
+ /* we are going to calculate the aggregate value afresh */
+ item_sum->clear();
+
+ /* The result will definitely be null : no more calculations needed */
+ if (always_null)
+ return;
+
+ if (item_sum->sum_func() == Item_sum::COUNT_FUNC ||
+ item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC)
+ {
+ DBUG_ASSERT(item_sum->fixed == 1);
+ Item_sum_count *sum= (Item_sum_count *)item_sum;
+ if (tree && tree->elements == 0)
+ {
+ /* everything fits in memory */
+ sum->count= (longlong) tree->elements_in_tree();
+ endup_done= TRUE;
+ }
+ if (!tree)
+ {
+ /* there were blobs */
+ table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ sum->count= table->file->stats.records;
+ endup_done= TRUE;
+ }
+ }
+ else
+ {
+ /*
+ We don't have a tree only if 'setup()' hasn't been called;
+ this is the case of sql_select.cc:return_zero_rows.
+ */
+ if (tree)
+ table->field[0]->set_notnull();
+ }
+
+ if (tree && !endup_done)
+ {
+ /* go over the tree of distinct keys and calculate the aggregate value */
+ use_distinct_values= TRUE;
+ tree->walk(item_sum_distinct_walk, (void*) this);
+ use_distinct_values= FALSE;
+ }
+ /* prevent consecutive recalculations */
+ endup_done= TRUE;
+}
+
+
String *
Item_sum_num::val_str(String *str)
{
@@ -823,10 +1328,27 @@ void Item_sum_sum::fix_length_and_dec()
bool Item_sum_sum::add()
{
DBUG_ENTER("Item_sum_sum::add");
+ bool arg_is_null;
if (hybrid_type == DECIMAL_RESULT)
{
- my_decimal value, *val= args[0]->val_decimal(&value);
- if (!args[0]->null_value)
+ my_decimal value, *val;
+ if (aggr->use_distinct_values)
+ {
+ /*
+ We are aggregating distinct rows. Get the value from the distinct
+ table pointer
+ */
+ Aggregator_distinct *daggr= (Aggregator_distinct *)aggr;
+ val= daggr->table->field[0]->val_decimal (&value);
+ arg_is_null= daggr->table->field[0]->is_null();
+ }
+ else
+ {
+ /* non-distinct aggregation */
+ val= args[0]->val_decimal(&value);
+ arg_is_null= args[0]->null_value;
+ }
+ if (!arg_is_null)
{
my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff^1),
val, dec_buffs + curr_dec_buff);
@@ -836,8 +1358,25 @@ bool Item_sum_sum::add()
}
else
{
- sum+= args[0]->val_real();
- if (!args[0]->null_value)
+ double val;
+ if (aggr->use_distinct_values)
+ {
+ /*
+ We are aggregating distinct rows. Get the value from the distinct
+ table pointer
+ */
+ Aggregator_distinct *daggr= (Aggregator_distinct *)aggr;
+ val= daggr->table->field[0]->val_real ();
+ arg_is_null= daggr->table->field[0]->is_null();
+ }
+ else
+ {
+ /* non-distinct aggregation */
+ val= args[0]->val_real();
+ arg_is_null= args[0]->null_value;
+ }
+ sum+= val;
+ if (!arg_is_null)
null_value= 0;
}
DBUG_RETURN(0);
@@ -847,6 +1386,8 @@ bool Item_sum_sum::add()
longlong Item_sum_sum::val_int()
{
DBUG_ASSERT(fixed == 1);
+ if (aggr)
+ aggr->endup();
if (hybrid_type == DECIMAL_RESULT)
{
longlong result;
@@ -861,6 +1402,8 @@ longlong Item_sum_sum::val_int()
double Item_sum_sum::val_real()
{
DBUG_ASSERT(fixed == 1);
+ if (aggr)
+ aggr->endup();
if (hybrid_type == DECIMAL_RESULT)
my_decimal2double(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, &sum);
return sum;
@@ -869,6 +1412,8 @@ double Item_sum_sum::val_real()
String *Item_sum_sum::val_str(String *str)
{
+ if (aggr)
+ aggr->endup();
if (hybrid_type == DECIMAL_RESULT)
return val_string_from_decimal(str);
return val_string_from_real(str);
@@ -877,311 +1422,54 @@ String *Item_sum_sum::val_str(String *str)
my_decimal *Item_sum_sum::val_decimal(my_decimal *val)
{
+ if (aggr)
+ aggr->endup();
if (hybrid_type == DECIMAL_RESULT)
return (dec_buffs + curr_dec_buff);
return val_decimal_from_real(val);
}
-/***************************************************************************/
-
-C_MODE_START
-
-/* Declarations for auxilary C-callbacks */
-
-static int simple_raw_key_cmp(void* arg, const void* key1, const void* key2)
-{
- return memcmp(key1, key2, *(uint *) arg);
-}
-
-
-static int item_sum_distinct_walk(void *element, element_count num_of_dups,
- void *item)
-{
- return ((Item_sum_distinct*) (item))->unique_walk_function(element);
-}
-
-C_MODE_END
-
-/* Item_sum_distinct */
-
-Item_sum_distinct::Item_sum_distinct(Item *item_arg)
- :Item_sum_num(item_arg), tree(0)
-{
- /*
- quick_group is an optimizer hint, which means that GROUP BY can be
- handled with help of index on grouped columns.
- By setting quick_group to zero we force creation of temporary table
- to perform GROUP BY.
- */
- quick_group= 0;
-}
-
-
-Item_sum_distinct::Item_sum_distinct(THD *thd, Item_sum_distinct *original)
- :Item_sum_num(thd, original), val(original->val), tree(0),
- table_field_type(original->table_field_type)
-{
- quick_group= 0;
-}
-
-
/**
- Behaves like an Integer except to fix_length_and_dec().
- Additionally div() converts val with this traits to a val with true
- decimal traits along with conversion of integer value to decimal value.
- This is to speedup SUM/AVG(DISTINCT) evaluation for 8-32 bit integer
- values.
+ Aggregate a distinct row from the distinct hash table.
+
+ Called for each row into the hash table 'Aggregator_distinct::table'.
+ Includes the current distinct row into the calculation of the
+ aggregate value. Uses the Field classes to get the value from the row.
+ This function is used for AVG/SUM(DISTINCT). For COUNT(DISTINCT)
+ it's called only when there are no blob arguments and the data don't
+ fit into memory (so Unique makes persisted trees on disk).
+
+ @param element pointer to the row data.
+
+ @return status
+ @retval FALSE success
+ @retval TRUE failure
*/
-struct Hybrid_type_traits_fast_decimal: public
- Hybrid_type_traits_integer
-{
- virtual Item_result type() const { return DECIMAL_RESULT; }
- virtual void fix_length_and_dec(Item *item, Item *arg) const
- { Hybrid_type_traits_decimal::instance()->fix_length_and_dec(item, arg); }
-
- virtual void div(Hybrid_type *val, ulonglong u) const
- {
- int2my_decimal(E_DEC_FATAL_ERROR, val->integer, 0, val->dec_buf);
- val->used_dec_buf_no= 0;
- val->traits= Hybrid_type_traits_decimal::instance();
- val->traits->div(val, u);
- }
- static const Hybrid_type_traits_fast_decimal *instance();
- Hybrid_type_traits_fast_decimal() {};
-};
-
-static const Hybrid_type_traits_fast_decimal fast_decimal_traits_instance;
-
-const Hybrid_type_traits_fast_decimal
- *Hybrid_type_traits_fast_decimal::instance()
-{
- return &fast_decimal_traits_instance;
-}
-
-void Item_sum_distinct::fix_length_and_dec()
+
+bool Aggregator_distinct::unique_walk_function(void *element)
{
- DBUG_ASSERT(args[0]->fixed);
-
- table_field_type= args[0]->field_type();
-
- /* Adjust tmp table type according to the chosen aggregation type */
- switch (args[0]->result_type()) {
- case STRING_RESULT:
- case REAL_RESULT:
- val.traits= Hybrid_type_traits::instance();
- if (table_field_type != MYSQL_TYPE_FLOAT)
- table_field_type= MYSQL_TYPE_DOUBLE;
- break;
- case INT_RESULT:
- /*
- Preserving int8, int16, int32 field types gives ~10% performance boost
- as the size of result tree becomes significantly smaller.
- Another speed up we gain by using longlong for intermediate
- calculations. The range of int64 is enough to hold sum 2^32 distinct
- integers each <= 2^32.
- */
- if (table_field_type == MYSQL_TYPE_INT24 ||
- (table_field_type >= MYSQL_TYPE_TINY &&
- table_field_type <= MYSQL_TYPE_LONG))
- {
- val.traits= Hybrid_type_traits_fast_decimal::instance();
- break;
- }
- table_field_type= MYSQL_TYPE_LONGLONG;
- /* fallthrough */
- case DECIMAL_RESULT:
- val.traits= Hybrid_type_traits_decimal::instance();
- if (table_field_type != MYSQL_TYPE_LONGLONG)
- table_field_type= MYSQL_TYPE_NEWDECIMAL;
- break;
- case ROW_RESULT:
- default:
- DBUG_ASSERT(0);
- }
- val.traits->fix_length_and_dec(this, args[0]);
+ memcpy(table->field[0]->ptr, element, tree_key_length);
+ item_sum->add();
+ return 0;
}
-/**
- @todo
- check that the case of CHAR(0) works OK
-*/
-bool Item_sum_distinct::setup(THD *thd)
+Aggregator_distinct::~Aggregator_distinct()
{
- List<Create_field> field_list;
- Create_field field_def; /* field definition */
- DBUG_ENTER("Item_sum_distinct::setup");
- /* It's legal to call setup() more than once when in a subquery */
if (tree)
- DBUG_RETURN(FALSE);
-
- /*
- Virtual table and the tree are created anew on each re-execution of
- PS/SP. Hence all further allocations are performed in the runtime
- mem_root.
- */
- if (field_list.push_back(&field_def))
- DBUG_RETURN(TRUE);
-
- null_value= maybe_null= 1;
- quick_group= 0;
-
- DBUG_ASSERT(args[0]->fixed);
-
- field_def.init_for_tmp_table(table_field_type, args[0]->max_length,
- args[0]->decimals, args[0]->maybe_null,
- args[0]->unsigned_flag);
-
- if (! (table= create_virtual_tmp_table(thd, field_list)))
- DBUG_RETURN(TRUE);
-
- /* XXX: check that the case of CHAR(0) works OK */
- tree_key_length= table->s->reclength - table->s->null_bytes;
-
- /*
- Unique handles all unique elements in a tree until they can't fit
- in. Then the tree is dumped to the temporary file. We can use
- simple_raw_key_cmp because the table contains numbers only; decimals
- are converted to binary representation as well.
- */
- tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length,
- thd->variables.max_heap_table_size);
-
- is_evaluated= FALSE;
- DBUG_RETURN(tree == 0);
-}
-
-
-bool Item_sum_distinct::add()
-{
- args[0]->save_in_field(table->field[0], FALSE);
- is_evaluated= FALSE;
- if (!table->field[0]->is_null())
{
- DBUG_ASSERT(tree);
- null_value= 0;
- /*
- '0' values are also stored in the tree. This doesn't matter
- for SUM(DISTINCT), but is important for AVG(DISTINCT)
- */
- return tree->unique_add(table->field[0]->ptr);
+ delete tree;
+ tree= NULL;
}
- return 0;
-}
-
-
-bool Item_sum_distinct::unique_walk_function(void *element)
-{
- memcpy(table->field[0]->ptr, element, tree_key_length);
- ++count;
- val.traits->add(&val, table->field[0]);
- return 0;
-}
-
-
-void Item_sum_distinct::clear()
-{
- DBUG_ENTER("Item_sum_distinct::clear");
- DBUG_ASSERT(tree != 0); /* we always have a tree */
- null_value= 1;
- tree->reset();
- is_evaluated= FALSE;
- DBUG_VOID_RETURN;
-}
-
-void Item_sum_distinct::cleanup()
-{
- Item_sum_num::cleanup();
- delete tree;
- tree= 0;
- table= 0;
- is_evaluated= FALSE;
-}
-
-Item_sum_distinct::~Item_sum_distinct()
-{
- delete tree;
- /* no need to free the table */
-}
-
-
-void Item_sum_distinct::calculate_val_and_count()
-{
- if (!is_evaluated)
+ if (table)
{
- count= 0;
- val.traits->set_zero(&val);
- /*
- We don't have a tree only if 'setup()' hasn't been called;
- this is the case of sql_select.cc:return_zero_rows.
- */
- if (tree)
- {
- table->field[0]->set_notnull();
- tree->walk(item_sum_distinct_walk, (void*) this);
- }
- is_evaluated= TRUE;
+ free_tmp_table(table->in_use, table);
+ table=NULL;
}
-}
-
-
-double Item_sum_distinct::val_real()
-{
- calculate_val_and_count();
- return val.traits->val_real(&val);
-}
-
-
-my_decimal *Item_sum_distinct::val_decimal(my_decimal *to)
-{
- calculate_val_and_count();
- if (null_value)
- return 0;
- return val.traits->val_decimal(&val, to);
-}
-
-
-longlong Item_sum_distinct::val_int()
-{
- calculate_val_and_count();
- return val.traits->val_int(&val, unsigned_flag);
-}
-
-
-String *Item_sum_distinct::val_str(String *str)
-{
- calculate_val_and_count();
- if (null_value)
- return 0;
- return val.traits->val_str(&val, str, decimals);
-}
-
-/* end of Item_sum_distinct */
-
-/* Item_sum_avg_distinct */
-
-void
-Item_sum_avg_distinct::fix_length_and_dec()
-{
- Item_sum_distinct::fix_length_and_dec();
- prec_increment= current_thd->variables.div_precincrement;
- /*
- AVG() will divide val by count. We need to reserve digits
- after decimal point as the result can be fractional.
- */
- decimals= min(decimals + prec_increment, NOT_FIXED_DEC);
-}
-
-
-void
-Item_sum_avg_distinct::calculate_val_and_count()
-{
- if (!is_evaluated)
+ if (tmp_table_param)
{
- Item_sum_distinct::calculate_val_and_count();
- if (count)
- val.traits->div(&val, count);
- is_evaluated= TRUE;
+ delete tmp_table_param;
+ tmp_table_param= NULL;
}
}
@@ -1208,6 +1496,8 @@ bool Item_sum_count::add()
longlong Item_sum_count::val_int()
{
DBUG_ASSERT(fixed == 1);
+ if (aggr)
+ aggr->endup();
return (longlong) count;
}
@@ -1298,6 +1588,8 @@ bool Item_sum_avg::add()
double Item_sum_avg::val_real()
{
DBUG_ASSERT(fixed == 1);
+ if (aggr)
+ aggr->endup();
if (!count)
{
null_value=1;
@@ -1312,6 +1604,8 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val)
my_decimal sum_buff, cnt;
const my_decimal *sum_dec;
DBUG_ASSERT(fixed == 1);
+ if (aggr)
+ aggr->endup();
if (!count)
{
null_value=1;
@@ -1334,6 +1628,8 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val)
String *Item_sum_avg::val_str(String *str)
{
+ if (aggr)
+ aggr->endup();
if (hybrid_type == DECIMAL_RESULT)
return val_string_from_decimal(str);
return val_string_from_real(str);
@@ -2029,6 +2325,7 @@ void Item_sum_hybrid::reset_field()
void Item_sum_sum::reset_field()
{
+ DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
if (hybrid_type == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
@@ -2053,6 +2350,7 @@ void Item_sum_count::reset_field()
{
uchar *res=result_field->ptr;
longlong nr=0;
+ DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
if (!args[0]->maybe_null || !args[0]->is_null())
nr=1;
@@ -2063,6 +2361,7 @@ void Item_sum_count::reset_field()
void Item_sum_avg::reset_field()
{
uchar *res=result_field->ptr;
+ DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
if (hybrid_type == DECIMAL_RESULT)
{
longlong tmp;
@@ -2116,6 +2415,7 @@ void Item_sum_bit::update_field()
void Item_sum_sum::update_field()
{
+ DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
if (hybrid_type == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
@@ -2168,6 +2468,9 @@ void Item_sum_avg::update_field()
{
longlong field_count;
uchar *res=result_field->ptr;
+
+ DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR);
+
if (hybrid_type == DECIMAL_RESULT)
{
my_decimal value, *arg_val= args[0]->val_decimal(&value);
@@ -2470,318 +2773,6 @@ double Item_variance_field::val_real()
/****************************************************************************
-** COUNT(DISTINCT ...)
-****************************************************************************/
-
-int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2)
-{
- Field *f= (Field*) arg;
- return f->cmp(key1, key2);
-}
-
-/**
- Did not make this one static - at least gcc gets confused when
- I try to declare a static function as a friend. If you can figure
- out the syntax to make a static function a friend, make this one
- static
-*/
-
-int composite_key_cmp(void* arg, uchar* key1, uchar* key2)
-{
- Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
- Field **field = item->table->field;
- Field **field_end= field + item->table->s->fields;
- uint32 *lengths=item->field_lengths;
- for (; field < field_end; ++field)
- {
- Field* f = *field;
- int len = *lengths++;
- int res = f->cmp(key1, key2);
- if (res)
- return res;
- key1 += len;
- key2 += len;
- }
- return 0;
-}
-
-
-C_MODE_START
-
-static int count_distinct_walk(void *elem, element_count count, void *arg)
-{
- (*((ulonglong*)arg))++;
- return 0;
-}
-
-C_MODE_END
-
-
-void Item_sum_count_distinct::cleanup()
-{
- DBUG_ENTER("Item_sum_count_distinct::cleanup");
- Item_sum_int::cleanup();
-
- /* Free objects only if we own them. */
- if (!original)
- {
- /*
- We need to delete the table and the tree in cleanup() as
- they were allocated in the runtime memroot. Using the runtime
- memroot reduces memory footprint for PS/SP and simplifies setup().
- */
- delete tree;
- tree= 0;
- is_evaluated= FALSE;
- if (table)
- {
- free_tmp_table(table->in_use, table);
- table= 0;
- }
- delete tmp_table_param;
- tmp_table_param= 0;
- }
- always_null= FALSE;
- DBUG_VOID_RETURN;
-}
-
-
-/**
- This is used by rollup to create a separate usable copy of
- the function.
-*/
-
-void Item_sum_count_distinct::make_unique()
-{
- table=0;
- original= 0;
- force_copy_fields= 1;
- tree= 0;
- is_evaluated= FALSE;
- tmp_table_param= 0;
- always_null= FALSE;
-}
-
-
-Item_sum_count_distinct::~Item_sum_count_distinct()
-{
- cleanup();
-}
-
-
-bool Item_sum_count_distinct::setup(THD *thd)
-{
- List<Item> list;
- SELECT_LEX *select_lex= thd->lex->current_select;
-
- /*
- Setup can be called twice for ROLLUP items. This is a bug.
- Please add DBUG_ASSERT(tree == 0) here when it's fixed.
- It's legal to call setup() more than once when in a subquery
- */
- if (tree || table || tmp_table_param)
- return FALSE;
-
- if (!(tmp_table_param= new TMP_TABLE_PARAM))
- return TRUE;
-
- /* Create a table with an unique key over all parameters */
- for (uint i=0; i < arg_count ; i++)
- {
- Item *item=args[i];
- if (list.push_back(item))
- return TRUE; // End of memory
- if (item->const_item() && item->is_null())
- always_null= 1;
- }
- if (always_null)
- return FALSE;
- count_field_types(select_lex, tmp_table_param, list, 0);
- tmp_table_param->force_copy_fields= force_copy_fields;
- DBUG_ASSERT(table == 0);
- /*
- Make create_tmp_table() convert BIT columns to BIGINT.
- This is needed because BIT fields store parts of their data in table's
- null bits, and we don't have methods to compare two table records, which
- is needed by Unique which is used when HEAP table is used.
- */
- {
- List_iterator_fast<Item> li(list);
- Item *item;
- while ((item= li++))
- {
- if (item->type() == Item::FIELD_ITEM &&
- ((Item_field*)item)->field->type() == FIELD_TYPE_BIT)
- item->marker=4;
- }
- }
-
- if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
- 0,
- (select_lex->options | thd->options),
- HA_POS_ERROR, (char*)"")))
- return TRUE;
- table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
- table->no_rows=1;
-
- if (table->s->db_type() == heap_hton)
- {
- /*
- No blobs, otherwise it would have been MyISAM: set up a compare
- function and its arguments to use with Unique.
- */
- qsort_cmp2 compare_key;
- void* cmp_arg;
- Field **field= table->field;
- Field **field_end= field + table->s->fields;
- bool all_binary= TRUE;
-
- for (tree_key_length= 0; field < field_end; ++field)
- {
- Field *f= *field;
- enum enum_field_types f_type= f->type();
- tree_key_length+= f->pack_length();
- if ((f_type == MYSQL_TYPE_VARCHAR) ||
- (!f->binary() && (f_type == MYSQL_TYPE_STRING ||
- f_type == MYSQL_TYPE_VAR_STRING)))
- {
- all_binary= FALSE;
- break;
- }
- }
- if (all_binary)
- {
- cmp_arg= (void*) &tree_key_length;
- compare_key= (qsort_cmp2) simple_raw_key_cmp;
- }
- else
- {
- if (table->s->fields == 1)
- {
- /*
- If we have only one field, which is the most common use of
- count(distinct), it is much faster to use a simpler key
- compare method that can take advantage of not having to worry
- about other fields.
- */
- compare_key= (qsort_cmp2) simple_str_key_cmp;
- cmp_arg= (void*) table->field[0];
- /* tree_key_length has been set already */
- }
- else
- {
- uint32 *length;
- compare_key= (qsort_cmp2) composite_key_cmp;
- cmp_arg= (void*) this;
- field_lengths= (uint32*) thd->alloc(table->s->fields * sizeof(uint32));
- for (tree_key_length= 0, length= field_lengths, field= table->field;
- field < field_end; ++field, ++length)
- {
- *length= (*field)->pack_length();
- tree_key_length+= *length;
- }
- }
- }
- DBUG_ASSERT(tree == 0);
- tree= new Unique(compare_key, cmp_arg, tree_key_length,
- thd->variables.max_heap_table_size);
- /*
- The only time tree_key_length could be 0 is if someone does
- count(distinct) on a char(0) field - stupid thing to do,
- but this has to be handled - otherwise someone can crash
- the server with a DoS attack
- */
- is_evaluated= FALSE;
- if (! tree)
- return TRUE;
- }
- return FALSE;
-}
-
-
-Item *Item_sum_count_distinct::copy_or_same(THD* thd)
-{
- return new (thd->mem_root) Item_sum_count_distinct(thd, this);
-}
-
-
-void Item_sum_count_distinct::clear()
-{
- /* tree and table can be both null only if always_null */
- is_evaluated= FALSE;
- if (tree)
- {
- tree->reset();
- }
- else if (table)
- {
- table->file->extra(HA_EXTRA_NO_CACHE);
- table->file->ha_delete_all_rows();
- table->file->extra(HA_EXTRA_WRITE_CACHE);
- }
-}
-
-bool Item_sum_count_distinct::add()
-{
- int error;
- if (always_null)
- return 0;
- copy_fields(tmp_table_param);
- copy_funcs(tmp_table_param->items_to_copy);
-
- for (Field **field=table->field ; *field ; field++)
- if ((*field)->is_real_null(0))
- return 0; // Don't count NULL
-
- is_evaluated= FALSE;
- if (tree)
- {
- /*
- The first few bytes of record (at least one) are just markers
- for deleted and NULLs. We want to skip them since they will
- bloat the tree without providing any valuable info. Besides,
- key_length used to initialize the tree didn't include space for them.
- */
- return tree->unique_add(table->record[0] + table->s->null_bytes);
- }
- if ((error= table->file->ha_write_row(table->record[0])) &&
- table->file->is_fatal_error(error, HA_CHECK_DUP))
- return TRUE;
- return FALSE;
-}
-
-
-longlong Item_sum_count_distinct::val_int()
-{
- int error;
- DBUG_ASSERT(fixed == 1);
- if (!table) // Empty query
- return LL(0);
- if (tree)
- {
- if (is_evaluated)
- return count;
-
- if (tree->elements == 0)
- return (longlong) tree->elements_in_tree(); // everything fits in memory
- count= 0;
- tree->walk(count_distinct_walk, (void*) &count);
- is_evaluated= TRUE;
- return (longlong) count;
- }
-
- error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
-
- if(error)
- {
- table->file->print_error(error, MYF(0));
- }
-
- return table->file->stats.records;
-}
-
-
-/****************************************************************************
** Functions to handle dynamic loadable aggregates
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
** Adapted for UDAs by: Andreas F. Bobak <bobak@relog.ch>.
@@ -3102,6 +3093,8 @@ int dump_leaf_key(uchar* key, element_count count __attribute__((unused)),
result->append(*res);
}
+ item->row_count++;
+
/* stop if length of result more than max_length */
if (result->length() > item->max_length)
{
@@ -3120,8 +3113,11 @@ int dump_leaf_key(uchar* key, element_count count __attribute__((unused)),
result->length(),
&well_formed_error);
result->length(old_length + add_length);
- item->count_cut_values++;
item->warning_for_row= TRUE;
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_CUT_VALUE_GROUP_CONCAT, ER(ER_CUT_VALUE_GROUP_CONCAT),
+ item->row_count);
+
return 1;
}
return 0;
@@ -3141,12 +3137,12 @@ Item_func_group_concat::
Item_func_group_concat(Name_resolution_context *context_arg,
bool distinct_arg, List<Item> *select_list,
SQL_LIST *order_list, String *separator_arg)
- :tmp_table_param(0), warning(0),
- separator(separator_arg), tree(0), unique_filter(NULL), table(0),
+ :tmp_table_param(0), separator(separator_arg), tree(0),
+ unique_filter(NULL), table(0),
order(0), context(context_arg),
arg_count_order(order_list ? order_list->elements : 0),
arg_count_field(select_list->elements),
- count_cut_values(0),
+ row_count(0),
distinct(distinct_arg),
warning_for_row(FALSE),
force_copy_fields(0), original(0)
@@ -3200,7 +3196,6 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
Item_func_group_concat *item)
:Item_sum(thd, item),
tmp_table_param(item->tmp_table_param),
- warning(item->warning),
separator(item->separator),
tree(item->tree),
unique_filter(item->unique_filter),
@@ -3209,7 +3204,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
context(item->context),
arg_count_order(item->arg_count_order),
arg_count_field(item->arg_count_field),
- count_cut_values(item->count_cut_values),
+ row_count(item->row_count),
distinct(item->distinct),
warning_for_row(item->warning_for_row),
always_null(item->always_null),
@@ -3227,15 +3222,6 @@ void Item_func_group_concat::cleanup()
DBUG_ENTER("Item_func_group_concat::cleanup");
Item_sum::cleanup();
- /* Adjust warning message to include total number of cut values */
- if (warning)
- {
- char warn_buff[MYSQL_ERRMSG_SIZE];
- sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
- warning->set_msg(current_thd, warn_buff);
- warning= 0;
- }
-
/*
Free table and tree if they belong to this item (if item have not pointer
to original item from which was made copy => it own its objects )
@@ -3259,15 +3245,8 @@ void Item_func_group_concat::cleanup()
delete unique_filter;
unique_filter= NULL;
}
- if (warning)
- {
- char warn_buff[MYSQL_ERRMSG_SIZE];
- sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
- warning->set_msg(thd, warn_buff);
- warning= 0;
- }
}
- DBUG_ASSERT(tree == 0 && warning == 0);
+ DBUG_ASSERT(tree == 0);
}
DBUG_VOID_RETURN;
}
@@ -3556,17 +3535,6 @@ String* Item_func_group_concat::val_str(String* str)
/* Tree is used for sorting as in ORDER BY */
tree_walk(tree, (tree_walk_action)&dump_leaf_key, (void*)this,
left_root_right);
- if (count_cut_values && !warning)
- {
- /*
- ER_CUT_VALUE_GROUP_CONCAT needs an argument, but this gets set in
- Item_func_group_concat::cleanup().
- */
- DBUG_ASSERT(table);
- warning= push_warning(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_CUT_VALUE_GROUP_CONCAT,
- ER(ER_CUT_VALUE_GROUP_CONCAT));
- }
return &result;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index d991327d847..1dd1c5b5dd5 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -22,7 +22,87 @@
#include <my_tree.h>
-/*
+class Item_sum;
+class Aggregator_distinct;
+class Aggregator_simple;
+
+/**
+ The abstract base class for the Aggregator_* classes.
+ It implements the data collection functions (setup/add/clear)
+ as either pass-through to the real functionality or
+ as collectors into an Unique (for distinct) structure.
+
+ Note that update_field/reset_field are not in that
+ class, because they're simply not called when
+ GROUP BY/DISTINCT can be handled with help of index on grouped
+ fields (quick_group = 0);
+*/
+
+class Aggregator : public Sql_alloc
+{
+ friend class Item_sum;
+ friend class Item_sum_sum;
+ friend class Item_sum_count;
+ friend class Item_sum_avg;
+
+ /*
+ All members are protected as this class is not usable outside of an
+ Item_sum descendant.
+ */
+protected:
+ /* the aggregate function class to act on */
+ Item_sum *item_sum;
+
+ /**
+ When feeding back the data in endup() from Unique/temp table back to
+ Item_sum::add() methods we must read the data from Unique (and not
+ recalculate the functions that are given as arguments to the aggregate
+ function.
+ This flag is to tell the add() methods to take the data from the Unique
+ instead by calling the relevant val_..() method
+ */
+
+ bool use_distinct_values;
+
+public:
+ Aggregator (Item_sum *arg): item_sum(arg), use_distinct_values(FALSE) {}
+ virtual ~Aggregator () {} /* Keep gcc happy */
+
+ enum Aggregator_type { SIMPLE_AGGREGATOR, DISTINCT_AGGREGATOR };
+ virtual Aggregator_type Aggrtype() = 0;
+
+ /**
+ Called before adding the first row.
+ Allocates and sets up the internal aggregation structures used,
+ e.g. the Unique instance used to calculate distinct.
+ */
+ virtual bool setup(THD *) = 0;
+
+ /**
+ Called when we need to wipe out all the data from the aggregator :
+ all the values acumulated and all the state.
+ Cleans up the internal structures and resets them to their initial state.
+ */
+ virtual void clear() = 0;
+
+ /**
+ Called when there's a new value to be aggregated.
+ Updates the internal state of the aggregator to reflect the new value.
+ */
+ virtual bool add() = 0;
+
+ /**
+ Called when there are no more data and the final value is to be retrieved.
+ Finalises the state of the aggregator, so the final result can be retrieved.
+ */
+ virtual void endup() = 0;
+
+};
+
+
+class st_select_lex;
+
+/**
Class Item_sum is the base class used for special expressions that SQL calls
'set functions'. These expressions are formed with the help of aggregate
functions such as SUM, MAX, GROUP_CONCAT etc.
@@ -215,13 +295,32 @@
TODO: to catch queries where the limit is exceeded to make the
code clean here.
-*/
-
-class st_select_lex;
+*/
class Item_sum :public Item_result_field
{
public:
+ /**
+ Aggregator class instance. Not set initially. Allocated only after
+ it is determined if the incoming data are already distinct.
+ */
+ Aggregator *aggr;
+
+ /**
+ Used in making ROLLUP. Set for the ROLLUP copies of the original
+ Item_sum and passed to create_tmp_field() to cause it to work
+ over the temp table buffer that is referenced by
+ Item_result_field::result_field.
+ */
+ bool force_copy_fields;
+
+ /**
+ Indicates how the aggregate function was specified by the parser :
+ 1 if it was written as AGGREGATE(DISTINCT),
+ 0 if it was AGGREGATE()
+ */
+ bool with_distinct;
+
enum Sumfunctype
{ COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC,
AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, STD_FUNC,
@@ -263,47 +362,28 @@ public:
Item_sum() :quick_group(1), arg_count(0), forced_const(FALSE)
{
mark_as_sum_func();
+ init_aggregator();
}
Item_sum(Item *a) :quick_group(1), arg_count(1), args(tmp_args),
orig_args(tmp_orig_args), forced_const(FALSE)
{
args[0]=a;
mark_as_sum_func();
+ init_aggregator();
}
Item_sum( Item *a, Item *b ) :quick_group(1), arg_count(2), args(tmp_args),
orig_args(tmp_orig_args), forced_const(FALSE)
{
args[0]=a; args[1]=b;
mark_as_sum_func();
+ init_aggregator();
}
Item_sum(List<Item> &list);
//Copy constructor, need to perform subselects with temporary tables
Item_sum(THD *thd, Item_sum *item);
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
-
- /*
- This method is similar to add(), but it is called when the current
- aggregation group changes. Thus it performs a combination of
- clear() and add().
- */
- inline bool reset() { clear(); return add(); };
-
- /*
- Prepare this item for evaluation of an aggregate value. This is
- called by reset() when a group changes, or, for correlated
- subqueries, between subquery executions. E.g. for COUNT(), this
- method should set count= 0;
- */
- virtual void clear()= 0;
-
- /*
- This method is called for the next row in the same group. Its
- purpose is to aggregate the new value to the previous values in
- the group (i.e. since clear() was called last time). For example,
- for COUNT(), do count++.
- */
- virtual bool add()=0;
+ inline bool reset() { aggregator_clear(); return aggregator_add(); };
/*
Called when new group is started and results are being saved in
@@ -343,11 +423,6 @@ public:
{ return new Item_field(field); }
table_map used_tables() const { return used_tables_cache; }
void update_used_tables ();
- void cleanup()
- {
- Item::cleanup();
- forced_const= FALSE;
- }
bool is_null() { return null_value; }
void make_const ()
{
@@ -359,7 +434,9 @@ public:
virtual void print(String *str, enum_query_type query_type);
void fix_num_length_and_dec();
- /*
+ /**
+ Mark an aggregate as having no rows.
+
This function is called by the execution engine to assign 'NO ROWS
FOUND' value to an aggregate item, when the underlying result set
has no rows. Such value, in a general case, may be different from
@@ -367,10 +444,15 @@ public:
may be initialized to 0 by clear() and to NULL by
no_rows_in_result().
*/
- void no_rows_in_result() { clear(); }
-
- virtual bool setup(THD *thd) {return 0;}
- virtual void make_unique() {}
+ void no_rows_in_result()
+ {
+ if (!aggr)
+ set_aggregator(with_distinct ?
+ Aggregator::DISTINCT_AGGREGATOR :
+ Aggregator::SIMPLE_AGGREGATOR);
+ reset();
+ }
+ virtual void make_unique() { force_copy_fields= TRUE; }
Item *get_tmp_table_item(THD *thd);
virtual Field *create_tmp_field(bool group, TABLE *table,
uint convert_blob_length);
@@ -381,14 +463,178 @@ public:
st_select_lex *depended_from()
{ return (nest_level == aggr_level ? 0 : aggr_sel); }
- Item *get_arg(int i) { return args[i]; }
- Item *set_arg(int i, THD *thd, Item *new_val);
+ Item *get_arg(uint i) { return args[i]; }
+ Item *set_arg(uint i, THD *thd, Item *new_val);
uint get_arg_count() { return arg_count; }
+
+ /* Initialization of distinct related members */
+ void init_aggregator()
+ {
+ aggr= NULL;
+ with_distinct= FALSE;
+ force_copy_fields= FALSE;
+ }
+
+ /**
+ Called to initialize the aggregator.
+ */
+
+ inline bool aggregator_setup(THD *thd) { return aggr->setup(thd); };
+
+ /**
+ Called to cleanup the aggregator.
+ */
+
+ inline void aggregator_clear() { aggr->clear(); }
+
+ /**
+ Called to add value to the aggregator.
+ */
+
+ inline bool aggregator_add() { return aggr->add(); };
+
+ /* stores the declared DISTINCT flag (from the parser) */
+ void set_distinct(bool distinct)
+ {
+ with_distinct= distinct;
+ quick_group= with_distinct ? 0 : 1;
+ }
+
+ /**
+ Set the type of aggregation : DISTINCT or not.
+
+ Called when the final determination is done about the aggregation
+ type and the object is about to be used.
+ */
+
+ int set_aggregator(Aggregator::Aggregator_type aggregator);
+ virtual void clear()= 0;
+ virtual bool add()= 0;
+ virtual bool setup(THD *thd) {return 0;}
+
+ void cleanup ();
+};
+
+
+class Unique;
+
+
+/**
+ The distinct aggregator.
+ Implements AGGFN (DISTINCT ..)
+ Collects all the data into an Unique (similarly to what Item_sum_distinct
+ does currently) and then (if applicable) iterates over the list of
+ unique values and pumps them back into its object
+*/
+
+class Aggregator_distinct : public Aggregator
+{
+ friend class Item_sum_sum;
+ friend class Item_sum_count;
+ friend class Item_sum_avg;
+protected:
+
+ /*
+ flag to prevent consecutive runs of endup(). Normally in endup there are
+ expensive calculations (like walking the distinct tree for example)
+ which we must do only once if there are no data changes.
+ We can re-use the data for the second and subsequent val_xxx() calls.
+ endup_done set to TRUE also means that the calculated values for
+ the aggregate functions are correct and don't need recalculation.
+ */
+ bool endup_done;
+
+ /*
+ Used depending on the type of the aggregate function and the presence of
+ blob columns in it:
+ - For COUNT(DISTINCT) and no blob fields this points to a real temporary
+ table. It's used as a hash table.
+ - For AVG/SUM(DISTINCT) or COUNT(DISTINCT) with blob fields only the
+ in-memory data structure of a temporary table is constructed.
+ It's used by the Field classes to transform data into row format.
+ */
+ TABLE *table;
+
+ /*
+ An array of field lengths on row allocated and used only for
+ COUNT(DISTINCT) with multiple columns and no blobs. Used in
+ Aggregator_distinct::composite_key_cmp (called from Unique to compare
+ nodes
+ */
+ uint32 *field_lengths;
+
+ /*
+ used in conjunction with 'table' to support the access to Field classes
+ for COUNT(DISTINCT). Needed by copy_fields()/copy_funcs().
+ */
+ TMP_TABLE_PARAM *tmp_table_param;
+
+ /*
+ If there are no blobs in the COUNT(DISTINCT) arguments, we can use a tree,
+ which is faster than heap table. In that case, we still use the table
+ to help get things set up, but we insert nothing in it.
+ For AVG/SUM(DISTINCT) we always use this tree (as it takes a single
+ argument) to get the distinct rows.
+ */
+ Unique *tree;
+
+ /*
+ The length of the temp table row. Must be a member of the class as it
+ gets passed down to simple_raw_key_cmp () as a compare function argument
+ to Unique. simple_raw_key_cmp () is used as a fast comparison function
+ when the entire row can be binary compared.
+ */
+ uint tree_key_length;
+
+ /*
+ Set to true if the result is known to be always NULL.
+ If set deactivates creation and usage of the temporary table (in the
+ 'table' member) and the Unique instance (in the 'tree' member) as well as
+ the calculation of the final value on the first call to
+ Item_[sum|avg|count]::val_xxx().
+ */
+ bool always_null;
+
+public:
+ Aggregator_distinct (Item_sum *sum) :
+ Aggregator(sum), table(NULL), tmp_table_param(NULL), tree(NULL),
+ always_null(FALSE) {}
+ virtual ~Aggregator_distinct ();
+ Aggregator_type Aggrtype() { return DISTINCT_AGGREGATOR; }
+
+ bool setup(THD *);
+ void clear();
+ bool add();
+ void endup();
+
+ bool unique_walk_function(void *element);
+ static int composite_key_cmp(void* arg, uchar* key1, uchar* key2);
+};
+
+
+/**
+ The pass-through aggregator.
+ Implements AGGFN (DISTINCT ..) by knowing it gets distinct data on input.
+ So it just pumps them back to the Item_sum descendant class.
+*/
+class Aggregator_simple : public Aggregator
+{
+public:
+
+ Aggregator_simple (Item_sum *sum) :
+ Aggregator(sum) {}
+ Aggregator_type Aggrtype() { return Aggregator::SIMPLE_AGGREGATOR; }
+
+ bool setup(THD * thd) { return item_sum->setup(thd); }
+ void clear() { item_sum->clear(); }
+ bool add() { return item_sum->add(); }
+ void endup() {};
};
class Item_sum_num :public Item_sum
{
+ friend class Aggregator_distinct;
protected:
/*
val_xxx() functions may be called several times during the execution of a
@@ -443,9 +689,15 @@ protected:
void fix_length_and_dec();
public:
- Item_sum_sum(Item *item_par) :Item_sum_num(item_par) {}
+ Item_sum_sum(Item *item_par, bool distinct= FALSE) :Item_sum_num(item_par)
+ {
+ set_distinct(distinct);
+ }
Item_sum_sum(THD *thd, Item_sum_sum *item);
- enum Sumfunctype sum_func () const {return SUM_FUNC;}
+ enum Sumfunctype sum_func () const
+ {
+ return with_distinct ? SUM_DISTINCT_FUNC : SUM_FUNC;
+ }
void clear();
bool add();
double val_real();
@@ -456,109 +708,50 @@ public:
void reset_field();
void update_field();
void no_rows_in_result() {}
- const char *func_name() const { return "sum("; }
+ const char *func_name() const
+ {
+ return with_distinct ? "sum(distinct " : "sum(";
+ }
Item *copy_or_same(THD* thd);
};
-
-/* Common class for SUM(DISTINCT), AVG(DISTINCT) */
-
-class Unique;
-
-class Item_sum_distinct :public Item_sum_num
+class Item_sum_count :public Item_sum_int
{
-protected:
- /* storage for the summation result */
- ulonglong count;
- Hybrid_type val;
- /* storage for unique elements */
- Unique *tree;
- TABLE *table;
- enum enum_field_types table_field_type;
- uint tree_key_length;
-protected:
- Item_sum_distinct(THD *thd, Item_sum_distinct *item);
-public:
- Item_sum_distinct(Item *item_par);
- ~Item_sum_distinct();
+ longlong count;
+
+ friend class Aggregator_distinct;
- bool setup(THD *thd);
void clear();
- void cleanup();
bool add();
- double val_real();
- my_decimal *val_decimal(my_decimal *);
- longlong val_int();
- String *val_str(String *str);
-
- /* XXX: does it need make_unique? */
-
- enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
- void reset_field() {} // not used
- void update_field() {} // not used
- virtual void no_rows_in_result() {}
- void fix_length_and_dec();
- enum Item_result result_type () const { return val.traits->type(); }
- virtual void calculate_val_and_count();
- virtual bool unique_walk_function(void *elem);
-};
-
-
-/*
- Item_sum_sum_distinct - implementation of SUM(DISTINCT expr).
- See also: MySQL manual, chapter 'Adding New Functions To MySQL'
- and comments in item_sum.cc.
-*/
-
-class Item_sum_sum_distinct :public Item_sum_distinct
-{
-private:
- Item_sum_sum_distinct(THD *thd, Item_sum_sum_distinct *item)
- :Item_sum_distinct(thd, item) {}
-public:
- Item_sum_sum_distinct(Item *item_arg) :Item_sum_distinct(item_arg) {}
-
- enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
- const char *func_name() const { return "sum(distinct "; }
- Item *copy_or_same(THD* thd) { return new Item_sum_sum_distinct(thd, this); }
-};
-
-
-/* Item_sum_avg_distinct - SELECT AVG(DISTINCT expr) FROM ... */
-
-class Item_sum_avg_distinct: public Item_sum_distinct
-{
-private:
- Item_sum_avg_distinct(THD *thd, Item_sum_avg_distinct *original)
- :Item_sum_distinct(thd, original) {}
-public:
- uint prec_increment;
- Item_sum_avg_distinct(Item *item_arg) : Item_sum_distinct(item_arg) {}
-
- void fix_length_and_dec();
- virtual void calculate_val_and_count();
- enum Sumfunctype sum_func () const { return AVG_DISTINCT_FUNC; }
- const char *func_name() const { return "avg(distinct "; }
- Item *copy_or_same(THD* thd) { return new Item_sum_avg_distinct(thd, this); }
-};
-
-
-class Item_sum_count :public Item_sum_int
-{
- longlong count;
+ void cleanup();
public:
Item_sum_count(Item *item_par)
:Item_sum_int(item_par),count(0)
{}
+
+ /**
+ Constructs an instance for COUNT(DISTINCT)
+
+ @param list a list of the arguments to the aggregate function
+
+ This constructor is called by the parser only for COUNT (DISTINCT).
+ */
+
+ Item_sum_count(List<Item> &list)
+ :Item_sum_int(list),count(0)
+ {
+ set_distinct(TRUE);
+ }
Item_sum_count(THD *thd, Item_sum_count *item)
:Item_sum_int(thd, item), count(item->count)
{}
- enum Sumfunctype sum_func () const { return COUNT_FUNC; }
- void clear();
+ enum Sumfunctype sum_func () const
+ {
+ return with_distinct ? COUNT_DISTINCT_FUNC : COUNT_FUNC;
+ }
void no_rows_in_result() { count=0; }
- bool add();
void make_const(longlong count_arg)
{
count=count_arg;
@@ -566,76 +759,12 @@ class Item_sum_count :public Item_sum_int
}
longlong val_int();
void reset_field();
- void cleanup();
void update_field();
- const char *func_name() const { return "count("; }
- Item *copy_or_same(THD* thd);
-};
-
-
-class TMP_TABLE_PARAM;
-
-class Item_sum_count_distinct :public Item_sum_int
-{
- TABLE *table;
- uint32 *field_lengths;
- TMP_TABLE_PARAM *tmp_table_param;
- bool force_copy_fields;
- /*
- If there are no blobs, we can use a tree, which
- is faster than heap table. In that case, we still use the table
- to help get things set up, but we insert nothing in it
- */
- Unique *tree;
- /*
- Storage for the value of count between calls to val_int() so val_int()
- will not recalculate on each call. Validitiy of the value is stored in
- is_evaluated.
- */
- longlong count;
- /*
- Following is 0 normal object and pointer to original one for copy
- (to correctly free resources)
- */
- Item_sum_count_distinct *original;
- uint tree_key_length;
-
-
- bool always_null; // Set to 1 if the result is always NULL
-
-
- friend int composite_key_cmp(void* arg, uchar* key1, uchar* key2);
- friend int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2);
-
-public:
- Item_sum_count_distinct(List<Item> &list)
- :Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0),
- force_copy_fields(0), tree(0), count(0),
- original(0), always_null(FALSE)
- { quick_group= 0; }
- Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item)
- :Item_sum_int(thd, item), table(item->table),
- field_lengths(item->field_lengths),
- tmp_table_param(item->tmp_table_param),
- force_copy_fields(0), tree(item->tree), count(item->count),
- original(item), tree_key_length(item->tree_key_length),
- always_null(item->always_null)
- {}
- ~Item_sum_count_distinct();
-
- void cleanup();
-
- enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; }
- void clear();
- bool add();
- longlong val_int();
- void reset_field() { return ;} // Never called
- void update_field() { return ; } // Never called
- const char *func_name() const { return "count(distinct "; }
- bool setup(THD *thd);
- void make_unique();
+ const char *func_name() const
+ {
+ return with_distinct ? "count(distinct " : "count(";
+ }
Item *copy_or_same(THD* thd);
- void no_rows_in_result() {}
};
@@ -674,13 +803,18 @@ public:
uint prec_increment;
uint f_precision, f_scale, dec_bin_size;
- Item_sum_avg(Item *item_par) :Item_sum_sum(item_par), count(0) {}
+ Item_sum_avg(Item *item_par, bool distinct= FALSE)
+ :Item_sum_sum(item_par, distinct), count(0)
+ {}
Item_sum_avg(THD *thd, Item_sum_avg *item)
:Item_sum_sum(thd, item), count(item->count),
prec_increment(item->prec_increment) {}
void fix_length_and_dec();
- enum Sumfunctype sum_func () const {return AVG_FUNC;}
+ enum Sumfunctype sum_func () const
+ {
+ return with_distinct ? AVG_DISTINCT_FUNC : AVG_FUNC;
+ }
void clear();
bool add();
double val_real();
@@ -693,7 +827,10 @@ public:
Item *result_item(Field *field)
{ return new Item_avg_field(hybrid_type, this); }
void no_rows_in_result() {}
- const char *func_name() const { return "avg("; }
+ const char *func_name() const
+ {
+ return with_distinct ? "avg(distinct " : "avg(";
+ }
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
void cleanup()
@@ -1181,12 +1318,9 @@ public:
#endif /* HAVE_DLOPEN */
-class MYSQL_ERROR;
-
class Item_func_group_concat : public Item_sum
{
TMP_TABLE_PARAM *tmp_table_param;
- MYSQL_ERROR *warning;
String result;
String *separator;
TREE tree_base;
@@ -1207,7 +1341,7 @@ class Item_func_group_concat : public Item_sum
uint arg_count_order;
/** The number of selected items, aka the expr list. */
uint arg_count_field;
- uint count_cut_values;
+ uint row_count;
bool distinct;
bool warning_for_row;
bool always_null;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index a9e5c71ab56..6eb733f00d7 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -602,7 +602,7 @@ err:
{
char buff[128];
strmake(buff, val_begin, min(length, sizeof(buff)-1));
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
date_time_type, buff, "str_to_date");
}
diff --git a/sql/lex.h b/sql/lex.h
index 0a85824f6f7..b4945bbfd1a 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -96,6 +96,7 @@ static SYMBOL symbols[] = {
{ "CASCADE", SYM(CASCADE)},
{ "CASCADED", SYM(CASCADED)},
{ "CASE", SYM(CASE_SYM)},
+ { "CATALOG_NAME", SYM(CATALOG_NAME_SYM)},
{ "CHAIN", SYM(CHAIN_SYM)},
{ "CHANGE", SYM(CHANGE)},
{ "CHANGED", SYM(CHANGED)},
@@ -105,6 +106,7 @@ static SYMBOL symbols[] = {
{ "CHECK", SYM(CHECK_SYM)},
{ "CHECKSUM", SYM(CHECKSUM_SYM)},
{ "CIPHER", SYM(CIPHER_SYM)},
+ { "CLASS_ORIGIN", SYM(CLASS_ORIGIN_SYM)},
{ "CLIENT", SYM(CLIENT_SYM)},
{ "CLOSE", SYM(CLOSE_SYM)},
{ "COALESCE", SYM(COALESCE)},
@@ -112,6 +114,7 @@ static SYMBOL symbols[] = {
{ "COLLATE", SYM(COLLATE_SYM)},
{ "COLLATION", SYM(COLLATION_SYM)},
{ "COLUMN", SYM(COLUMN_SYM)},
+ { "COLUMN_NAME", SYM(COLUMN_NAME_SYM)},
{ "COLUMNS", SYM(COLUMNS)},
{ "COMMENT", SYM(COMMENT_SYM)},
{ "COMMIT", SYM(COMMIT_SYM)},
@@ -124,6 +127,9 @@ static SYMBOL symbols[] = {
{ "CONNECTION", SYM(CONNECTION_SYM)},
{ "CONSISTENT", SYM(CONSISTENT_SYM)},
{ "CONSTRAINT", SYM(CONSTRAINT)},
+ { "CONSTRAINT_CATALOG", SYM(CONSTRAINT_CATALOG_SYM)},
+ { "CONSTRAINT_NAME", SYM(CONSTRAINT_NAME_SYM)},
+ { "CONSTRAINT_SCHEMA", SYM(CONSTRAINT_SCHEMA_SYM)},
{ "CONTAINS", SYM(CONTAINS_SYM)},
{ "CONTEXT", SYM(CONTEXT_SYM)},
{ "CONTINUE", SYM(CONTINUE_SYM)},
@@ -138,6 +144,7 @@ static SYMBOL symbols[] = {
{ "CURRENT_TIMESTAMP", SYM(NOW_SYM)},
{ "CURRENT_USER", SYM(CURRENT_USER)},
{ "CURSOR", SYM(CURSOR_SYM)},
+ { "CURSOR_NAME", SYM(CURSOR_NAME_SYM)},
{ "DATA", SYM(DATA_SYM)},
{ "DATABASE", SYM(DATABASE)},
{ "DATABASES", SYM(DATABASES)},
@@ -334,6 +341,7 @@ static SYMBOL symbols[] = {
{ "MEDIUMTEXT", SYM(MEDIUMTEXT)},
{ "MEMORY", SYM(MEMORY_SYM)},
{ "MERGE", SYM(MERGE_SYM)},
+ { "MESSAGE_TEXT", SYM(MESSAGE_TEXT_SYM)},
{ "MICROSECOND", SYM(MICROSECOND_SYM)},
{ "MIDDLEINT", SYM(MEDIUMINT)}, /* For powerbuilder */
{ "MIGRATE", SYM(MIGRATE_SYM)},
@@ -350,6 +358,7 @@ static SYMBOL symbols[] = {
{ "MULTIPOINT", SYM(MULTIPOINT)},
{ "MULTIPOLYGON", SYM(MULTIPOLYGON)},
{ "MUTEX", SYM(MUTEX_SYM)},
+ { "MYSQL_ERRNO", SYM(MYSQL_ERRNO_SYM)},
{ "NAME", SYM(NAME_SYM)},
{ "NAMES", SYM(NAMES_SYM)},
{ "NATIONAL", SYM(NATIONAL_SYM)},
@@ -441,6 +450,7 @@ static SYMBOL symbols[] = {
{ "REPEAT", SYM(REPEAT_SYM)},
{ "REQUIRE", SYM(REQUIRE_SYM)},
{ "RESET", SYM(RESET_SYM)},
+ { "RESIGNAL", SYM(RESIGNAL_SYM)},
{ "RESTORE", SYM(RESTORE_SYM)},
{ "RESTRICT", SYM(RESTRICT)},
{ "RESUME", SYM(RESUME_SYM)},
@@ -459,6 +469,7 @@ static SYMBOL symbols[] = {
{ "SAVEPOINT", SYM(SAVEPOINT_SYM)},
{ "SCHEDULE", SYM(SCHEDULE_SYM)},
{ "SCHEMA", SYM(DATABASE)},
+ { "SCHEMA_NAME", SYM(SCHEMA_NAME_SYM)},
{ "SCHEMAS", SYM(DATABASES)},
{ "SECOND", SYM(SECOND_SYM)},
{ "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM)},
@@ -474,6 +485,7 @@ static SYMBOL symbols[] = {
{ "SHARE", SYM(SHARE_SYM)},
{ "SHOW", SYM(SHOW)},
{ "SHUTDOWN", SYM(SHUTDOWN)},
+ { "SIGNAL", SYM(SIGNAL_SYM)},
{ "SIGNED", SYM(SIGNED_SYM)},
{ "SIMPLE", SYM(SIMPLE_SYM)},
{ "SLAVE", SYM(SLAVE)},
@@ -515,6 +527,7 @@ static SYMBOL symbols[] = {
{ "STORAGE", SYM(STORAGE_SYM)},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN)},
{ "STRING", SYM(STRING_SYM)},
+ { "SUBCLASS_ORIGIN", SYM(SUBCLASS_ORIGIN_SYM)},
{ "SUBJECT", SYM(SUBJECT_SYM)},
{ "SUBPARTITION", SYM(SUBPARTITION_SYM)},
{ "SUBPARTITIONS", SYM(SUBPARTITIONS_SYM)},
@@ -523,6 +536,7 @@ static SYMBOL symbols[] = {
{ "SWAPS", SYM(SWAPS_SYM)},
{ "SWITCHES", SYM(SWITCHES_SYM)},
{ "TABLE", SYM(TABLE_SYM)},
+ { "TABLE_NAME", SYM(TABLE_NAME_SYM)},
{ "TABLES", SYM(TABLES)},
{ "TABLESPACE", SYM(TABLESPACE)},
{ "TABLE_CHECKSUM", SYM(TABLE_CHECKSUM_SYM)},
@@ -593,6 +607,7 @@ static SYMBOL symbols[] = {
{ "X509", SYM(X509_SYM)},
{ "XOR", SYM(XOR)},
{ "XA", SYM(XA_SYM)},
+ { "XML", SYM(XML_SYM)}, /* LOAD XML Arnold/Erik */
{ "YEAR", SYM(YEAR_SYM)},
{ "YEAR_MONTH", SYM(YEAR_MONTH_SYM)},
{ "ZEROFILL", SYM(ZEROFILL)},
diff --git a/sql/log.cc b/sql/log.cc
index feaa5499912..ed208a84ffc 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -33,7 +33,7 @@
#include <stdarg.h>
#include <m_ctype.h> // For test_if_number
-#ifdef __NT__
+#ifdef _WIN32
#include "message.h"
#endif
@@ -80,23 +80,28 @@ public:
virtual ~Silence_log_table_errors() {}
- virtual bool handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sql_state,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
const char *message() const { return m_message; }
};
bool
-Silence_log_table_errors::handle_error(uint /* sql_errno */,
- const char *message_arg,
- MYSQL_ERROR::enum_warning_level /* level */,
- THD * /* thd */)
-{
- strmake(m_message, message_arg, sizeof(m_message)-1);
+Silence_log_table_errors::handle_condition(THD *,
+ uint,
+ const char*,
+ MYSQL_ERROR::enum_warning_level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
+{
+ *cond_hdl= NULL;
+ strmake(m_message, msg, sizeof(m_message)-1);
return TRUE;
}
-
sql_print_message_func sql_print_message_handlers[3] =
{
sql_print_information,
@@ -1661,7 +1666,7 @@ bool MYSQL_BIN_LOG::check_write_error(THD *thd)
if (!thd->is_error())
DBUG_RETURN(checked);
- switch (thd->main_da.sql_errno())
+ switch (thd->stmt_da->sql_errno())
{
case ER_TRANS_CACHE_FULL:
case ER_ERROR_ON_WRITE:
@@ -1789,7 +1794,7 @@ err:
DBUG_RETURN(-1);
}
-#ifdef __NT__
+#ifdef _WIN32
static int eventSource = 0;
static void setup_windows_event_source()
@@ -1824,7 +1829,7 @@ static void setup_windows_event_source()
RegCloseKey(hRegKey);
}
-#endif /* __NT__ */
+#endif /* _WIN32 */
/**
@@ -1955,7 +1960,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
#ifdef EMBEDDED_LIBRARY
"embedded library\n",
my_progname, server_version, MYSQL_COMPILATION_COMMENT
-#elif __NT__
+#elif _WIN32
"started with:\nTCP Port: %d, Named Pipe: %s\n",
my_progname, server_version, MYSQL_COMPILATION_COMMENT,
mysqld_port, mysqld_unix_port
@@ -2917,7 +2922,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
}
else
{
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with deleting %s; "
"consider examining correspondence "
@@ -2948,7 +2953,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
}
else
{
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with deleting %s; "
"consider examining correspondence "
@@ -3279,7 +3284,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
*/
if (thd)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with getting info on being purged %s; "
"consider examining correspondence "
@@ -3325,7 +3330,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
{
if (thd)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with deleting %s; "
"consider examining correspondence "
@@ -3424,7 +3429,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
*/
if (thd)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_BINLOG_PURGE_FATAL_ERR,
"a problem with getting info on being purged %s; "
"consider examining correspondence "
@@ -4435,9 +4440,9 @@ int query_error_code(THD *thd, bool not_killed)
if (not_killed)
{
- error= thd->is_error() ? thd->main_da.sql_errno() : 0;
+ error= thd->is_error() ? thd->stmt_da->sql_errno() : 0;
- /* thd->main_da.sql_errno() might be ER_SERVER_SHUTDOWN or
+ /* thd->stmt_da->sql_errno() might be ER_SERVER_SHUTDOWN or
ER_QUERY_INTERRUPTED, So here we need to make sure that error
is not set to these errors when specified not_killed by the
caller.
@@ -4846,7 +4851,7 @@ void MYSQL_BIN_LOG::signal_update()
DBUG_VOID_RETURN;
}
-#ifdef __NT__
+#ifdef _WIN32
static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
size_t length, size_t buffLen)
{
@@ -4879,7 +4884,7 @@ static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
DBUG_VOID_RETURN;
}
-#endif /* __NT__ */
+#endif /* _WIN32 */
/**
@@ -4941,7 +4946,7 @@ int vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
length= my_vsnprintf(buff, sizeof(buff), format, args);
print_buffer_to_file(level, buff);
-#ifdef __NT__
+#ifdef _WIN32
print_buffer_to_nt_eventlog(level, buff, length, sizeof(buff));
#endif
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 08fe3aba8ed..f2f1e84b22f 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -134,7 +134,7 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error,
char buff[MAX_SLAVE_ERRMSG], *slider;
const char *buff_end= buff + sizeof(buff);
uint len;
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
buff[0]= 0;
@@ -142,10 +142,11 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error,
slider += len, err= it++)
{
len= my_snprintf(slider, buff_end - slider,
- " %s, Error_code: %d;", err->msg, err->code);
+ " %s, Error_code: %d;", err->get_message_text(),
+ err->get_sql_errno());
}
- rli->report(level, thd->is_error()? thd->main_da.sql_errno() : 0,
+ rli->report(level, thd->is_error()? thd->stmt_da->sql_errno() : 0,
"Could not execute %s event on table %s.%s;"
"%s handler error %s; "
"the event's master log %s, end_log_pos %lu",
@@ -353,13 +354,13 @@ inline int ignored_error_code(int err_code)
*/
int convert_handler_error(int error, THD* thd, TABLE *table)
{
- uint actual_error= (thd->is_error() ? thd->main_da.sql_errno() :
+ uint actual_error= (thd->is_error() ? thd->stmt_da->sql_errno() :
0);
if (actual_error == 0)
{
table->file->print_error(error, MYF(0));
- actual_error= (thd->is_error() ? thd->main_da.sql_errno() :
+ actual_error= (thd->is_error() ? thd->stmt_da->sql_errno() :
ER_UNKNOWN_ERROR);
if (actual_error == ER_UNKNOWN_ERROR)
if (global_system_variables.log_warnings)
@@ -3162,7 +3163,7 @@ START SLAVE; . Query: '%s'", expected_error, thd->query);
}
/* If the query was not ignored, it is printed to the general log */
- if (!thd->is_error() || thd->main_da.sql_errno() != ER_SLAVE_IGNORED_TABLE)
+ if (!thd->is_error() || thd->stmt_da->sql_errno() != ER_SLAVE_IGNORED_TABLE)
general_log_write(thd, COM_QUERY, thd->query, thd->query_length);
compare_errors:
@@ -3171,7 +3172,7 @@ compare_errors:
If we expected a non-zero error code, and we don't get the same error
code, and it should be ignored or is related to a concurrency issue.
*/
- actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0;
+ actual_error= thd->is_error() ? thd->stmt_da->sql_errno() : 0;
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
expected_error, actual_error));
if ((expected_error && expected_error != actual_error &&
@@ -3186,7 +3187,7 @@ Error on master: '%s' (%d), Error on slave: '%s' (%d). \
Default database: '%s'. Query: '%s'",
ER_SAFE(expected_error),
expected_error,
- actual_error ? thd->main_da.message() : "no error",
+ actual_error ? thd->stmt_da->message() : "no error",
actual_error,
print_slave_db_safe(db), query_arg);
thd->is_slave_error= 1;
@@ -3227,7 +3228,7 @@ Default database: '%s'. Query: '%s'",
{
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on query. Default database: '%s'. Query: '%s'",
- (actual_error ? thd->main_da.message() :
+ (actual_error ? thd->stmt_da->message() :
"unexpected success or fatal error"),
print_slave_db_safe(thd->db), query_arg);
thd->is_slave_error= 1;
@@ -4534,13 +4535,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id = next_query_id();
VOID(pthread_mutex_unlock(&LOCK_thread_count));
- /*
- Initing thd->row_count is not necessary in theory as this variable has no
- influence in the case of the slave SQL thread (it is used to generate a
- "data truncated" warning but which is absorbed and never gets to the
- error log); still we init it to avoid a Valgrind message.
- */
- mysql_reset_errors(thd, 0);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
TABLE_LIST tables;
bzero((char*) &tables,sizeof(tables));
@@ -4701,8 +4696,8 @@ error:
int sql_errno;
if (thd->is_error())
{
- err= thd->main_da.message();
- sql_errno= thd->main_da.sql_errno();
+ err= thd->stmt_da->message();
+ sql_errno= thd->stmt_da->sql_errno();
}
else
{
@@ -7265,7 +7260,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
if (simple_open_n_lock_tables(thd, rli->tables_to_lock))
{
- uint actual_error= thd->main_da.sql_errno();
+ uint actual_error= thd->stmt_da->sql_errno();
if (thd->is_slave_error || thd->is_fatal_error)
{
/*
@@ -7276,7 +7271,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
*/
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on opening tables",
- (actual_error ? thd->main_da.message() :
+ (actual_error ? thd->stmt_da->message() :
"unexpected success or fatal error"));
thd->is_slave_error= 1;
}
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index 68cd2bf4673..49181bcf543 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -78,7 +78,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
if (simple_open_n_lock_tables(thd, rli->tables_to_lock))
{
- uint actual_error= thd->main_da.sql_errno();
+ uint actual_error= thd->stmt_da->sql_errno();
if (thd->is_slave_error || thd->is_fatal_error)
{
/*
@@ -87,7 +87,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
*/
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on opening tables",
- (actual_error ? thd->main_da.message() :
+ (actual_error ? thd->stmt_da->message() :
"unexpected success or fatal error"));
thd->is_slave_error= 1;
}
@@ -216,10 +216,10 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
break;
default:
- rli->report(ERROR_LEVEL, thd->main_da.sql_errno(),
+ rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(),
"Error in %s event: row application failed. %s",
ev->get_type_str(),
- thd->is_error() ? thd->main_da.message() : "");
+ thd->is_error() ? thd->stmt_da->message() : "");
thd->is_slave_error= 1;
break;
}
@@ -245,12 +245,12 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
if (error)
{ /* error has occured during the transaction */
- rli->report(ERROR_LEVEL, thd->main_da.sql_errno(),
+ rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(),
"Error in %s event: error during transaction execution "
"on table %s.%s. %s",
ev->get_type_str(), table->s->db.str,
table->s->table_name.str,
- thd->is_error() ? thd->main_da.message() : "");
+ thd->is_error() ? thd->stmt_da->message() : "");
/*
If one day we honour --skip-slave-errors in row-based replication, and
diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc
index 208ddefb890..16d07526a0f 100644
--- a/sql/my_decimal.cc
+++ b/sql/my_decimal.cc
@@ -41,17 +41,17 @@ int decimal_operation_results(int result)
"", (long)-1);
break;
case E_DEC_OVERFLOW:
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE),
"DECIMAL", "");
break;
case E_DEC_DIV_ZERO:
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_DIVISION_BY_ZERO, ER(ER_DIVISION_BY_ZERO));
break;
case E_DEC_BAD_NUM:
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", "", "", (long)-1);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index f21c274a23a..fc0c688610b 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -128,6 +128,10 @@ extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *national_charset_info;
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *table_alias_charset;
+/**
+ Character set of the buildin error messages loaded from errmsg.sys.
+*/
+extern CHARSET_INFO *error_message_charset_info;
enum Derivation
{
@@ -152,18 +156,26 @@ typedef struct my_locale_st
TYPELIB *ab_day_names;
uint max_month_name_length;
uint max_day_name_length;
+ uint decimal_point;
+ uint thousand_sep;
+ const char *grouping;
#ifdef __cplusplus
my_locale_st(uint number_par,
const char *name_par, const char *descr_par, bool is_ascii_par,
TYPELIB *month_names_par, TYPELIB *ab_month_names_par,
TYPELIB *day_names_par, TYPELIB *ab_day_names_par,
- uint max_month_name_length_par, uint max_day_name_length_par) :
+ uint max_month_name_length_par, uint max_day_name_length_par,
+ uint decimal_point_par, uint thousand_sep_par,
+ const char *grouping_par) :
number(number_par),
name(name_par), description(descr_par), is_ascii(is_ascii_par),
month_names(month_names_par), ab_month_names(ab_month_names_par),
day_names(day_names_par), ab_day_names(ab_day_names_par),
max_month_name_length(max_month_name_length_par),
- max_day_name_length(max_day_name_length_par)
+ max_day_name_length(max_day_name_length_par),
+ decimal_point(decimal_point_par),
+ thousand_sep(thousand_sep_par),
+ grouping(grouping_par)
{}
#endif
} MY_LOCALE;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index b07e4b2af0e..422927f7fda 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -628,6 +628,7 @@ MY_BITMAP temp_pool;
CHARSET_INFO *system_charset_info, *files_charset_info ;
CHARSET_INFO *national_charset_info, *table_alias_charset;
CHARSET_INFO *character_set_filesystem;
+CHARSET_INFO *error_message_charset_info;
MY_LOCALE *my_default_lc_time_names;
@@ -731,7 +732,7 @@ static NTService Service; ///< Service object for WinNT
#endif /* EMBEDDED_LIBRARY */
#endif /* __WIN__ */
-#ifdef __NT__
+#ifdef _WIN32
static char pipe_name[512];
static SECURITY_ATTRIBUTES saPipeSecurity;
static SECURITY_DESCRIPTOR sdPipeDescriptor;
@@ -804,11 +805,14 @@ static void set_server_version(void);
static int init_thread_environment();
static char *get_relative_path(const char *path);
static int fix_paths(void);
-pthread_handler_t handle_connections_sockets(void *arg);
+void handle_connections_sockets();
+#ifdef _WIN32
+pthread_handler_t handle_connections_sockets_thread(void *arg);
+#endif
pthread_handler_t kill_server_thread(void *arg);
static void bootstrap(FILE *file);
static bool read_init_file(char *file_name);
-#ifdef __NT__
+#ifdef _WIN32
pthread_handler_t handle_connections_namedpipes(void *arg);
#endif
#ifdef HAVE_SMEM
@@ -894,7 +898,7 @@ static void close_connections(void)
ip_sock= INVALID_SOCKET;
}
}
-#ifdef __NT__
+#ifdef _WIN32
if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
{
HANDLE temp;
@@ -1686,7 +1690,7 @@ static void network_init(void)
}
}
-#ifdef __NT__
+#ifdef _WIN32
/* create named pipe */
if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
opt_enable_named_pipe)
@@ -1808,7 +1812,8 @@ void close_connection(THD *thd, uint errcode, bool lock)
if ((vio= thd->net.vio) != 0)
{
if (errcode)
- net_send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
+ net_send_error(thd, errcode,
+ ER(errcode), NULL); /* purecov: inspected */
vio_close(vio); /* vio is freed in delete thd */
}
if (lock)
@@ -2032,29 +2037,7 @@ static BOOL WINAPI console_event_handler( DWORD type )
}
-/*
- In Visual Studio 2005 and later, default SIGABRT handler will overwrite
- any unhandled exception filter set by the application and will try to
- call JIT debugger. This is not what we want, this we calling __debugbreak
- to stop in debugger, if process is being debugged or to generate
- EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.
-*/
-#if (_MSC_VER >= 1400)
-static void my_sigabrt_handler(int sig)
-{
- __debugbreak();
-}
-#endif /*_MSC_VER >=1400 */
-
-void win_install_sigabrt_handler(void)
-{
-#if (_MSC_VER >=1400)
- /*abort() should not override our exception filter*/
- _set_abort_behavior(0,_CALL_REPORTFAULT);
- signal(SIGABRT,my_sigabrt_handler);
-#endif /* _MSC_VER >=1400 */
-}
#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
#define DEBUGGER_ATTACH_TIMEOUT 120
@@ -2133,7 +2116,6 @@ LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
static void init_signals(void)
{
- win_install_sigabrt_handler();
if(opt_console)
SetConsoleCtrlHandler(console_event_handler,TRUE);
@@ -2853,11 +2835,11 @@ static void check_data_home(const char *path)
for the client.
*/
/* ARGSUSED */
-extern "C" int my_message_sql(uint error, const char *str, myf MyFlags);
+extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
-int my_message_sql(uint error, const char *str, myf MyFlags)
+void my_message_sql(uint error, const char *str, myf MyFlags)
{
- THD *thd;
+ THD *thd= current_thd;
DBUG_ENTER("my_message_sql");
DBUG_PRINT("error", ("error: %u message: '%s'", error, str));
@@ -2879,70 +2861,18 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
error= ER_UNKNOWN_ERROR;
}
- if ((thd= current_thd))
+ if (thd)
{
- /*
- TODO: There are two exceptions mechanism (THD and sp_rcontext),
- this could be improved by having a common stack of handlers.
- */
- if (thd->handle_error(error, str,
- MYSQL_ERROR::WARN_LEVEL_ERROR))
- DBUG_RETURN(0);
-
- thd->is_slave_error= 1; // needed to catch query errors during replication
-
- /*
- thd->lex->current_select == 0 if lex structure is not inited
- (not query command (COM_QUERY))
- */
- if (thd->lex->current_select &&
- thd->lex->current_select->no_error && !thd->is_fatal_error)
- {
- DBUG_PRINT("error",
- ("Error converted to warning: current_select: no_error %d "
- "fatal_error: %d",
- (thd->lex->current_select ?
- thd->lex->current_select->no_error : 0),
- (int) thd->is_fatal_error));
- }
- else
- {
- if (! thd->main_da.is_error()) // Return only first message
- {
- thd->main_da.set_error_status(thd, error, str);
- }
- query_cache_abort(&thd->net);
- }
- /*
- If a continue handler is found, the error message will be cleared
- by the stored procedures code.
- */
- if (thd->spcont &&
- ! (MyFlags & ME_NO_SP_HANDLER) &&
- thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
- {
- /*
- Do not push any warnings, a handled error must be completely
- silenced.
- */
- DBUG_RETURN(0);
- }
-
- if (!thd->no_warnings_for_error &&
- !(MyFlags & ME_NO_WARNING_FOR_ERROR))
- {
- /*
- Suppress infinite recursion if there a memory allocation error
- inside push_warning.
- */
- thd->no_warnings_for_error= TRUE;
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
- thd->no_warnings_for_error= FALSE;
- }
+ if (MyFlags & ME_FATALERROR)
+ thd->is_fatal_error= 1;
+ (void) thd->raise_condition(error,
+ NULL,
+ MYSQL_ERROR::WARN_LEVEL_ERROR,
+ str);
}
if (!thd || MyFlags & ME_NOREFRESH)
sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
- DBUG_RETURN(0);
+ DBUG_VOID_RETURN;
}
@@ -3106,6 +3036,7 @@ SHOW_VAR com_status_vars[]= {
{"replace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
{"replace_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
{"reset", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS},
+ {"resignal", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS},
{"restore_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESTORE_TABLE]), SHOW_LONG_STATUS},
{"revoke", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS},
{"revoke_all", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS},
@@ -3114,6 +3045,7 @@ SHOW_VAR com_status_vars[]= {
{"savepoint", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
{"select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS},
{"set_option", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
+ {"signal", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]), SHOW_LONG_STATUS},
{"show_authors", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_AUTHORS]), SHOW_LONG_STATUS},
{"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},
@@ -4180,7 +4112,8 @@ static void create_shutdown_thread()
#ifdef __WIN__
hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
pthread_t hThread;
- if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
+ if (pthread_create(&hThread,&connection_attrib,
+ handle_connections_sockets_thread, 0))
sql_print_warning("Can't create thread to handle shutdown requests");
// On "Stop Service" we have to do regular shutdown
@@ -4191,12 +4124,11 @@ static void create_shutdown_thread()
#endif /* EMBEDDED_LIBRARY */
-#if (defined(__NT__) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
+#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
static void handle_connections_methods()
{
pthread_t hThread;
DBUG_ENTER("handle_connections_methods");
-#ifdef __NT__
if (hPipe == INVALID_HANDLE_VALUE &&
(!have_tcpip || opt_disable_networking) &&
!opt_enable_shared_memory)
@@ -4204,12 +4136,10 @@ static void handle_connections_methods()
sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
unireg_abort(1); // Will not return
}
-#endif
pthread_mutex_lock(&LOCK_thread_count);
(void) pthread_cond_init(&COND_handler_count,NULL);
handler_count=0;
-#ifdef __NT__
if (hPipe != INVALID_HANDLE_VALUE)
{
handler_count++;
@@ -4220,12 +4150,11 @@ static void handle_connections_methods()
handler_count--;
}
}
-#endif /* __NT__ */
if (have_tcpip && !opt_disable_networking)
{
handler_count++;
if (pthread_create(&hThread,&connection_attrib,
- handle_connections_sockets, 0))
+ handle_connections_sockets_thread, 0))
{
sql_print_warning("Can't create thread to handle TCP/IP");
handler_count--;
@@ -4260,7 +4189,7 @@ void decrement_handler_count()
}
#else
#define decrement_handler_count()
-#endif /* defined(__NT__) || defined(HAVE_SMEM) */
+#endif /* defined(_WIN32) || defined(HAVE_SMEM) */
#ifndef EMBEDDED_LIBRARY
@@ -4554,18 +4483,11 @@ we force server id to 2, but this MySQL server will not act as a slave.");
pthread_cond_signal(&COND_server_started);
pthread_mutex_unlock(&LOCK_server_started);
-#if defined(__NT__) || defined(HAVE_SMEM)
+#if defined(_WIN32) || defined(HAVE_SMEM)
handle_connections_methods();
#else
-#ifdef __WIN__
- if (!have_tcpip || opt_disable_networking)
- {
- sql_print_error("TCP/IP unavailable or disabled with --skip-networking; no available interfaces");
- unireg_abort(1);
- }
-#endif
- handle_connections_sockets(0);
-#endif /* __NT__ */
+ handle_connections_sockets();
+#endif /* _WIN32 || HAVE_SMEM */
/* (void) pthread_attr_destroy(&connection_attrib); */
@@ -4938,7 +4860,7 @@ void create_thread_to_handle_connection(THD *thd)
/* Can't use my_error() since store_globals has not been called. */
my_snprintf(error_message_buff, sizeof(error_message_buff),
ER(ER_CANT_CREATE_THREAD), error);
- net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff);
+ net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
(void) pthread_mutex_lock(&LOCK_thread_count);
close_connection(thd,0,0);
delete thd;
@@ -5040,7 +4962,7 @@ inline void kill_broken_server()
/* Handle new connections and spawn new process to handle them */
#ifndef EMBEDDED_LIBRARY
-pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
+void handle_connections_sockets()
{
my_socket sock,new_sock;
uint error_count=0;
@@ -5243,13 +5165,19 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused)))
create_new_thread(thd);
}
+ DBUG_VOID_RETURN;
+}
+
+#ifdef _WIN32
+pthread_handler_t handle_connections_sockets_thread(void *arg)
+{
+ my_thread_init();
+ handle_connections_sockets();
decrement_handler_count();
- DBUG_RETURN(0);
+ return 0;
}
-
-#ifdef __NT__
pthread_handler_t handle_connections_namedpipes(void *arg)
{
HANDLE hConnectedPipe;
@@ -5329,7 +5257,7 @@ pthread_handler_t handle_connections_namedpipes(void *arg)
decrement_handler_count();
DBUG_RETURN(0);
}
-#endif /* __NT__ */
+#endif /* _WIN32 */
#ifdef HAVE_SMEM
@@ -5905,7 +5833,7 @@ struct my_option my_long_options[] =
"Deprecated option, use --external-locking instead.",
(uchar**) &opt_external_locking, (uchar**) &opt_external_locking,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef __NT__
+#ifdef _WIN32
{"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT).",
(uchar**) &opt_enable_named_pipe, (uchar**) &opt_enable_named_pipe, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -7571,10 +7499,7 @@ SHOW_VAR status_vars[]= {
static void print_version(void)
{
set_server_version();
- /*
- Note: the instance manager keys off the string 'Ver' so it can find the
- version from the output of 'mysqld --version', so don't change it!
- */
+
printf("%s Ver %s for %s on %s (%s)\n",my_progname,
server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT);
}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 05575e2744b..52e8d5d61c2 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -708,7 +708,8 @@ 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);
+TRP_GROUP_MIN_MAX *get_best_group_min_max(PARAM *param, SEL_TREE *tree,
+ double read_time);
static double get_index_only_read_time(const PARAM* param, ha_rows records,
int keynr);
@@ -2049,7 +2050,7 @@ public:
class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
{
private:
- bool have_min, have_max;
+ bool have_min, have_max, have_agg_distinct;
KEY_PART_INFO *min_max_arg_part;
uint group_prefix_len;
uint used_key_parts;
@@ -2061,11 +2062,13 @@ private:
SEL_TREE *range_tree; /* Represents all range predicates in the query. */
SEL_ARG *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */
uint param_idx; /* Index of used key in param->key. */
- /* Number of records selected by the ranges in index_tree. */
+ bool is_index_scan; /* Use index_next() instead of random read */
public:
+ /* Number of records selected by the ranges in index_tree. */
ha_rows quick_prefix_records;
public:
- TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
+ TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
+ bool have_agg_distinct_arg,
KEY_PART_INFO *min_max_arg_part_arg,
uint group_prefix_len_arg, uint used_key_parts_arg,
uint group_key_parts_arg, KEY *index_info_arg,
@@ -2074,11 +2077,12 @@ public:
SEL_TREE *tree_arg, SEL_ARG *index_tree_arg,
uint param_idx_arg, ha_rows quick_prefix_records_arg)
: have_min(have_min_arg), have_max(have_max_arg),
+ have_agg_distinct(have_agg_distinct_arg),
min_max_arg_part(min_max_arg_part_arg),
group_prefix_len(group_prefix_len_arg), used_key_parts(used_key_parts_arg),
group_key_parts(group_key_parts_arg), index_info(index_info_arg),
index(index_arg), key_infix_len(key_infix_len_arg), range_tree(tree_arg),
- index_tree(index_tree_arg), param_idx(param_idx_arg),
+ index_tree(index_tree_arg), param_idx(param_idx_arg), is_index_scan(FALSE),
quick_prefix_records(quick_prefix_records_arg)
{
if (key_infix_len)
@@ -2088,6 +2092,7 @@ public:
QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
MEM_ROOT *parent_alloc);
+ void use_index_scan() { is_index_scan= TRUE; }
};
@@ -2349,7 +2354,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
Notice that it can be constructed no matter if there is a range tree.
*/
- group_trp= get_best_group_min_max(&param, tree);
+ group_trp= get_best_group_min_max(&param, tree, best_read_time);
if (group_trp)
{
param.table->quick_condition_rows= min(group_trp->records,
@@ -9048,15 +9053,10 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
double *read_cost, ha_rows *records);
-/*
+/**
Test if this access method is applicable to a GROUP query with MIN/MAX
functions, and if so, construct a new TRP object.
- SYNOPSIS
- get_best_group_min_max()
- param Parameter from test_quick_select
- sel_tree Range tree generated by get_mm_tree
-
DESCRIPTION
Test whether a query can be computed via a QUICK_GROUP_MIN_MAX_SELECT.
Queries computable via a QUICK_GROUP_MIN_MAX_SELECT must satisfy the
@@ -9167,17 +9167,16 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
- Lift the limitation in condition (B3), that is, make this access method
applicable to ROLLUP queries.
- RETURN
- If mem_root != NULL
- - valid TRP_GROUP_MIN_MAX object if this QUICK class can be used for
- the query
- - NULL o/w.
- If mem_root == NULL
- - NULL
+ @param param Parameter from test_quick_select
+ @param sel_tree Range tree generated by get_mm_tree
+ @param read_time Best read time so far (=table/index scan time)
+ @return table read plan
+ @retval NULL Loose index scan not applicable or mem_root == NULL
+ @retval !NULL Loose index scan table read plan
*/
static TRP_GROUP_MIN_MAX *
-get_best_group_min_max(PARAM *param, SEL_TREE *tree)
+get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
{
THD *thd= param->thd;
JOIN *join= thd->lex->current_select->join;
@@ -9198,25 +9197,33 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
ORDER *tmp_group;
Item *item;
Item_field *item_field;
+ bool is_agg_distinct;
+ List<Item_field> agg_distinct_flds;
+
DBUG_ENTER("get_best_group_min_max");
/* Perform few 'cheap' tests whether this access method is applicable. */
if (!join)
DBUG_RETURN(NULL); /* This is not a select statement. */
if ((join->tables != 1) || /* The query must reference one table. */
- ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
- (!join->select_distinct)) ||
(join->select_lex->olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */
DBUG_RETURN(NULL);
if (table->s->keys == 0) /* There are no indexes to use. */
DBUG_RETURN(NULL);
- /* Analyze the query in more detail. */
- List_iterator<Item> select_items_it(join->fields_list);
-
/* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/
if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
DBUG_RETURN(NULL);
+
+ List_iterator<Item> select_items_it(join->fields_list);
+ is_agg_distinct = is_indexed_agg_distinct(join, &agg_distinct_flds);
+
+ if ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */
+ (!join->select_distinct) &&
+ !is_agg_distinct)
+ DBUG_RETURN(NULL);
+ /* Analyze the query in more detail. */
+
if (join->sum_funcs[0])
{
Item_sum *min_max_item;
@@ -9227,6 +9234,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
have_min= TRUE;
else if (min_max_item->sum_func() == Item_sum::MAX_FUNC)
have_max= TRUE;
+ else if (min_max_item->sum_func() == Item_sum::COUNT_DISTINCT_FUNC ||
+ min_max_item->sum_func() == Item_sum::SUM_DISTINCT_FUNC ||
+ min_max_item->sum_func() == Item_sum::AVG_DISTINCT_FUNC)
+ continue;
else
DBUG_RETURN(NULL);
@@ -9243,13 +9254,12 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
DBUG_RETURN(NULL);
}
}
-
/* Check (SA5). */
if (join->select_distinct)
{
while ((item= select_items_it++))
{
- if (item->type() != Item::FIELD_ITEM)
+ if (item->real_item()->type() != Item::FIELD_ITEM)
DBUG_RETURN(NULL);
}
}
@@ -9257,7 +9267,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
/* Check (GA4) - that there are no expressions among the group attributes. */
for (tmp_group= join->group_list; tmp_group; tmp_group= tmp_group->next)
{
- if ((*tmp_group->item)->type() != Item::FIELD_ITEM)
+ if ((*tmp_group->item)->real_item()->type() != Item::FIELD_ITEM)
DBUG_RETURN(NULL);
}
@@ -9276,6 +9286,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
uint best_param_idx= 0;
const uint pk= param->table->s->primary_key;
+ uint max_key_part;
SEL_ARG *cur_index_tree= NULL;
ha_rows cur_quick_prefix_records= 0;
uint cur_param_idx=MAX_KEY;
@@ -9329,6 +9340,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
}
}
+ max_key_part= 0;
+ used_key_parts_map.clear_all();
/*
Check (GA1) for GROUP BY queries.
*/
@@ -9352,6 +9365,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
{
cur_group_prefix_len+= cur_part->store_length;
++cur_group_key_parts;
+ max_key_part= cur_part - cur_index_info->key_part + 1;
+ used_key_parts_map.set_bit(max_key_part);
}
else
goto next_index;
@@ -9365,14 +9380,26 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
Later group_fields_array of ORDER objects is used to convert the query
to a GROUP query.
*/
- else if (join->select_distinct)
+ if ((!join->group_list && join->select_distinct) ||
+ is_agg_distinct)
{
- select_items_it.rewind();
- used_key_parts_map.clear_all();
- uint max_key_part= 0;
- while ((item= select_items_it++))
+ if (!is_agg_distinct)
{
- item_field= (Item_field*) item; /* (SA5) already checked above. */
+ select_items_it.rewind();
+ }
+
+ List_iterator<Item_field> agg_distinct_flds_it (agg_distinct_flds);
+ while (NULL != (item = (is_agg_distinct ?
+ (Item *) agg_distinct_flds_it++ : select_items_it++)))
+ {
+ /* (SA5) already checked above. */
+ item_field= (Item_field*) item->real_item();
+ DBUG_ASSERT(item->real_item()->type() == Item::FIELD_ITEM);
+
+ /* not doing loose index scan for derived tables */
+ if (!item_field->field)
+ goto next_index;
+
/* Find the order of the key part in the index. */
key_part_nr= get_field_keypart(cur_index_info, item_field->field);
/*
@@ -9381,7 +9408,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
if (used_key_parts_map.is_set(key_part_nr))
continue;
- if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
+ if (key_part_nr < 1 ||
+ (!is_agg_distinct && key_part_nr > join->fields_list.elements))
goto next_index;
cur_part= cur_index_info->key_part + key_part_nr - 1;
cur_group_prefix_len+= cur_part->store_length;
@@ -9401,10 +9429,6 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
if (all_parts != cur_parts)
goto next_index;
}
- else
- {
- DBUG_ASSERT(FALSE);
- }
/* Check (SA2). */
if (min_max_arg_item)
@@ -9558,7 +9582,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
/* The query passes all tests, so construct a new TRP object. */
read_plan= new (param->mem_root)
- TRP_GROUP_MIN_MAX(have_min, have_max, min_max_arg_part,
+ TRP_GROUP_MIN_MAX(have_min, have_max, is_agg_distinct,
+ min_max_arg_part,
group_prefix_len, used_key_parts,
group_key_parts, index_info, index,
key_infix_len,
@@ -9572,6 +9597,11 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
read_plan->read_cost= best_read_cost;
read_plan->records= best_records;
+ if (read_time < best_read_cost && is_agg_distinct)
+ {
+ read_plan->read_cost= 0;
+ read_plan->use_index_scan();
+ }
DBUG_PRINT("info",
("Returning group min/max plan: cost: %g, records: %lu",
@@ -10077,11 +10107,12 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
param->thd->lex->current_select->join,
- have_min, have_max, min_max_arg_part,
+ have_min, have_max,
+ have_agg_distinct, min_max_arg_part,
group_prefix_len, group_key_parts,
used_key_parts, index_info, index,
read_cost, records, key_infix_len,
- key_infix, parent_alloc);
+ key_infix, parent_alloc, is_index_scan);
if (!quick)
DBUG_RETURN(NULL);
@@ -10161,6 +10192,9 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
key_infix_len Length of the key infix appended to the group prefix
key_infix Infix of constants from equality predicates
parent_alloc Memory pool for this and quick_prefix_select data
+ is_index_scan get the next different key not by jumping on it via
+ index read, but by scanning until the end of the
+ rows with equal key value.
RETURN
None
@@ -10168,20 +10202,22 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
QUICK_GROUP_MIN_MAX_SELECT::
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
- bool have_max_arg,
+ bool have_max_arg, bool have_agg_distinct_arg,
KEY_PART_INFO *min_max_arg_part_arg,
uint group_prefix_len_arg, uint group_key_parts_arg,
uint used_key_parts_arg, KEY *index_info_arg,
uint use_index, double read_cost_arg,
ha_rows records_arg, uint key_infix_len_arg,
- uchar *key_infix_arg, MEM_ROOT *parent_alloc)
+ uchar *key_infix_arg, MEM_ROOT *parent_alloc,
+ bool is_index_scan_arg)
:join(join_arg), index_info(index_info_arg),
group_prefix_len(group_prefix_len_arg),
group_key_parts(group_key_parts_arg), have_min(have_min_arg),
- have_max(have_max_arg), seen_first_key(FALSE),
- min_max_arg_part(min_max_arg_part_arg), key_infix(key_infix_arg),
- key_infix_len(key_infix_len_arg), min_functions_it(NULL),
- max_functions_it(NULL)
+ have_max(have_max_arg), have_agg_distinct(have_agg_distinct_arg),
+ seen_first_key(FALSE), min_max_arg_part(min_max_arg_part_arg),
+ key_infix(key_infix_arg), key_infix_len(key_infix_len_arg),
+ min_functions_it(NULL), max_functions_it(NULL),
+ is_index_scan(is_index_scan_arg)
{
head= table;
file= head->file;
@@ -10744,6 +10780,56 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max()
}
+/**
+ Find the next different key value by skiping all the rows with the same key
+ value.
+
+ Implements a specialized loose index access method for queries
+ containing aggregate functions with distinct of the form:
+ SELECT [SUM|COUNT|AVG](DISTINCT a,...) FROM t
+ This method comes to replace the index scan + Unique class
+ (distinct selection) for loose index scan that visits all the rows of a
+ covering index instead of jumping in the begining of each group.
+ TODO: Placeholder function. To be replaced by a handler API call
+
+ @param is_index_scan hint to use index scan instead of random index read
+ to find the next different value.
+ @param file table handler
+ @param key_part group key to compare
+ @param record row data
+ @param group_prefix current key prefix data
+ @param group_prefix_len length of the current key prefix data
+ @param group_key_parts number of the current key prefix columns
+ @return status
+ @retval 0 success
+ @retval !0 failure
+*/
+
+static int index_next_different (bool is_index_scan, handler *file,
+ KEY_PART_INFO *key_part, uchar * record,
+ const uchar * group_prefix,
+ uint group_prefix_len,
+ uint group_key_parts)
+{
+ if (is_index_scan)
+ {
+ int result= 0;
+
+ while (!key_cmp (key_part, group_prefix, group_prefix_len))
+ {
+ result= file->index_next(record);
+ if (result)
+ return(result);
+ }
+ return result;
+ }
+ else
+ return file->index_read_map(record, group_prefix,
+ make_prev_keypart_map(group_key_parts),
+ HA_READ_AFTER_KEY);
+}
+
+
/*
Determine the prefix of the next group.
@@ -10790,9 +10876,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= index_next_different (is_index_scan, file, index_info->key_part,
+ record, group_prefix, group_prefix_len,
+ group_key_parts);
if (result)
DBUG_RETURN(result);
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 8d2ba1bb0a6..393ffcb2115 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -616,6 +616,7 @@ private:
uchar *last_prefix; /* Prefix of the last group for detecting EOF. */
bool have_min; /* Specify whether we are computing */
bool have_max; /* a MIN, a MAX, or both. */
+ bool have_agg_distinct;/* aggregate_function(DISTINCT ...). */
bool seen_first_key; /* Denotes whether the first key was retrieved.*/
KEY_PART_INFO *min_max_arg_part; /* The keypart of the only argument field */
/* of all MIN/MAX functions. */
@@ -629,6 +630,11 @@ private:
List<Item_sum> *max_functions;
List_iterator<Item_sum> *min_functions_it;
List_iterator<Item_sum> *max_functions_it;
+ /*
+ Use index scan to get the next different key instead of jumping into it
+ through index read
+ */
+ bool is_index_scan;
public:
/*
The following two members are public to allow easy access from
@@ -646,12 +652,13 @@ private:
void update_max_result();
public:
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min,
- bool have_max, KEY_PART_INFO *min_max_arg_part,
+ bool have_max, bool have_agg_distinct,
+ KEY_PART_INFO *min_max_arg_part,
uint group_prefix_len, uint group_key_parts,
uint used_key_parts, KEY *index_info, uint
use_index, double read_cost, ha_rows records, uint
key_infix_len, uchar *key_infix, MEM_ROOT
- *parent_alloc);
+ *parent_alloc, bool is_index_scan);
~QUICK_GROUP_MIN_MAX_SELECT();
bool add_range(SEL_ARG *sel_range);
void update_key_stat();
@@ -667,6 +674,12 @@ public:
#ifndef DBUG_OFF
void dbug_dump(int indent, bool verbose);
#endif
+ bool is_agg_distinct() { return have_agg_distinct; }
+ virtual void append_loose_scan_type(String *str)
+ {
+ if (is_index_scan)
+ str->append(STRING_WITH_LEN(" (scanning)"));
+ }
};
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 8e7265ba1ad..d995faf1ab6 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -355,10 +355,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
+ item_sum->set_aggregator (item_sum->with_distinct ?
+ Aggregator::DISTINCT_AGGREGATOR :
+ Aggregator::SIMPLE_AGGREGATOR);
if (!count)
{
/* If count == 0, then we know that is_exact_count == TRUE. */
- ((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */
+ ((Item_sum_min*) item_sum)->aggregator_clear(); /* Set to NULL. */
}
else
((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */
@@ -443,10 +446,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
+ item_sum->set_aggregator (item_sum->with_distinct ?
+ Aggregator::DISTINCT_AGGREGATOR :
+ Aggregator::SIMPLE_AGGREGATOR);
if (!count)
{
/* If count != 1, then we know that is_exact_count == TRUE. */
- ((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */
+ ((Item_sum_max*) item_sum)->aggregator_clear(); /* Set to NULL. */
}
else
((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */
diff --git a/sql/partition_element.h b/sql/partition_element.h
index 905bc38165b..bede5264c71 100644
--- a/sql/partition_element.h
+++ b/sql/partition_element.h
@@ -32,7 +32,8 @@ enum partition_state {
PART_REORGED_DROPPED= 5,
PART_CHANGED= 6,
PART_IS_CHANGED= 7,
- PART_IS_ADDED= 8
+ PART_IS_ADDED= 8,
+ PART_ADMIN= 9
};
/*
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 4f69a0fdb52..7abc051af68 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -28,13 +28,13 @@
#include <stdarg.h>
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
+bool net_send_error_packet(THD *, uint, const char *, const char *);
/* Declared non-static only because of the embedded library. */
-bool net_send_error_packet(THD *thd, uint sql_errno, const char *err);
-bool net_send_ok(THD *, uint, uint, ha_rows, ulonglong, const char *);
-bool net_send_eof(THD *thd, uint server_status, uint total_warn_count);
+bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *);
+/* Declared non-static only because of the embedded library. */
+bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count);
#ifndef EMBEDDED_LIBRARY
-static bool write_eof_packet(THD *thd, NET *net,
- uint server_status, uint total_warn_count);
+static bool write_eof_packet(THD *, NET *, uint, uint);
#endif
#ifndef EMBEDDED_LIBRARY
@@ -58,6 +58,64 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length)
}
+
+
+/*
+ net_store_data() - extended version with character set conversion.
+
+ It is optimized for short strings whose length after
+ conversion is garanteed to be less than 251, which accupies
+ exactly one byte to store length. It allows not to use
+ the "convert" member as a temporary buffer, conversion
+ is done directly to the "packet" member.
+ The limit 251 is good enough to optimize send_result_set_metadata()
+ because column, table, database names fit into this limit.
+*/
+
+#ifndef EMBEDDED_LIBRARY
+bool Protocol::net_store_data(const uchar *from, size_t length,
+ CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
+{
+ uint dummy_errors;
+ /* Calculate maxumum possible result length */
+ uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
+ if (conv_length > 250)
+ {
+ /*
+ For strings with conv_length greater than 250 bytes
+ we don't know how many bytes we will need to store length: one or two,
+ because we don't know result length until conversion is done.
+ For example, when converting from utf8 (mbmaxlen=3) to latin1,
+ conv_length=300 means that the result length can vary between 100 to 300.
+ length=100 needs one byte, length=300 needs to bytes.
+
+ Thus conversion directly to "packet" is not worthy.
+ Let's use "convert" as a temporary buffer.
+ */
+ return (convert->copy((const char*) from, length, from_cs,
+ to_cs, &dummy_errors) ||
+ net_store_data((const uchar*) convert->ptr(), convert->length()));
+ }
+
+ ulong packet_length= packet->length();
+ ulong new_length= packet_length + conv_length + 1;
+
+ if (new_length > packet->alloced_length() && packet->realloc(new_length))
+ return 1;
+
+ char *length_pos= (char*) packet->ptr() + packet_length;
+ char *to= length_pos + 1;
+
+ to+= copy_and_convert(to, conv_length, to_cs,
+ (const char*) from, length, from_cs, &dummy_errors);
+
+ net_store_length((uchar*) length_pos, to - length_pos - 1);
+ packet->length((uint) (to - packet->ptr()));
+ return 0;
+}
+#endif
+
+
/**
Send a error string to client.
@@ -80,29 +138,33 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length)
@retval TRUE An error occurred and the message wasn't sent properly
*/
-bool net_send_error(THD *thd, uint sql_errno, const char *err)
+bool net_send_error(THD *thd, uint sql_errno, const char *err,
+ const char* sqlstate)
{
DBUG_ENTER("net_send_error");
DBUG_ASSERT(!thd->spcont);
DBUG_ASSERT(sql_errno);
- DBUG_ASSERT(err && err[0]);
+ DBUG_ASSERT(err);
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
bool error;
+ if (sqlstate == NULL)
+ sqlstate= mysql_errno_to_sqlstate(sql_errno);
+
/*
It's one case when we can push an error even though there
is an OK or EOF already.
*/
- thd->main_da.can_overwrite_status= TRUE;
+ thd->stmt_da->can_overwrite_status= TRUE;
/* Abort multi-result sets */
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
- error= net_send_error_packet(thd, sql_errno, err);
+ error= net_send_error_packet(thd, sql_errno, err, sqlstate);
- thd->main_da.can_overwrite_status= FALSE;
+ thd->stmt_da->can_overwrite_status= FALSE;
DBUG_RETURN(error);
}
@@ -124,7 +186,7 @@ bool net_send_error(THD *thd, uint sql_errno, const char *err)
@param thd Thread handler
@param server_status The server status
- @param total_warn_count Total number of warnings
+ @param statement_warn_count Total number of warnings
@param affected_rows Number of rows changed by statement
@param id Auto_increment id for first row (if used)
@param message Message to send to the client (Used by mysql_status)
@@ -138,8 +200,8 @@ bool net_send_error(THD *thd, uint sql_errno, const char *err)
#ifndef EMBEDDED_LIBRARY
bool
net_send_ok(THD *thd,
- uint server_status, uint total_warn_count,
- ha_rows affected_rows, ulonglong id, const char *message)
+ uint server_status, uint statement_warn_count,
+ ulonglong affected_rows, ulonglong id, const char *message)
{
NET *net= &thd->net;
uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
@@ -162,12 +224,12 @@ net_send_ok(THD *thd,
(ulong) affected_rows,
(ulong) id,
(uint) (server_status & 0xffff),
- (uint) total_warn_count));
+ (uint) statement_warn_count));
int2store(pos, server_status);
pos+=2;
/* We can only return up to 65535 warnings in two bytes */
- uint tmp= min(total_warn_count, 65535);
+ uint tmp= min(statement_warn_count, 65535);
int2store(pos, tmp);
pos+= 2;
}
@@ -176,7 +238,7 @@ net_send_ok(THD *thd,
int2store(pos, server_status);
pos+=2;
}
- thd->main_da.can_overwrite_status= TRUE;
+ thd->stmt_da->can_overwrite_status= TRUE;
if (message && message[0])
pos= net_store_data(pos, (uchar*) message, strlen(message));
@@ -184,7 +246,7 @@ net_send_ok(THD *thd,
if (!error)
error= net_flush(net);
- thd->main_da.can_overwrite_status= FALSE;
+ thd->stmt_da->can_overwrite_status= FALSE;
DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
DBUG_RETURN(error);
@@ -208,7 +270,7 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
@param thd Thread handler
@param server_status The server status
- @param total_warn_count Total number of warnings
+ @param statement_warn_count Total number of warnings
@return
@retval FALSE The message was successfully sent
@@ -216,7 +278,7 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
*/
bool
-net_send_eof(THD *thd, uint server_status, uint total_warn_count)
+net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
{
NET *net= &thd->net;
bool error= FALSE;
@@ -224,11 +286,11 @@ net_send_eof(THD *thd, uint server_status, uint total_warn_count)
/* Set to TRUE if no active vio, to work well in case of --init-file */
if (net->vio != 0)
{
- thd->main_da.can_overwrite_status= TRUE;
- error= write_eof_packet(thd, net, server_status, total_warn_count);
+ thd->stmt_da->can_overwrite_status= TRUE;
+ error= write_eof_packet(thd, net, server_status, statement_warn_count);
if (!error)
error= net_flush(net);
- thd->main_da.can_overwrite_status= FALSE;
+ thd->stmt_da->can_overwrite_status= FALSE;
DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
}
DBUG_RETURN(error);
@@ -242,7 +304,7 @@ net_send_eof(THD *thd, uint server_status, uint total_warn_count)
@param thd The thread handler
@param net The network handler
@param server_status The server status
- @param total_warn_count The number of warnings
+ @param statement_warn_count The number of warnings
@return
@@ -252,7 +314,7 @@ net_send_eof(THD *thd, uint server_status, uint total_warn_count)
static bool write_eof_packet(THD *thd, NET *net,
uint server_status,
- uint total_warn_count)
+ uint statement_warn_count)
{
bool error;
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -262,7 +324,7 @@ static bool write_eof_packet(THD *thd, NET *net,
Don't send warn count during SP execution, as the warn_list
is cleared between substatements, and mysqltest gets confused
*/
- uint tmp= min(total_warn_count, 65535);
+ uint tmp= min(statement_warn_count, 65535);
buff[0]= 254;
int2store(buff+1, tmp);
/*
@@ -309,7 +371,9 @@ bool send_old_password_request(THD *thd)
@retval TRUE An error occurred and the messages wasn't sent properly
*/
-bool net_send_error_packet(THD *thd, uint sql_errno, const char *err)
+bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
+ const char* sqlstate)
+
{
NET *net= &thd->net;
uint length;
@@ -338,7 +402,7 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err)
{
/* The first # is to make the protocol backward compatible */
buff[2]= '#';
- pos= (uchar*) strmov((char*) buff+3, mysql_errno_to_sqlstate(sql_errno));
+ pos= (uchar*) strmov((char*) buff+3, sqlstate);
}
length= (uint) (strmake((char*) pos, err, MYSQL_ERRMSG_SIZE-1) -
(char*) buff);
@@ -430,45 +494,45 @@ static uchar *net_store_length_fast(uchar *packet, uint length)
void net_end_statement(THD *thd)
{
- DBUG_ASSERT(! thd->main_da.is_sent);
+ DBUG_ASSERT(! thd->stmt_da->is_sent);
/* Can not be true, but do not take chances in production. */
- if (thd->main_da.is_sent)
+ if (thd->stmt_da->is_sent)
return;
bool error= FALSE;
- switch (thd->main_da.status()) {
+ switch (thd->stmt_da->status()) {
case Diagnostics_area::DA_ERROR:
/* The query failed, send error to log and abort bootstrap. */
error= net_send_error(thd,
- thd->main_da.sql_errno(),
- thd->main_da.message());
+ thd->stmt_da->sql_errno(),
+ thd->stmt_da->message(),
+ thd->stmt_da->get_sqlstate());
break;
case Diagnostics_area::DA_EOF:
error= net_send_eof(thd,
- thd->main_da.server_status(),
- thd->main_da.total_warn_count());
+ thd->stmt_da->server_status(),
+ thd->stmt_da->statement_warn_count());
break;
case Diagnostics_area::DA_OK:
error= net_send_ok(thd,
- thd->main_da.server_status(),
- thd->main_da.total_warn_count(),
- thd->main_da.affected_rows(),
- thd->main_da.last_insert_id(),
- thd->main_da.message());
+ thd->stmt_da->server_status(),
+ thd->stmt_da->statement_warn_count(),
+ thd->stmt_da->affected_rows(),
+ thd->stmt_da->last_insert_id(),
+ thd->stmt_da->message());
break;
case Diagnostics_area::DA_DISABLED:
break;
case Diagnostics_area::DA_EMPTY:
default:
DBUG_ASSERT(0);
- error= net_send_ok(thd, thd->server_status, thd->total_warn_count,
- 0, 0, NULL);
+ error= net_send_ok(thd, thd->server_status, 0, 0, 0, NULL);
break;
}
if (!error)
- thd->main_da.is_sent= TRUE;
+ thd->stmt_da->is_sent= TRUE;
}
@@ -711,7 +775,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
to show that there is no cursor.
Send no warning information, as it will be sent at statement end.
*/
- write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
+ write_eof_packet(thd, &thd->net, thd->server_status,
+ thd->warning_info->statement_warn_count());
}
DBUG_RETURN(prepare_for_send(list));
@@ -820,10 +885,10 @@ bool Protocol::store_string_aux(const char *from, size_t length,
fromcs != &my_charset_bin &&
tocs != &my_charset_bin)
{
- uint dummy_errors;
- return (convert->copy(from, length, fromcs, tocs, &dummy_errors) ||
- net_store_data((uchar*) convert->ptr(), convert->length()));
+ /* Store with conversion */
+ return net_store_data((uchar*) from, length, fromcs, tocs);
}
+ /* Store without conversion */
return net_store_data((uchar*) from, length);
}
diff --git a/sql/protocol.h b/sql/protocol.h
index 251ba6fbc33..3b6a3bdb863 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -17,6 +17,7 @@
#pragma interface /* gcc class implementation */
#endif
+#include "sql_error.h"
class i_string;
class THD;
@@ -42,6 +43,8 @@ protected:
MYSQL_FIELD *next_mysql_field;
MEM_ROOT *alloc;
#endif
+ bool net_store_data(const uchar *from, size_t length,
+ CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
bool store_string_aux(const char *from, size_t length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
public:
@@ -173,7 +176,8 @@ 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);
+bool net_send_error(THD *thd, uint sql_errno, const char *err,
+ const char* sqlstate);
void net_end_statement(THD *thd);
bool send_old_password_request(THD *thd);
uchar *net_store_data(uchar *to,const uchar *from, size_t length);
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 582348608de..e470317abef 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -913,7 +913,7 @@ bool load_master_data(THD* thd)
goto err;
}
/* Clear the result of mysql_create_db(). */
- thd->main_da.reset_diagnostics_area();
+ thd->stmt_da->reset_diagnostics_area();
if (mysql_select_db(&mysql, db) ||
mysql_real_query(&mysql, STRING_WITH_LEN("SHOW TABLES")) ||
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index 18fbae9bb9d..61d3840569f 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -183,7 +183,7 @@ int init_relay_log_info(Relay_log_info* rli,
{
sql_print_error("Failed to create a new relay log info file (\
file '%s', errno %d)", fname, my_errno);
- msg= current_thd->main_da.message();
+ msg= current_thd->stmt_da->message();
goto err;
}
if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
@@ -191,7 +191,7 @@ file '%s', errno %d)", fname, my_errno);
{
sql_print_error("Failed to create a cache on relay log info file '%s'",
fname);
- msg= current_thd->main_da.message();
+ msg= current_thd->stmt_da->message();
goto err;
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index b64b54fdd29..def0be4aff4 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -434,7 +434,7 @@ static sys_var_thd_enum sys_myisam_stats_method(&vars, "myisam_stats_met
&myisam_stats_method_typelib,
NULL);
-#ifdef __NT__
+#ifdef _WIN32
/* purecov: begin inspected */
static sys_var_const sys_named_pipe(&vars, "named_pipe",
OPT_GLOBAL, SHOW_MY_BOOL,
@@ -2916,7 +2916,7 @@ bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var)
{
char buf[20];
int10_to_str((int) var->value->val_int(), buf, -10);
- my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%s'", MYF(0), buf);
+ my_printf_error(ER_UNKNOWN_LOCALE, ER(ER_UNKNOWN_LOCALE), MYF(0), buf);
return 1;
}
}
@@ -2932,8 +2932,7 @@ bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var)
const char *locale_str= res->c_ptr();
if (!(locale_match= my_locale_by_name(locale_str)))
{
- my_printf_error(ER_UNKNOWN_ERROR,
- "Unknown locale: '%s'", MYF(0), locale_str);
+ my_printf_error(ER_UNKNOWN_LOCALE, ER(ER_UNKNOWN_LOCALE), MYF(0), locale_str);
return 1;
}
}
@@ -3133,17 +3132,13 @@ static int check_pseudo_thread_id(THD *thd, set_var *var)
static uchar *get_warning_count(THD *thd)
{
- thd->sys_var_tmp.long_value=
- (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
- thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
- thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
+ thd->sys_var_tmp.long_value= thd->warning_info->warn_count();
return (uchar*) &thd->sys_var_tmp.long_value;
}
static uchar *get_error_count(THD *thd)
{
- thd->sys_var_tmp.long_value=
- thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
+ thd->sys_var_tmp.long_value= thd->warning_info->error_count();
return (uchar*) &thd->sys_var_tmp.long_value;
}
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index 3aba434b284..a98b3af5dd5 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -4879,13 +4879,7 @@ ER_ZLIB_Z_DATA_ERROR
por "ZLIB: Dados de entrada está corrupto"
spa "ZLIB: Dato de entrada fué corrompido para zlib"
ER_CUT_VALUE_GROUP_CONCAT
- eng "%d line(s) were cut by GROUP_CONCAT()"
- ger "%d Zeile(n) durch GROUP_CONCAT() abgeschnitten"
- nla "%d regel(s) door GROUP_CONCAT() ingekort"
- por "%d linha(s) foram cortada(s) por GROUP_CONCAT()"
- spa "%d línea(s) fue(fueron) cortadas por group_concat()"
- swe "%d rad(er) kapades av group_concat()"
- ukr "%d line(s) was(were) cut by group_concat()"
+ eng "Row %u was cut by GROUP_CONCAT()"
ER_WARN_TOO_FEW_RECORDS 01000
eng "Row %ld doesn't contain data for all columns"
ger "Zeile %ld enthält nicht für alle Felder Daten"
@@ -6206,3 +6200,33 @@ ER_TOO_MANY_CONCURRENT_TRXS
WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED
eng "Non-ASCII separator arguments are not fully supported"
+
+ER_DUP_SIGNAL_SET 42000
+ eng "Duplicate condition information item '%s'"
+
+# Note that the SQLSTATE is not 01000, it is provided by SIGNAL/RESIGNAL
+ER_SIGNAL_WARN 01000
+ eng "Unhandled user-defined warning condition"
+
+# Note that the SQLSTATE is not 02000, it is provided by SIGNAL/RESIGNAL
+ER_SIGNAL_NOT_FOUND 02000
+ eng "Unhandled user-defined not found condition"
+
+# Note that the SQLSTATE is not HY000, it is provided by SIGNAL/RESIGNAL
+ER_SIGNAL_EXCEPTION HY000
+ eng "Unhandled user-defined exception condition"
+
+ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER 0K000
+ eng "RESIGNAL when handler not active"
+
+ER_SIGNAL_BAD_CONDITION_TYPE
+ eng "SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE"
+
+WARN_COND_ITEM_TRUNCATED
+ eng "Data truncated for condition item '%s'"
+
+ER_COND_ITEM_TOO_LONG
+ eng "Data too long for condition item '%s'"
+
+ER_UNKNOWN_LOCALE
+ eng "Unknown locale: '%-.64s'"
diff --git a/sql/slave.cc b/sql/slave.cc
index fac9ee214c5..7ad282c0f24 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1274,7 +1274,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
else
{
/* Clear the OK result of mysql_rm_table(). */
- thd->main_da.reset_diagnostics_area();
+ thd->stmt_da->reset_diagnostics_area();
}
}
@@ -1297,7 +1297,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
goto err; // mysql_parse took care of the error send
thd_proc_info(thd, "Opening master dump table");
- thd->main_da.reset_diagnostics_area(); /* cleanup from CREATE_TABLE */
+ thd->stmt_da->reset_diagnostics_area(); /* cleanup from CREATE_TABLE */
/*
Note: If this function starts to fail for MERGE tables,
change the next two lines to these:
@@ -2011,7 +2011,7 @@ static int has_temporary_error(THD *thd)
DBUG_ENTER("has_temporary_error");
DBUG_EXECUTE_IF("all_errors_are_temporary_errors",
- if (thd->main_da.is_error())
+ if (thd->stmt_da->is_error())
{
thd->clear_error();
my_error(ER_LOCK_DEADLOCK, MYF(0));
@@ -2030,20 +2030,21 @@ static int has_temporary_error(THD *thd)
currently, InnoDB deadlock detected by InnoDB or lock
wait timeout (innodb_lock_wait_timeout exceeded
*/
- if (thd->main_da.sql_errno() == ER_LOCK_DEADLOCK ||
- thd->main_da.sql_errno() == ER_LOCK_WAIT_TIMEOUT)
+ if (thd->stmt_da->sql_errno() == ER_LOCK_DEADLOCK ||
+ thd->stmt_da->sql_errno() == ER_LOCK_WAIT_TIMEOUT)
DBUG_RETURN(1);
#ifdef HAVE_NDB_BINLOG
/*
currently temporary error set in ndbcluster
*/
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
while ((err= it++))
{
- DBUG_PRINT("info", ("has warning %d %s", err->code, err->msg));
- switch (err->code)
+ DBUG_PRINT("info", ("has condition %d %s", err->get_sql_errno(),
+ err->get_message_text()));
+ switch (err->get_sql_errno())
{
case ER_GET_TEMPORARY_ERRMSG:
DBUG_RETURN(1);
@@ -2977,9 +2978,9 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
if (check_temp_dir(rli->slave_patternload_file))
{
- rli->report(ERROR_LEVEL, thd->main_da.sql_errno(),
+ rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(),
"Unable to use slave's temporary directory %s - %s",
- slave_load_tmpdir, thd->main_da.message());
+ slave_load_tmpdir, thd->stmt_da->message());
goto err;
}
@@ -2989,7 +2990,7 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
execute_init_command(thd, &sys_init_slave, &LOCK_sys_init_slave);
if (thd->is_slave_error)
{
- rli->report(ERROR_LEVEL, thd->main_da.sql_errno(),
+ rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(),
"Slave SQL thread aborted. Can't execute init_slave query");
goto err;
}
@@ -3033,20 +3034,20 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
if (thd->is_error())
{
- char const *const errmsg= thd->main_da.message();
+ char const *const errmsg= thd->stmt_da->message();
DBUG_PRINT("info",
- ("thd->main_da.sql_errno()=%d; rli->last_error.number=%d",
- thd->main_da.sql_errno(), last_errno));
+ ("thd->stmt_da->sql_errno()=%d; rli->last_error.number=%d",
+ thd->stmt_da->sql_errno(), last_errno));
if (last_errno == 0)
{
/*
This function is reporting an error which was not reported
while executing exec_relay_log_event().
*/
- rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), errmsg);
+ rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(), errmsg);
}
- else if (last_errno != thd->main_da.sql_errno())
+ else if (last_errno != thd->stmt_da->sql_errno())
{
/*
* An error was reported while executing exec_relay_log_event()
@@ -3055,12 +3056,12 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
* what caused the problem.
*/
sql_print_error("Slave (additional info): %s Error_code: %d",
- errmsg, thd->main_da.sql_errno());
+ errmsg, thd->stmt_da->sql_errno());
}
}
/* Print any warnings issued */
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
/*
Added controlled slave thread cancel for replication
@@ -3069,9 +3070,9 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME,
bool udf_error = false;
while ((err= it++))
{
- if (err->code == ER_CANT_OPEN_LIBRARY)
+ if (err->get_sql_errno() == ER_CANT_OPEN_LIBRARY)
udf_error = true;
- sql_print_warning("Slave: %s Error_code: %d",err->msg, err->code);
+ sql_print_warning("Slave: %s Error_code: %d", err->get_message_text(), err->get_sql_errno());
}
if (udf_error)
sql_print_error("Error loading user-defined library, slave SQL "
diff --git a/sql/sp.cc b/sql/sp.cc
index 4d840f53e2f..5898e553320 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -522,16 +522,24 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
struct Silence_deprecated_warning : public Internal_error_handler
{
public:
- virtual bool handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
};
bool
-Silence_deprecated_warning::handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+Silence_deprecated_warning::handle_condition(
+ THD *,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level level,
+ const char*,
+ MYSQL_ERROR ** cond_hdl)
{
+ *cond_hdl= NULL;
if (sql_errno == ER_WARN_DEPRECATED_SYNTAX &&
level == MYSQL_ERROR::WARN_LEVEL_WARN)
return TRUE;
@@ -1336,7 +1344,7 @@ sp_exist_routines(THD *thd, TABLE_LIST *routines, bool any)
&thd->sp_proc_cache, FALSE) != NULL ||
sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
&thd->sp_func_cache, FALSE) != NULL;
- mysql_reset_errors(thd, TRUE);
+ thd->warning_info->clear_warning_info(thd->query_id);
if (sp_object_found)
{
if (any)
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index aed19b76011..908f0997be6 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1083,6 +1083,7 @@ sp_head::execute(THD *thd)
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
Object_creation_ctx *saved_creation_ctx;
+ Warning_info *saved_warning_info, warning_info(thd->warning_info->warn_id());
/* Use some extra margin for possible SP recursion and functions */
if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (uchar*)&old_packet))
@@ -1131,6 +1132,11 @@ sp_head::execute(THD *thd)
thd->is_slave_error= 0;
old_arena= thd->stmt_arena;
+ /* Push a new warning information area. */
+ warning_info.append_warning_info(thd, thd->warning_info);
+ saved_warning_info= thd->warning_info;
+ thd->warning_info= &warning_info;
+
/*
Switch query context. This has to be done early as this is sometimes
allocated trough sql_alloc
@@ -1278,29 +1284,33 @@ sp_head::execute(THD *thd)
*/
if (ctx)
{
- uint hf;
+ uint handler_index;
- switch (ctx->found_handler(&hip, &hf)) {
+ switch (ctx->found_handler(& hip, & handler_index)) {
case SP_HANDLER_NONE:
break;
case SP_HANDLER_CONTINUE:
thd->restore_active_arena(&execute_arena, &backup_arena);
thd->set_n_backup_active_arena(&execute_arena, &backup_arena);
ctx->push_hstack(i->get_cont_dest());
- // Fall through
+ /* Fall through */
default:
+ if (ctx->end_partial_result_set)
+ thd->protocol->end_partial_result_set(thd);
ip= hip;
err_status= FALSE;
ctx->clear_handler();
- ctx->enter_handler(hip);
+ ctx->enter_handler(hip, handler_index);
thd->clear_error();
thd->is_fatal_error= 0;
thd->killed= THD::NOT_KILLED;
thd->mysys_var->abort= 0;
continue;
}
+
+ ctx->end_partial_result_set= FALSE;
}
- } while (!err_status && !thd->killed);
+ } while (!err_status && !thd->killed && !thd->is_fatal_error);
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.finish_current_query();
@@ -1334,6 +1344,10 @@ sp_head::execute(THD *thd)
thd->stmt_arena= old_arena;
state= EXECUTED;
+ /* Restore the caller's original warning information area. */
+ saved_warning_info->merge_with_routine_info(thd, thd->warning_info);
+ thd->warning_info= saved_warning_info;
+
done:
DBUG_PRINT("info", ("err_status: %d killed: %d is_slave_error: %d report_error: %d",
err_status, thd->killed, thd->is_slave_error,
@@ -2523,7 +2537,8 @@ void sp_head::optimize()
else
{
if (src != dst)
- { // Move the instruction and update prev. jumps
+ {
+ /* Move the instruction and update prev. jumps */
sp_instr *ibp;
List_iterator_fast<sp_instr> li(bp);
@@ -2848,7 +2863,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
{
res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this);
- if (thd->main_da.is_eof())
+ if (thd->stmt_da->is_eof())
net_end_statement(thd);
query_cache_end_of_result(thd);
@@ -2862,7 +2877,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
thd->query_name_consts= 0;
if (!thd->is_error())
- thd->main_da.reset_diagnostics_area();
+ thd->stmt_da->reset_diagnostics_area();
}
DBUG_RETURN(res || thd->is_error());
}
@@ -3238,7 +3253,7 @@ sp_instr_hpush_jump::execute(THD *thd, uint *nextp)
sp_cond_type_t *p;
while ((p= li++))
- thd->spcont->push_handler(p, m_ip+1, m_type, m_frame);
+ thd->spcont->push_handler(p, m_ip+1, m_type);
*nextp= m_dest;
DBUG_RETURN(0);
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index 302faf3f681..31c307ebe74 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -51,7 +51,8 @@ sp_cond_check(LEX_STRING *sqlstate)
(c < 'A' || 'Z' < c))
return FALSE;
}
- if (strcmp(sqlstate->str, "00000") == 0)
+ /* SQLSTATE class '00' : completion condition */
+ if (strncmp(sqlstate->str, "00", 2) == 0)
return FALSE;
return TRUE;
}
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index 3145ba2fea4..75e55880e60 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -71,7 +71,7 @@ typedef struct sp_label
typedef struct sp_cond_type
{
enum { number, state, warning, notfound, exception } type;
- char sqlstate[6];
+ char sqlstate[SQLSTATE_LENGTH+1];
uint mysqlerr;
} sp_cond_type_t;
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 9b237b3e7cc..51b797fe088 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -32,7 +32,8 @@
sp_rcontext::sp_rcontext(sp_pcontext *root_parsing_ctx,
Field *return_value_fld,
sp_rcontext *prev_runtime_ctx)
- :m_root_parsing_ctx(root_parsing_ctx),
+ :end_partial_result_set(FALSE),
+ m_root_parsing_ctx(root_parsing_ctx),
m_var_table(0),
m_var_items(0),
m_return_value_fld(return_value_fld),
@@ -68,21 +69,28 @@ sp_rcontext::~sp_rcontext()
bool sp_rcontext::init(THD *thd)
{
+ uint handler_count= m_root_parsing_ctx->max_handler_index();
+ uint i;
+
in_sub_stmt= thd->in_sub_stmt;
if (init_var_table(thd) || init_var_items())
return TRUE;
+ if (!(m_raised_conditions= new (thd->mem_root) MYSQL_ERROR[handler_count]))
+ return TRUE;
+
+ for (i= 0; i<handler_count; i++)
+ m_raised_conditions[i].init(thd->mem_root);
+
return
!(m_handler=
- (sp_handler_t*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
- sizeof(sp_handler_t))) ||
+ (sp_handler_t*)thd->alloc(handler_count * sizeof(sp_handler_t))) ||
!(m_hstack=
- (uint*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
- sizeof(uint))) ||
+ (uint*)thd->alloc(handler_count * sizeof(uint))) ||
!(m_in_handler=
- (uint*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
- sizeof(uint))) ||
+ (sp_active_handler_t*)thd->alloc(handler_count *
+ sizeof(sp_active_handler_t))) ||
!(m_cstack=
(sp_cursor**)thd->alloc(m_root_parsing_ctx->max_cursor_index() *
sizeof(sp_cursor*))) ||
@@ -194,13 +202,19 @@ sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
*/
bool
-sp_rcontext::find_handler(THD *thd, uint sql_errno,
- MYSQL_ERROR::enum_warning_level level)
+sp_rcontext::find_handler(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
{
if (m_hfound >= 0)
- return 1; // Already got one
+ {
+ *cond_hdl= NULL;
+ return TRUE; // Already got one
+ }
- const char *sqlstate= mysql_errno_to_sqlstate(sql_errno);
int i= m_hcount, found= -1;
/*
@@ -220,7 +234,7 @@ sp_rcontext::find_handler(THD *thd, uint sql_errno,
/* Check active handlers, to avoid invoking one recursively */
while (j--)
- if (m_in_handler[j] == m_handler[i].handler)
+ if (m_in_handler[j].ip == m_handler[i].handler)
break;
if (j >= 0)
continue; // Already executing this handler
@@ -264,10 +278,26 @@ sp_rcontext::find_handler(THD *thd, uint sql_errno,
*/
if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR)
- return m_prev_runtime_ctx->find_handler(thd, sql_errno, level);
+ return m_prev_runtime_ctx->find_handler(thd,
+ sql_errno,
+ sqlstate,
+ level,
+ msg,
+ cond_hdl);
+ *cond_hdl= NULL;
return FALSE;
}
+
m_hfound= found;
+
+ MYSQL_ERROR *raised= NULL;
+ DBUG_ASSERT(m_hfound >= 0);
+ DBUG_ASSERT((uint) m_hfound < m_root_parsing_ctx->max_handler_index());
+ raised= & m_raised_conditions[m_hfound];
+ raised->clear();
+ raised->set(sql_errno, sqlstate, level, msg);
+
+ *cond_hdl= raised;
return TRUE;
}
@@ -293,9 +323,12 @@ sp_rcontext::find_handler(THD *thd, uint sql_errno,
FALSE if no handler was found.
*/
bool
-sp_rcontext::handle_error(uint sql_errno,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+sp_rcontext::handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
{
MYSQL_ERROR::enum_warning_level elevated_level= level;
@@ -308,7 +341,7 @@ sp_rcontext::handle_error(uint sql_errno,
elevated_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
}
- return find_handler(thd, sql_errno, elevated_level);
+ return find_handler(thd, sql_errno, sqlstate, elevated_level, msg, cond_hdl);
}
void
@@ -335,7 +368,7 @@ sp_rcontext::pop_cursors(uint count)
}
void
-sp_rcontext::push_handler(struct sp_cond_type *cond, uint h, int type, uint f)
+sp_rcontext::push_handler(struct sp_cond_type *cond, uint h, int type)
{
DBUG_ENTER("sp_rcontext::push_handler");
DBUG_ASSERT(m_hcount < m_root_parsing_ctx->max_handler_index());
@@ -343,7 +376,6 @@ sp_rcontext::push_handler(struct sp_cond_type *cond, uint h, int type, uint f)
m_handler[m_hcount].cond= cond;
m_handler[m_hcount].handler= h;
m_handler[m_hcount].type= type;
- m_handler[m_hcount].foffset= f;
m_hcount+= 1;
DBUG_PRINT("info", ("m_hcount: %d", m_hcount));
@@ -382,11 +414,13 @@ sp_rcontext::pop_hstack()
}
void
-sp_rcontext::enter_handler(int hid)
+sp_rcontext::enter_handler(uint hip, uint hindex)
{
DBUG_ENTER("sp_rcontext::enter_handler");
DBUG_ASSERT(m_ihsp < m_root_parsing_ctx->max_handler_index());
- m_in_handler[m_ihsp++]= hid;
+ m_in_handler[m_ihsp].ip= hip;
+ m_in_handler[m_ihsp].index= hindex;
+ m_ihsp++;
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
}
@@ -396,11 +430,29 @@ sp_rcontext::exit_handler()
{
DBUG_ENTER("sp_rcontext::exit_handler");
DBUG_ASSERT(m_ihsp);
+ uint hindex= m_in_handler[m_ihsp-1].index;
+ m_raised_conditions[hindex].clear();
m_ihsp-= 1;
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
}
+MYSQL_ERROR*
+sp_rcontext::raised_condition() const
+{
+ if (m_ihsp > 0)
+ {
+ uint hindex= m_in_handler[m_ihsp - 1].index;
+ MYSQL_ERROR *raised= & m_raised_conditions[hindex];
+ return raised;
+ }
+
+ if (m_prev_runtime_ctx)
+ return m_prev_runtime_ctx->raised_condition();
+
+ return NULL;
+}
+
int
sp_rcontext::set_variable(THD *thd, uint var_idx, Item **value)
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 368a017da21..2af96cf64dd 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -34,12 +34,21 @@ class sp_instr_cpush;
typedef struct
{
+ /** Condition caught by this HANDLER. */
struct sp_cond_type *cond;
- uint handler; // Location of handler
+ /** Location (instruction pointer) of the handler code. */
+ uint handler;
+ /** Handler type (EXIT, CONTINUE). */
int type;
- uint foffset; // Frame offset for the handlers declare level
} sp_handler_t;
+typedef struct
+{
+ /** Instruction pointer of the active handler. */
+ uint ip;
+ /** Handler index of the active handler. */
+ uint index;
+} sp_active_handler_t;
/*
This class is a runtime context of a Stored Routine. It is used in an
@@ -75,6 +84,13 @@ class sp_rcontext : public Sql_alloc
*/
Query_arena *callers_arena;
+ /*
+ End a open result set before start executing a continue/exit
+ handler if one is found as otherwise the client will hang
+ due to a violation of the client/server protocol.
+ */
+ bool end_partial_result_set;
+
#ifndef DBUG_OFF
/*
The routine for which this runtime context is created. Used for checking
@@ -107,31 +123,41 @@ class sp_rcontext : public Sql_alloc
return m_return_value_set;
}
- void push_handler(struct sp_cond_type *cond, uint h, int type, uint f);
+ void push_handler(struct sp_cond_type *cond, uint h, int type);
void pop_handlers(uint count);
// Returns 1 if a handler was found, 0 otherwise.
bool
- find_handler(THD *thd, uint sql_errno,MYSQL_ERROR::enum_warning_level level);
+ find_handler(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
// If there is an error handler for this error, handle it and return TRUE.
bool
- handle_error(uint sql_errno,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
// Returns handler type and sets *ip to location if one was found
inline int
- found_handler(uint *ip, uint *fp)
+ found_handler(uint *ip, uint *index)
{
if (m_hfound < 0)
return SP_HANDLER_NONE;
*ip= m_handler[m_hfound].handler;
- *fp= m_handler[m_hfound].foffset;
+ *index= m_hfound;
return m_handler[m_hfound].type;
}
+ MYSQL_ERROR* raised_condition() const;
+
// Returns true if we found a handler in this context
inline bool
found_handler_here()
@@ -150,7 +176,12 @@ class sp_rcontext : public Sql_alloc
uint pop_hstack();
- void enter_handler(int hid);
+ /**
+ Enter a SQL exception handler.
+ @param hip the handler instruction pointer
+ @param index the handler index
+ */
+ void enter_handler(uint hip, uint index);
void exit_handler();
@@ -214,10 +245,18 @@ private:
bool in_sub_stmt;
sp_handler_t *m_handler; // Visible handlers
+
+ /**
+ SQL conditions caught by each handler.
+ This is an array indexed by handler index.
+ */
+ MYSQL_ERROR *m_raised_conditions;
+
uint m_hcount; // Stack pointer for m_handler
uint *m_hstack; // Return stack for continue handlers
uint m_hsp; // Stack pointer for m_hstack
- uint *m_in_handler; // Active handler, for recursion check
+ /** Active handler stack. */
+ sp_active_handler_t *m_in_handler;
uint m_ihsp; // Stack pointer for m_in_handler
int m_hfound; // Set by find_handler; -1 if not found
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index ab18a2d1d04..9ab13438926 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -702,7 +702,7 @@ my_bool acl_reload(THD *thd)
if (simple_open_n_lock_tables(thd, tables))
{
sql_print_error("Fatal error: Can't open and lock privilege tables: %s",
- thd->main_da.message());
+ thd->stmt_da->message());
goto end;
}
@@ -6036,9 +6036,12 @@ public:
virtual ~Silence_routine_definer_errors()
{}
- virtual bool handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
bool has_errors() { return is_grave; }
@@ -6047,18 +6050,23 @@ private:
};
bool
-Silence_routine_definer_errors::handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+Silence_routine_definer_errors::handle_condition(
+ THD *thd,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
{
+ *cond_hdl= NULL;
if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
{
switch (sql_errno)
{
case ER_NONEXISTING_PROC_GRANT:
/* Convert the error into a warning. */
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno, message);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ sql_errno, msg);
return TRUE;
default:
is_grave= TRUE;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index f55d3fc5006..e5005f42b0d 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -44,9 +44,12 @@ public:
virtual ~Prelock_error_handler() {}
- virtual bool handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
bool safely_trapped_errors();
@@ -57,11 +60,14 @@ private:
bool
-Prelock_error_handler::handle_error(uint sql_errno,
- const char * /* message */,
- MYSQL_ERROR::enum_warning_level /* level */,
- THD * /* thd */)
+Prelock_error_handler::handle_condition(THD *,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level,
+ const char*,
+ MYSQL_ERROR ** cond_hdl)
{
+ *cond_hdl= NULL;
if (sql_errno == ER_NO_SUCH_TABLE)
{
m_handled_errors++;
@@ -473,7 +479,7 @@ static TABLE_SHARE
@todo Rework alternative ways to deal with ER_NO_SUCH TABLE.
*/
- if (share || (thd->is_error() && thd->main_da.sql_errno() != ER_NO_SUCH_TABLE))
+ if (share || (thd->is_error() && thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE))
DBUG_RETURN(share);
@@ -520,7 +526,7 @@ static TABLE_SHARE
DBUG_RETURN(0);
}
/* Table existed in engine. Let's open it */
- mysql_reset_errors(thd, 1); // Clear warnings
+ thd->warning_info->clear_warning_info(thd->query_id);
thd->clear_error(); // Clear error message
DBUG_RETURN(get_table_share(thd, table_list, key, key_length,
db_flags, error));
@@ -1281,9 +1287,9 @@ void close_thread_tables(THD *thd)
*/
if (!(thd->state_flags & Open_tables_state::BACKUPS_AVAIL))
{
- thd->main_da.can_overwrite_status= TRUE;
+ thd->stmt_da->can_overwrite_status= TRUE;
ha_autocommit_or_rollback(thd, thd->is_error());
- thd->main_da.can_overwrite_status= FALSE;
+ thd->stmt_da->can_overwrite_status= FALSE;
/*
Reset transaction state, but only if we're not inside a
@@ -3946,7 +3952,7 @@ retry:
release_table_share(share, RELEASE_WAIT_FOR_DROP);
if (!thd->killed)
{
- mysql_reset_errors(thd, 1); // Clear warnings
+ thd->warning_info->clear_warning_info(thd->query_id);
thd->clear_error(); // Clear error message
goto retry;
}
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 3c4ee274e7b..9f427f39265 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -934,7 +934,7 @@ void query_cache_end_of_result(THD *thd)
DBUG_VOID_RETURN;
/* Ensure that only complete results are cached. */
- DBUG_ASSERT(thd->main_da.is_eof());
+ DBUG_ASSERT(thd->stmt_da->is_eof());
if (thd->killed)
{
@@ -1626,7 +1626,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
thd->limit_found_rows = query->found_rows();
thd->status_var.last_query_cost= 0.0;
- thd->main_da.disable_status();
+ thd->stmt_da->disable_status();
BLOCK_UNLOCK_RD(query_block);
MYSQL_QUERY_CACHE_HIT(thd->query, (ulong) thd->limit_found_rows);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index daef5a26742..11692c2fd9f 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -199,19 +199,6 @@ bool foreign_key_prefix(Key *a, Key *b)
** Thread specific functions
****************************************************************************/
-/** Push an error to the error stack and return TRUE for now. */
-
-bool
-Reprepare_observer::report_error(THD *thd)
-{
- my_error(ER_NEED_REPREPARE, MYF(ME_NO_WARNING_FOR_ERROR|ME_NO_SP_HANDLER));
-
- m_invalidated= TRUE;
-
- return TRUE;
-}
-
-
Open_tables_state::Open_tables_state(ulong version_arg)
:version(version_arg), state_flags(0U)
{
@@ -304,7 +291,7 @@ int thd_tx_isolation(const THD *thd)
extern "C"
void thd_inc_row_count(THD *thd)
{
- thd->row_count++;
+ thd->warning_info->inc_current_row_for_warning();
}
@@ -414,150 +401,19 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
@return TRUE if the condition is handled.
*/
-bool Drop_table_error_handler::handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
-{
+bool Drop_table_error_handler::handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
+{
+ *cond_hdl= NULL;
return ((sql_errno == EE_DELETE && my_errno == ENOENT) ||
sql_errno == ER_TRG_NO_DEFINER);
}
-/**
- Clear this diagnostics area.
-
- Normally called at the end of a statement.
-*/
-
-void
-Diagnostics_area::reset_diagnostics_area()
-{
-#ifdef DBUG_OFF
- can_overwrite_status= FALSE;
- /** Don't take chances in production */
- m_message[0]= '\0';
- m_sql_errno= 0;
- m_server_status= 0;
- m_affected_rows= 0;
- m_last_insert_id= 0;
- m_total_warn_count= 0;
-#endif
- is_sent= FALSE;
- /** Tiny reset in debug mode to see garbage right away */
- m_status= DA_EMPTY;
-}
-
-
-/**
- Set OK status -- ends commands that do not return a
- result set, e.g. INSERT/UPDATE/DELETE.
-*/
-
-void
-Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
- ulonglong last_insert_id_arg,
- const char *message_arg)
-{
- DBUG_ASSERT(! is_set());
-#ifdef DBUG_OFF
- /*
- In production, refuse to overwrite an error or a custom response
- with an OK packet.
- */
- if (is_error() || is_disabled())
- return;
-#endif
- /** Only allowed to report success if has not yet reported an error */
-
- m_server_status= thd->server_status;
- m_total_warn_count= thd->total_warn_count;
- m_affected_rows= affected_rows_arg;
- m_last_insert_id= last_insert_id_arg;
- if (message_arg)
- strmake(m_message, message_arg, sizeof(m_message) - 1);
- else
- m_message[0]= '\0';
- m_status= DA_OK;
-}
-
-
-/**
- Set EOF status.
-*/
-
-void
-Diagnostics_area::set_eof_status(THD *thd)
-{
- /** Only allowed to report eof if has not yet reported an error */
-
- DBUG_ASSERT(! is_set());
-#ifdef DBUG_OFF
- /*
- In production, refuse to overwrite an error or a custom response
- with an EOF packet.
- */
- if (is_error() || is_disabled())
- return;
-#endif
-
- m_server_status= thd->server_status;
- /*
- If inside a stored procedure, do not return the total
- number of warnings, since they are not available to the client
- anyway.
- */
- m_total_warn_count= thd->spcont ? 0 : thd->total_warn_count;
-
- m_status= DA_EOF;
-}
-
-/**
- Set ERROR status.
-*/
-
-void
-Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
- const char *message_arg)
-{
- /*
- Only allowed to report error if has not yet reported a success
- The only exception is when we flush the message to the client,
- an error can happen during the flush.
- */
- DBUG_ASSERT(! is_set() || can_overwrite_status);
-#ifdef DBUG_OFF
- /*
- In production, refuse to overwrite a custom response with an
- ERROR packet.
- */
- if (is_disabled())
- return;
-#endif
-
- m_sql_errno= sql_errno_arg;
- strmake(m_message, message_arg, sizeof(m_message) - 1);
-
- m_status= DA_ERROR;
-}
-
-
-/**
- Mark the diagnostics area as 'DISABLED'.
-
- This is used in rare cases when the COM_ command at hand sends a response
- in a custom format. One example is the query cache, another is
- COM_STMT_PREPARE.
-*/
-
-void
-Diagnostics_area::disable_status()
-{
- DBUG_ASSERT(! is_set());
- m_status= DA_DISABLED;
-}
-
-
THD::THD()
:Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
/* statement id */ 0),
@@ -573,6 +429,8 @@ THD::THD()
first_successful_insert_id_in_cur_stmt(0),
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
examined_row_count(0),
+ warning_info(&main_warning_info),
+ stmt_da(&main_da),
global_read_lock(0),
is_fatal_error(0),
transaction_rollback_request(0),
@@ -583,7 +441,8 @@ THD::THD()
bootstrap(0),
derived_tables_processing(FALSE),
spcont(NULL),
- m_parser_state(NULL)
+ m_parser_state(NULL),
+ main_warning_info(0)
{
ulong tmp;
@@ -607,7 +466,8 @@ THD::THD()
hash_clear(&handler_tables_hash);
tmp_table=0;
used_tables=0;
- cuted_fields= sent_row_count= row_count= 0L;
+ cuted_fields= 0L;
+ sent_row_count= 0L;
limit_found_rows= 0;
row_count_func= -1;
statement_id_counter= 0UL;
@@ -627,7 +487,6 @@ THD::THD()
file_id = 0;
query_id= 0;
query_name_consts= 0;
- warn_id= 0;
db_charset= global_system_variables.collation_database;
bzero(ha_data, sizeof(ha_data));
mysys_var=0;
@@ -663,8 +522,6 @@ THD::THD()
*scramble= '\0';
init();
- /* Initialize sub structures */
- init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
profiling.set_thd(this);
#endif
@@ -712,19 +569,27 @@ void THD::push_internal_handler(Internal_error_handler *handler)
}
}
-
-bool THD::handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level)
+bool THD::handle_condition(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
{
if (!m_internal_handler)
+ {
+ *cond_hdl= NULL;
return FALSE;
+ }
for (Internal_error_handler *error_handler= m_internal_handler;
error_handler;
error_handler= m_internal_handler->m_prev_internal_handler)
{
- if (error_handler->handle_error(sql_errno, message, level, this))
- return TRUE;
+ if (error_handler-> handle_condition(this, sql_errno, sqlstate, level, msg,
+ cond_hdl))
+ {
+ return TRUE;
+ }
}
return FALSE;
@@ -737,6 +602,207 @@ void THD::pop_internal_handler()
m_internal_handler= m_internal_handler->m_prev_internal_handler;
}
+
+void THD::raise_error(uint sql_errno)
+{
+ const char* msg= ER(sql_errno);
+ (void) raise_condition(sql_errno,
+ NULL,
+ MYSQL_ERROR::WARN_LEVEL_ERROR,
+ msg);
+}
+
+void THD::raise_error_printf(uint sql_errno, ...)
+{
+ va_list args;
+ char ebuff[MYSQL_ERRMSG_SIZE];
+ DBUG_ENTER("THD::raise_error_printf");
+ DBUG_PRINT("my", ("nr: %d errno: %d", sql_errno, errno));
+ const char* format= ER(sql_errno);
+ va_start(args, sql_errno);
+ my_vsnprintf(ebuff, sizeof(ebuff), format, args);
+ va_end(args);
+ (void) raise_condition(sql_errno,
+ NULL,
+ MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ebuff);
+ DBUG_VOID_RETURN;
+}
+
+void THD::raise_warning(uint sql_errno)
+{
+ const char* msg= ER(sql_errno);
+ (void) raise_condition(sql_errno,
+ NULL,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ msg);
+}
+
+void THD::raise_warning_printf(uint sql_errno, ...)
+{
+ va_list args;
+ char ebuff[MYSQL_ERRMSG_SIZE];
+ DBUG_ENTER("THD::raise_warning_printf");
+ DBUG_PRINT("enter", ("warning: %u", sql_errno));
+ const char* format= ER(sql_errno);
+ va_start(args, sql_errno);
+ my_vsnprintf(ebuff, sizeof(ebuff), format, args);
+ va_end(args);
+ (void) raise_condition(sql_errno,
+ NULL,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ebuff);
+ DBUG_VOID_RETURN;
+}
+
+void THD::raise_note(uint sql_errno)
+{
+ DBUG_ENTER("THD::raise_note");
+ DBUG_PRINT("enter", ("code: %d", sql_errno));
+ if (!(this->options & OPTION_SQL_NOTES))
+ DBUG_VOID_RETURN;
+ const char* msg= ER(sql_errno);
+ (void) raise_condition(sql_errno,
+ NULL,
+ MYSQL_ERROR::WARN_LEVEL_NOTE,
+ msg);
+ DBUG_VOID_RETURN;
+}
+
+void THD::raise_note_printf(uint sql_errno, ...)
+{
+ va_list args;
+ char ebuff[MYSQL_ERRMSG_SIZE];
+ DBUG_ENTER("THD::raise_note_printf");
+ DBUG_PRINT("enter",("code: %u", sql_errno));
+ if (!(this->options & OPTION_SQL_NOTES))
+ DBUG_VOID_RETURN;
+ const char* format= ER(sql_errno);
+ va_start(args, sql_errno);
+ my_vsnprintf(ebuff, sizeof(ebuff), format, args);
+ va_end(args);
+ (void) raise_condition(sql_errno,
+ NULL,
+ MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ebuff);
+ DBUG_VOID_RETURN;
+}
+
+MYSQL_ERROR* THD::raise_condition(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg)
+{
+ MYSQL_ERROR *cond= NULL;
+ DBUG_ENTER("THD::raise_condition");
+
+ if (!(this->options & OPTION_SQL_NOTES) &&
+ (level == MYSQL_ERROR::WARN_LEVEL_NOTE))
+ DBUG_RETURN(NULL);
+
+ warning_info->opt_clear_warning_info(query_id);
+
+ /*
+ TODO: replace by DBUG_ASSERT(sql_errno != 0) once all bugs similar to
+ Bug#36768 are fixed: a SQL condition must have a real (!=0) error number
+ so that it can be caught by handlers.
+ */
+ if (sql_errno == 0)
+ sql_errno= ER_UNKNOWN_ERROR;
+ if (msg == NULL)
+ msg= ER(sql_errno);
+ if (sqlstate == NULL)
+ sqlstate= mysql_errno_to_sqlstate(sql_errno);
+
+ if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
+ really_abort_on_warning())
+ {
+ /*
+ FIXME:
+ push_warning and strict SQL_MODE case.
+ */
+ level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+ killed= THD::KILL_BAD_DATA;
+ }
+
+ switch (level)
+ {
+ case MYSQL_ERROR::WARN_LEVEL_NOTE:
+ case MYSQL_ERROR::WARN_LEVEL_WARN:
+ got_warning= 1;
+ break;
+ case MYSQL_ERROR::WARN_LEVEL_ERROR:
+ break;
+ default:
+ DBUG_ASSERT(FALSE);
+ }
+
+ if (handle_condition(sql_errno, sqlstate, level, msg, &cond))
+ DBUG_RETURN(cond);
+
+ if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
+ {
+ is_slave_error= 1; // needed to catch query errors during replication
+
+ /*
+ thd->lex->current_select == 0 if lex structure is not inited
+ (not query command (COM_QUERY))
+ */
+ if (lex->current_select &&
+ lex->current_select->no_error && !is_fatal_error)
+ {
+ DBUG_PRINT("error",
+ ("Error converted to warning: current_select: no_error %d "
+ "fatal_error: %d",
+ (lex->current_select ?
+ lex->current_select->no_error : 0),
+ (int) is_fatal_error));
+ }
+ else
+ {
+ if (! stmt_da->is_error())
+ stmt_da->set_error_status(this, sql_errno, msg, sqlstate);
+ }
+ }
+
+ /*
+ If a continue handler is found, the error message will be cleared
+ by the stored procedures code.
+ */
+ if (!is_fatal_error && spcont &&
+ spcont->handle_condition(this, sql_errno, sqlstate, level, msg, &cond))
+ {
+ /*
+ Do not push any warnings, a handled error must be completely
+ silenced.
+ */
+ DBUG_RETURN(cond);
+ }
+
+ /* Un-handled conditions */
+
+ cond= raise_condition_no_handler(sql_errno, sqlstate, level, msg);
+ DBUG_RETURN(cond);
+}
+
+MYSQL_ERROR*
+THD::raise_condition_no_handler(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg)
+{
+ MYSQL_ERROR *cond= NULL;
+ DBUG_ENTER("THD::raise_condition_no_handler");
+
+ query_cache_abort(& net);
+
+ /* FIXME: broken special case */
+ if (no_warnings_for_error && (level == MYSQL_ERROR::WARN_LEVEL_ERROR))
+ DBUG_RETURN(NULL);
+
+ cond= warning_info->push_warning(this, sql_errno, sqlstate, level, msg);
+ DBUG_RETURN(cond);
+}
extern "C"
void *thd_alloc(MYSQL_THD thd, unsigned int size)
{
@@ -825,9 +891,6 @@ void THD::init(void)
TL_WRITE_LOW_PRIORITY :
TL_WRITE);
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
- warn_list.empty();
- bzero((char*) warn_count, sizeof(warn_count));
- total_warn_count= 0;
update_charset();
reset_current_stmt_binlog_row_based();
bzero((char *) &status_var, sizeof(status_var));
@@ -965,7 +1028,6 @@ THD::~THD()
DBUG_PRINT("info", ("freeing security context"));
main_security_ctx.destroy();
safeFree(db);
- free_root(&warn_root,MYF(0));
#ifdef USING_TRANSACTIONS
free_root(&transaction.mem_root,MYF(0));
#endif
@@ -1540,13 +1602,17 @@ bool select_result::check_simple_select() const
static String default_line_term("\n",default_charset_info);
static String default_escaped("\\",default_charset_info);
static String default_field_term("\t",default_charset_info);
+static String default_xml_row_term("<row>", default_charset_info);
-sql_exchange::sql_exchange(char *name,bool flag)
+sql_exchange::sql_exchange(char *name, bool flag,
+ enum enum_filetype filetype_arg)
:file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
{
+ filetype= filetype_arg;
field_term= &default_field_term;
enclosed= line_start= &my_empty_string;
- line_term= &default_line_term;
+ line_term= filetype == FILETYPE_CSV ?
+ &default_line_term : &default_xml_row_term;
escaped= &default_escaped;
cs= NULL;
}
@@ -1568,21 +1634,19 @@ bool select_send::send_fields(List<Item> &list, uint flags)
void select_send::abort()
{
DBUG_ENTER("select_send::abort");
- if (is_result_set_started && thd->spcont &&
- thd->spcont->find_handler(thd, thd->main_da.sql_errno(),
- MYSQL_ERROR::WARN_LEVEL_ERROR))
+
+ if (is_result_set_started && thd->spcont)
{
/*
We're executing a stored procedure, have an open result
- set, an SQL exception condition and a handler for it.
- In this situation we must abort the current statement,
- silence the error and start executing the continue/exit
- handler.
+ set and an SQL exception condition. In this situation we
+ must abort the current statement, silence the error and
+ start executing the continue/exit handler if one is found.
Before aborting the statement, let's end the open result set, as
otherwise the client will hang due to the violation of the
client/server protocol.
*/
- thd->protocol->end_partial_result_set(thd);
+ thd->spcont->end_partial_result_set= TRUE;
}
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 8a47c171cc6..5dcf3fdaad0 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
+/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@
class Reprepare_observer
{
public:
+ Reprepare_observer() {}
/**
Check if a change of metadata is OK. In future
the signature of this method may be extended to accept the old
@@ -88,6 +89,7 @@ enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT,
SLAVE_EXEC_MODE_LAST_BIT};
enum enum_mark_columns
{ MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE};
+enum enum_filetype { FILETYPE_CSV, FILETYPE_XML };
extern char internal_table_name[2];
extern char empty_c_string[1];
@@ -265,6 +267,41 @@ public:
LEX_COLUMN (const String& x,const uint& y ): column (x),rights (y) {}
};
+/* SIGNAL / RESIGNAL / GET DIAGNOSTICS */
+
+/**
+ This enumeration list all the condition item names of a condition in the
+ SQL condition area.
+*/
+typedef enum enum_diag_condition_item_name
+{
+ /*
+ Conditions that can be set by the user (SIGNAL/RESIGNAL),
+ and by the server implementation.
+ */
+
+ DIAG_CLASS_ORIGIN= 0,
+ FIRST_DIAG_SET_PROPERTY= DIAG_CLASS_ORIGIN,
+ DIAG_SUBCLASS_ORIGIN= 1,
+ DIAG_CONSTRAINT_CATALOG= 2,
+ DIAG_CONSTRAINT_SCHEMA= 3,
+ DIAG_CONSTRAINT_NAME= 4,
+ DIAG_CATALOG_NAME= 5,
+ DIAG_SCHEMA_NAME= 6,
+ DIAG_TABLE_NAME= 7,
+ DIAG_COLUMN_NAME= 8,
+ DIAG_CURSOR_NAME= 9,
+ DIAG_MESSAGE_TEXT= 10,
+ DIAG_MYSQL_ERRNO= 11,
+ LAST_DIAG_SET_PROPERTY= DIAG_MYSQL_ERRNO
+} Diag_condition_item_name;
+
+/**
+ Name of each diagnostic condition item.
+ This array is indexed by Diag_condition_item_name.
+*/
+extern const LEX_STRING Diag_condition_item_names[];
+
#include "sql_lex.h" /* Must be here */
class Delayed_insert;
@@ -1038,12 +1075,12 @@ protected:
public:
/**
- Handle an error condition.
+ Handle a sql condition.
This method can be implemented by a subclass to achieve any of the
following:
- - mask an error internally, prevent exposing it to the user,
- - mask an error and throw another one instead.
- When this method returns true, the error condition is considered
+ - mask a warning/error internally, prevent exposing it to the user,
+ - mask a warning/error and throw another one instead.
+ When this method returns true, the sql condition is considered
'handled', and will not be propagated to upper layers.
It is the responsability of the code installing an internal handler
to then check for trapped conditions, and implement logic to recover
@@ -1057,15 +1094,17 @@ public:
before removing it from the exception stack with
<code>THD::pop_internal_handler()</code>.
- @param sql_errno the error number
- @param level the error level
@param thd the calling thread
- @return true if the error is handled
+ @param cond the condition raised.
+ @return true if the condition is handled
*/
- virtual bool handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd) = 0;
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl) = 0;
+
private:
Internal_error_handler *m_prev_internal_handler;
friend class THD;
@@ -1080,10 +1119,12 @@ private:
class Dummy_error_handler : public Internal_error_handler
{
public:
- bool handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+ bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl)
{
/* Ignore error */
return TRUE;
@@ -1092,7 +1133,7 @@ public:
/**
- This class is an internal error handler implementation for
+ This class is an internal error handler implementation for
DROP TABLE statements. The thing is that there may be warnings during
execution of these statements, which should not be exposed to the user.
This class is intended to silence such warnings.
@@ -1106,10 +1147,12 @@ public:
{ }
public:
- bool handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
private:
Internal_error_handler *m_err_handler;
@@ -1117,123 +1160,6 @@ private:
/**
- Stores status of the currently executed statement.
- Cleared at the beginning of the statement, and then
- can hold either OK, ERROR, or EOF status.
- Can not be assigned twice per statement.
-*/
-
-class Diagnostics_area
-{
-public:
- enum enum_diagnostics_status
- {
- /** The area is cleared at start of a statement. */
- DA_EMPTY= 0,
- /** Set whenever one calls my_ok(). */
- DA_OK,
- /** Set whenever one calls my_eof(). */
- DA_EOF,
- /** Set whenever one calls my_error() or my_message(). */
- DA_ERROR,
- /** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
- DA_DISABLED
- };
- /** True if status information is sent to the client. */
- bool is_sent;
- /** Set to make set_error_status after set_{ok,eof}_status possible. */
- bool can_overwrite_status;
-
- void set_ok_status(THD *thd, ha_rows affected_rows_arg,
- ulonglong last_insert_id_arg,
- const char *message);
- void set_eof_status(THD *thd);
- void set_error_status(THD *thd, uint sql_errno_arg, const char *message_arg);
-
- void disable_status();
-
- void reset_diagnostics_area();
-
- bool is_set() const { return m_status != DA_EMPTY; }
- bool is_error() const { return m_status == DA_ERROR; }
- bool is_eof() const { return m_status == DA_EOF; }
- bool is_ok() const { return m_status == DA_OK; }
- bool is_disabled() const { return m_status == DA_DISABLED; }
- enum_diagnostics_status status() const { return m_status; }
-
- const char *message() const
- { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }
-
- uint sql_errno() const
- { DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
-
- uint server_status() const
- {
- DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
- return m_server_status;
- }
-
- ha_rows affected_rows() const
- { DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
-
- ulonglong last_insert_id() const
- { DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
-
- uint total_warn_count() const
- {
- DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
- return m_total_warn_count;
- }
-
- Diagnostics_area() { reset_diagnostics_area(); }
-
-private:
- /** Message buffer. Can be used by OK or ERROR status. */
- char m_message[MYSQL_ERRMSG_SIZE];
- /**
- SQL error number. One of ER_ codes from share/errmsg.txt.
- Set by set_error_status.
- */
- uint m_sql_errno;
-
- /**
- Copied from thd->server_status when the diagnostics area is assigned.
- We need this member as some places in the code use the following pattern:
- thd->server_status|= ...
- my_eof(thd);
- thd->server_status&= ~...
- Assigned by OK, EOF or ERROR.
- */
- uint m_server_status;
- /**
- The number of rows affected by the last statement. This is
- semantically close to thd->row_count_func, but has a different
- life cycle. thd->row_count_func stores the value returned by
- function ROW_COUNT() and is cleared only by statements that
- update its value, such as INSERT, UPDATE, DELETE and few others.
- This member is cleared at the beginning of the next statement.
-
- We could possibly merge the two, but life cycle of thd->row_count_func
- can not be changed.
- */
- ha_rows m_affected_rows;
- /**
- Similarly to the previous member, this is a replacement of
- thd->first_successful_insert_id_in_prev_stmt, which is used
- to implement LAST_INSERT_ID().
- */
- ulonglong m_last_insert_id;
- /** The total number of warnings. */
- uint m_total_warn_count;
- enum_diagnostics_status m_status;
- /**
- @todo: the following THD members belong here:
- - warn_list, warn_count,
- */
-};
-
-
-/**
Storage engine specific thread local data.
*/
@@ -1259,6 +1185,7 @@ struct Ha_data
Ha_data() :ha_ptr(NULL) {}
};
+extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
/**
@class THD
@@ -1301,7 +1228,6 @@ public:
struct st_mysql_stmt *current_stmt;
#endif
NET net; // client connection descriptor
- MEM_ROOT warn_root; // For warnings and errors
Protocol *protocol; // Current protocol
Protocol_text protocol_text; // Normal protocol
Protocol_binary protocol_binary; // Binary protocol
@@ -1717,16 +1643,8 @@ public:
table_map used_tables;
USER_CONN *user_connect;
CHARSET_INFO *db_charset;
- /*
- FIXME: this, and some other variables like 'count_cuted_fields'
- maybe should be statement/cursor local, that is, moved to Statement
- class. With current implementation warnings produced in each prepared
- statement/cursor settle here.
- */
- List <MYSQL_ERROR> warn_list;
- uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
- uint total_warn_count;
- Diagnostics_area main_da;
+ Warning_info *warning_info;
+ Diagnostics_area *stmt_da;
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
PROFILING profiling;
#endif
@@ -1739,7 +1657,7 @@ public:
from table are necessary for this select, to check if it's necessary to
update auto-updatable fields (like auto_increment and timestamp).
*/
- query_id_t query_id, warn_id;
+ query_id_t query_id;
ulong col_access;
#ifdef ERROR_INJECT_SUPPORT
@@ -1748,11 +1666,6 @@ public:
/* Statement id is thread-wide. This counter is used to generate ids */
ulong statement_id_counter;
ulong rand_saved_seed1, rand_saved_seed2;
- /*
- Row counter, mainly for errors and warnings. Not increased in
- create_sort_index(); may differ from examined_row_count.
- */
- ulong row_count;
pthread_t real_id; /* For debugging */
my_thread_id thread_id;
uint tmp_table, global_read_lock;
@@ -2056,8 +1969,8 @@ public:
inline void clear_error()
{
DBUG_ENTER("clear_error");
- if (main_da.is_error())
- main_da.reset_diagnostics_area();
+ if (stmt_da->is_error())
+ stmt_da->reset_diagnostics_area();
is_slave_error= 0;
DBUG_VOID_RETURN;
}
@@ -2089,7 +2002,7 @@ public:
To raise this flag, use my_error().
*/
- inline bool is_error() const { return main_da.is_error(); }
+ inline bool is_error() const { return stmt_da->is_error(); }
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
@@ -2285,19 +2198,107 @@ public:
void push_internal_handler(Internal_error_handler *handler);
/**
- Handle an error condition.
- @param sql_errno the error number
- @param level the error level
- @return true if the error is handled
- */
- virtual bool handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level);
+ Handle a sql condition.
+ @param sql_errno the condition error number
+ @param sqlstate the condition sqlstate
+ @param level the condition level
+ @param msg the condition message text
+ @param[out] cond_hdl the sql condition raised, if any
+ @return true if the condition is handled
+ */
+ virtual bool handle_condition(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
/**
Remove the error handler last pushed.
*/
void pop_internal_handler();
+ /**
+ Raise an exception condition.
+ @param code the MYSQL_ERRNO error code of the error
+ */
+ void raise_error(uint code);
+
+ /**
+ Raise an exception condition, with a formatted message.
+ @param code the MYSQL_ERRNO error code of the error
+ */
+ void raise_error_printf(uint code, ...);
+
+ /**
+ Raise a completion condition (warning).
+ @param code the MYSQL_ERRNO error code of the warning
+ */
+ void raise_warning(uint code);
+
+ /**
+ Raise a completion condition (warning), with a formatted message.
+ @param code the MYSQL_ERRNO error code of the warning
+ */
+ void raise_warning_printf(uint code, ...);
+
+ /**
+ Raise a completion condition (note), with a fixed message.
+ @param code the MYSQL_ERRNO error code of the note
+ */
+ void raise_note(uint code);
+
+ /**
+ Raise an completion condition (note), with a formatted message.
+ @param code the MYSQL_ERRNO error code of the note
+ */
+ void raise_note_printf(uint code, ...);
+
+private:
+ /*
+ Only the implementation of the SIGNAL and RESIGNAL statements
+ is permitted to raise SQL conditions in a generic way,
+ or to raise them by bypassing handlers (RESIGNAL).
+ To raise a SQL condition, the code should use the public
+ raise_error() or raise_warning() methods provided by class THD.
+ */
+ friend class Signal_common;
+ friend class Signal_statement;
+ friend class Resignal_statement;
+ friend void push_warning(THD*, MYSQL_ERROR::enum_warning_level, uint, const char*);
+ friend void my_message_sql(uint, const char *, myf);
+
+ /**
+ Raise a generic SQL condition.
+ @param sql_errno the condition error number
+ @param sqlstate the condition SQLSTATE
+ @param level the condition level
+ @param msg the condition message text
+ @return The condition raised, or NULL
+ */
+ MYSQL_ERROR*
+ raise_condition(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg);
+
+ /**
+ Raise a generic SQL condition, without activation any SQL condition
+ handlers.
+ This method is necessary to support the RESIGNAL statement,
+ which is allowed to bypass SQL exception handlers.
+ @param sql_errno the condition error number
+ @param sqlstate the condition SQLSTATE
+ @param level the condition level
+ @param msg the condition message text
+ @return The condition raised, or NULL
+ */
+ MYSQL_ERROR*
+ raise_condition_no_handler(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg);
+
+public:
/** Overloaded to guard query/query_length fields */
virtual void set_statement(Statement *stmt);
@@ -2325,25 +2326,27 @@ private:
tree itself is reused between executions and thus is stored elsewhere.
*/
MEM_ROOT main_mem_root;
+ Warning_info main_warning_info;
+ Diagnostics_area main_da;
};
-/** A short cut for thd->main_da.set_ok_status(). */
+/** A short cut for thd->stmt_da->set_ok_status(). */
inline void
-my_ok(THD *thd, ha_rows affected_rows= 0, ulonglong id= 0,
+my_ok(THD *thd, ulonglong affected_rows= 0, ulonglong id= 0,
const char *message= NULL)
{
- thd->main_da.set_ok_status(thd, affected_rows, id, message);
+ thd->stmt_da->set_ok_status(thd, affected_rows, id, message);
}
-/** A short cut for thd->main_da.set_eof_status(). */
+/** A short cut for thd->stmt_da->set_eof_status(). */
inline void
my_eof(THD *thd)
{
- thd->main_da.set_eof_status(thd);
+ thd->stmt_da->set_eof_status(thd);
}
#define tmp_disable_binlog(A) \
@@ -2362,13 +2365,15 @@ my_eof(THD *thd)
class sql_exchange :public Sql_alloc
{
public:
+ enum enum_filetype filetype; /* load XML, Added by Arnold & Erik */
char *file_name;
String *field_term,*enclosed,*line_term,*line_start,*escaped;
bool opt_enclosed;
bool dumpfile;
ulong skip_lines;
CHARSET_INFO *cs;
- sql_exchange(char *name,bool dumpfile_flag);
+ sql_exchange(char *name, bool dumpfile_flag,
+ enum_filetype filetype_arg= FILETYPE_CSV);
bool escaped_given(void);
};
@@ -3011,11 +3016,11 @@ public:
/* Bits in sql_command_flags */
-#define CF_CHANGES_DATA 1
-#define CF_HAS_ROW_COUNT 2
-#define CF_STATUS_COMMAND 4
-#define CF_SHOW_TABLE_COMMAND 8
-#define CF_WRITE_LOGS_COMMAND 16
+#define CF_CHANGES_DATA (1U << 0)
+#define CF_HAS_ROW_COUNT (1U << 1)
+#define CF_STATUS_COMMAND (1U << 2)
+#define CF_SHOW_TABLE_COMMAND (1U << 3)
+#define CF_WRITE_LOGS_COMMAND (1U << 4)
/**
Must be set for SQL statements that may contain
Item expressions and/or use joins and tables.
@@ -3029,7 +3034,17 @@ public:
reprepare. Consequently, complex item expressions and
joins are currently prohibited in these statements.
*/
-#define CF_REEXECUTION_FRAGILE 32
+#define CF_REEXECUTION_FRAGILE (1U << 5)
+
+/**
+ Diagnostic statement.
+ Diagnostic statements:
+ - SHOW WARNING
+ - SHOW ERROR
+ - GET DIAGNOSTICS (WL#2111)
+ do not modify the diagnostics area during execution.
+*/
+#define CF_DIAGNOSTIC_STMT (1U << 8)
/* Functions in sql_class.cc */
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 3952567c329..4ae267a880c 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -39,10 +39,6 @@
#define MIN_HANDSHAKE_SIZE 6
#endif /* HAVE_OPENSSL */
-#ifdef __WIN__
-extern void win_install_sigabrt_handler();
-#endif
-
/*
Get structure for logging connection data for the current user
*/
@@ -612,13 +608,8 @@ void thd_init_client_charset(THD *thd, uint cs_number)
bool init_new_connection_handler_thread()
{
pthread_detach_this_thread();
-#if defined(__WIN__)
- win_install_sigabrt_handler();
-#else
- /* Win32 calls this in pthread_create */
if (my_thread_init())
return 1;
-#endif /* __WIN__ */
return 0;
}
@@ -958,7 +949,7 @@ static bool login_connection(THD *thd)
if (error)
{ // Wrong permissions
-#ifdef __NT__
+#ifdef _WIN32
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
my_sleep(1000); /* must wait after eof() */
#endif
@@ -1001,7 +992,7 @@ static void end_connection(THD *thd)
thd->thread_id,(thd->db ? thd->db : "unconnected"),
sctx->user ? sctx->user : "unauthenticated",
sctx->host_or_ip,
- (thd->main_da.is_error() ? thd->main_da.message() :
+ (thd->stmt_da->is_error() ? thd->stmt_da->message() :
ER(ER_UNKNOWN_ERROR)));
}
}
@@ -1046,7 +1037,7 @@ static void prepare_new_connection_state(THD* thd)
thd->thread_id,(thd->db ? thd->db : "unconnected"),
sctx->user ? sctx->user : "unauthenticated",
sctx->host_or_ip, "init_connect command failed");
- sql_print_warning("%s", thd->main_da.message());
+ sql_print_warning("%s", thd->stmt_da->message());
}
thd->proc_info=0;
thd->set_time();
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index d2f90fa9288..ee272dad341 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1075,6 +1075,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
{
handlerton *table_type= table->s->db_type();
TABLE_SHARE *share= table->s;
+ /* Note that a temporary table cannot be partitioned */
if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
goto trunc_by_del;
@@ -1113,8 +1114,22 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
table_list->db, table_list->table_name);
DBUG_RETURN(TRUE);
}
- if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd, table_type),
- HTON_CAN_RECREATE))
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ /*
+ TODO: Add support for TRUNCATE PARTITION for NDB and other engines
+ supporting native partitioning
+ */
+ if (table_type != DB_TYPE_PARTITION_DB &&
+ thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION)
+ {
+ my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+#endif
+ if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd,
+ table_type),
+ HTON_CAN_RECREATE) ||
+ thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION)
goto trunc_by_del;
if (lock_and_wait_for_table_name(thd, table_list))
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 37adf5c403a..9b747759ece 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -178,9 +178,9 @@ exit:
if (orig_table_list->view)
{
if (thd->is_error() &&
- (thd->main_da.sql_errno() == ER_BAD_FIELD_ERROR ||
- thd->main_da.sql_errno() == ER_FUNC_INEXISTENT_NAME_COLLISION ||
- thd->main_da.sql_errno() == ER_SP_DOES_NOT_EXIST))
+ (thd->stmt_da->sql_errno() == ER_BAD_FIELD_ERROR ||
+ thd->stmt_da->sql_errno() == ER_FUNC_INEXISTENT_NAME_COLLISION ||
+ thd->stmt_da->sql_errno() == ER_SP_DOES_NOT_EXIST))
{
thd->clear_error();
my_error(ER_VIEW_INVALID, MYF(0), orig_table_list->db,
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 9ea7facbe41..2837e45fb47 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 1995-2002 MySQL AB
+/* Copyright (C) 1995-2002 MySQL AB,
+ Copyright (C) 2008-2009 Sun Microsystems, Inc
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -42,133 +43,577 @@ This file contains the implementation of error and warnings related
***********************************************************************/
#include "mysql_priv.h"
+#include "sql_error.h"
#include "sp_rcontext.h"
/*
- Store a new message in an error object
-
- This is used to in group_concat() to register how many warnings we actually
- got after the query has been executed.
+ Design notes about MYSQL_ERROR::m_message_text.
+
+ The member MYSQL_ERROR::m_message_text contains the text associated with
+ an error, warning or note (which are all SQL 'conditions')
+
+ Producer of MYSQL_ERROR::m_message_text:
+ ----------------------------------------
+
+ (#1) the server implementation itself, when invoking functions like
+ my_error() or push_warning()
+
+ (#2) user code in stored programs, when using the SIGNAL statement.
+
+ (#3) user code in stored programs, when using the RESIGNAL statement.
+
+ When invoking my_error(), the error number and message is typically
+ provided like this:
+ - my_error(ER_WRONG_DB_NAME, MYF(0), ...);
+ - my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
+
+ In both cases, the message is retrieved from ER(ER_XXX), which in turn
+ is read from the resource file errmsg.sys at server startup.
+ The strings stored in the errmsg.sys file are expressed in the character set
+ that corresponds to the server --language start option
+ (see error_message_charset_info).
+
+ When executing:
+ - a SIGNAL statement,
+ - a RESIGNAL statement,
+ the message text is provided by the user logic, and is expressed in UTF8.
+
+ Storage of MYSQL_ERROR::m_message_text:
+ ---------------------------------------
+
+ (#4) The class MYSQL_ERROR is used to hold the message text member.
+ This class represents a single SQL condition.
+
+ (#5) The class Warning_info represents a SQL condition area, and contains
+ a collection of SQL conditions in the Warning_info::m_warn_list
+
+ Consumer of MYSQL_ERROR::m_message_text:
+ ----------------------------------------
+
+ (#6) The statements SHOW WARNINGS and SHOW ERRORS display the content of
+ the warning list.
+
+ (#7) The GET DIAGNOSTICS statement (planned, not implemented yet) will
+ also read the content of:
+ - the top level statement condition area (when executed in a query),
+ - a sub statement (when executed in a stored program)
+ and return the data stored in a MYSQL_ERROR.
+
+ (#8) The RESIGNAL statement reads the MYSQL_ERROR caught by an exception
+ handler, to raise a new or modified condition (in #3).
+
+ The big picture
+ ---------------
+ --------------
+ | ^
+ V |
+ my_error(#1) SIGNAL(#2) RESIGNAL(#3) |
+ |(#A) |(#B) |(#C) |
+ | | | |
+ ----------------------------|---------------------------- |
+ | |
+ V |
+ MYSQL_ERROR(#4) |
+ | |
+ | |
+ V |
+ Warning_info(#5) |
+ | |
+ ----------------------------------------------------- |
+ | | | |
+ | | | |
+ | | | |
+ V V V |
+ SHOW WARNINGS(#6) GET DIAGNOSTICS(#7) RESIGNAL(#8) |
+ | | | | |
+ | -------- | V |
+ | | | --------------
+ V | |
+ Connectors | |
+ | | |
+ -------------------------
+ |
+ V
+ Client application
+
+ Current implementation status
+ -----------------------------
+
+ (#1) (my_error) produces data in the 'error_message_charset_info' CHARSET
+
+ (#2) and (#3) (SIGNAL, RESIGNAL) produces data internally in UTF8
+
+ (#6) (SHOW WARNINGS) produces data in the 'error_message_charset_info' CHARSET
+
+ (#7) (GET DIAGNOSTICS) is not implemented.
+
+ (#8) (RESIGNAL) produces data internally in UTF8 (see #3)
+
+ As a result, the design choice for (#4) and (#5) is to store data in
+ the 'error_message_charset_info' CHARSET, to minimize impact on the code base.
+ This is implemented by using 'String MYSQL_ERROR::m_message_text'.
+
+ The UTF8 -> error_message_charset_info conversion is implemented in
+ Signal_common::eval_signal_informations() (for path #B and #C).
+
+ Future work
+ -----------
+
+ - Change (#1) (my_error) to generate errors in UTF8.
+ See WL#751 (Recoding of error messages)
+
+ - Change (#4 and #5) to store message text in UTF8 natively.
+ In practice, this means changing the type of the message text to
+ '<UTF8 String 128 class> MYSQL_ERROR::m_message_text', and is a direct
+ consequence of WL#751.
+
+ - Implement (#9) (GET DIAGNOSTICS).
+ See WL#2111 (Stored Procedures: Implement GET DIAGNOSTICS)
*/
-void MYSQL_ERROR::set_msg(THD *thd, const char *msg_arg)
+MYSQL_ERROR::MYSQL_ERROR()
+ : Sql_alloc(),
+ m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_catalog((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_schema((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_catalog_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_schema_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_table_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_message_text(),
+ m_sql_errno(0),
+ m_level(MYSQL_ERROR::WARN_LEVEL_ERROR),
+ m_mem_root(NULL)
{
- msg= strdup_root(&thd->warn_root, msg_arg);
+ memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
}
+void MYSQL_ERROR::init(MEM_ROOT *mem_root)
+{
+ DBUG_ASSERT(mem_root != NULL);
+ DBUG_ASSERT(m_mem_root == NULL);
+ m_mem_root= mem_root;
+}
-/*
- Reset all warnings for the thread
-
- SYNOPSIS
- mysql_reset_errors()
- thd Thread handle
- force Reset warnings even if it has been done before
+void MYSQL_ERROR::clear()
+{
+ m_class_origin.length(0);
+ m_subclass_origin.length(0);
+ m_constraint_catalog.length(0);
+ m_constraint_schema.length(0);
+ m_constraint_name.length(0);
+ m_catalog_name.length(0);
+ m_schema_name.length(0);
+ m_table_name.length(0);
+ m_column_name.length(0);
+ m_cursor_name.length(0);
+ m_message_text.length(0);
+ m_sql_errno= 0;
+ m_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+}
- IMPLEMENTATION
- Don't reset warnings if this has already been called for this query.
- This may happen if one gets a warning during the parsing stage,
- in which case push_warnings() has already called this function.
-*/
+MYSQL_ERROR::MYSQL_ERROR(MEM_ROOT *mem_root)
+ : Sql_alloc(),
+ m_class_origin((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_subclass_origin((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_catalog((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_schema((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_constraint_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_catalog_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_schema_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_table_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_column_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_cursor_name((const char*) NULL, 0, & my_charset_utf8_bin),
+ m_message_text(),
+ m_sql_errno(0),
+ m_level(MYSQL_ERROR::WARN_LEVEL_ERROR),
+ m_mem_root(mem_root)
+{
+ DBUG_ASSERT(mem_root != NULL);
+ memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
+}
-void mysql_reset_errors(THD *thd, bool force)
+static void copy_string(MEM_ROOT *mem_root, String* dst, const String* src)
{
- DBUG_ENTER("mysql_reset_errors");
- if (thd->query_id != thd->warn_id || force)
+ size_t len= src->length();
+ if (len)
{
- thd->warn_id= thd->query_id;
- free_root(&thd->warn_root,MYF(0));
- bzero((char*) thd->warn_count, sizeof(thd->warn_count));
- if (force)
- thd->total_warn_count= 0;
- thd->warn_list.empty();
- thd->row_count= 1; // by default point to row 1
+ char* copy= (char*) alloc_root(mem_root, len + 1);
+ if (copy)
+ {
+ memcpy(copy, src->ptr(), len);
+ copy[len]= '\0';
+ dst->set(copy, len, src->charset());
+ }
}
+ else
+ dst->length(0);
+}
+
+void
+MYSQL_ERROR::copy_opt_attributes(const MYSQL_ERROR *cond)
+{
+ DBUG_ASSERT(this != cond);
+ copy_string(m_mem_root, & m_class_origin, & cond->m_class_origin);
+ copy_string(m_mem_root, & m_subclass_origin, & cond->m_subclass_origin);
+ copy_string(m_mem_root, & m_constraint_catalog, & cond->m_constraint_catalog);
+ copy_string(m_mem_root, & m_constraint_schema, & cond->m_constraint_schema);
+ copy_string(m_mem_root, & m_constraint_name, & cond->m_constraint_name);
+ copy_string(m_mem_root, & m_catalog_name, & cond->m_catalog_name);
+ copy_string(m_mem_root, & m_schema_name, & cond->m_schema_name);
+ copy_string(m_mem_root, & m_table_name, & cond->m_table_name);
+ copy_string(m_mem_root, & m_column_name, & cond->m_column_name);
+ copy_string(m_mem_root, & m_cursor_name, & cond->m_cursor_name);
+}
+
+void
+MYSQL_ERROR::set(uint sql_errno, const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level, const char* msg)
+{
+ DBUG_ASSERT(sql_errno != 0);
+ DBUG_ASSERT(sqlstate != NULL);
+ DBUG_ASSERT(msg != NULL);
+
+ m_sql_errno= sql_errno;
+ memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH);
+ m_returned_sqlstate[SQLSTATE_LENGTH]= '\0';
+
+ set_builtin_message_text(msg);
+ m_level= level;
+}
+
+void
+MYSQL_ERROR::set_builtin_message_text(const char* str)
+{
+ /*
+ See the comments
+ "Design notes about MYSQL_ERROR::m_message_text."
+ */
+ const char* copy;
+
+ copy= strdup_root(m_mem_root, str);
+ m_message_text.set(copy, strlen(copy), error_message_charset_info);
+ DBUG_ASSERT(! m_message_text.is_alloced());
+}
+
+const char*
+MYSQL_ERROR::get_message_text() const
+{
+ return m_message_text.ptr();
+}
+
+int
+MYSQL_ERROR::get_message_octet_length() const
+{
+ return m_message_text.length();
+}
+
+void
+MYSQL_ERROR::set_sqlstate(const char* sqlstate)
+{
+ memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH);
+ m_returned_sqlstate[SQLSTATE_LENGTH]= '\0';
+}
+
+/**
+ Clear this diagnostics area.
+
+ Normally called at the end of a statement.
+*/
+
+void
+Diagnostics_area::reset_diagnostics_area()
+{
+ DBUG_ENTER("reset_diagnostics_area");
+#ifdef DBUG_OFF
+ can_overwrite_status= FALSE;
+ /** Don't take chances in production */
+ m_message[0]= '\0';
+ m_sql_errno= 0;
+ m_server_status= 0;
+ m_affected_rows= 0;
+ m_last_insert_id= 0;
+ m_statement_warn_count= 0;
+#endif
+ is_sent= FALSE;
+ /** Tiny reset in debug mode to see garbage right away */
+ m_status= DA_EMPTY;
DBUG_VOID_RETURN;
}
-/*
- Push the warning/error to error list if there is still room in the list
+/**
+ Set OK status -- ends commands that do not return a
+ result set, e.g. INSERT/UPDATE/DELETE.
+*/
- SYNOPSIS
- push_warning()
- thd Thread handle
- level Severity of warning (note, warning, error ...)
- code Error number
- msg Clear error message
-
- RETURN
- pointer on MYSQL_ERROR object
+void
+Diagnostics_area::set_ok_status(THD *thd, ulonglong affected_rows_arg,
+ ulonglong last_insert_id_arg,
+ const char *message_arg)
+{
+ DBUG_ENTER("set_ok_status");
+ DBUG_ASSERT(! is_set());
+ /*
+ In production, refuse to overwrite an error or a custom response
+ with an OK packet.
+ */
+ if (is_error() || is_disabled())
+ return;
+
+ m_server_status= thd->server_status;
+ m_statement_warn_count= thd->warning_info->statement_warn_count();
+ m_affected_rows= affected_rows_arg;
+ m_last_insert_id= last_insert_id_arg;
+ if (message_arg)
+ strmake(m_message, message_arg, sizeof(m_message) - 1);
+ else
+ m_message[0]= '\0';
+ m_status= DA_OK;
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ Set EOF status.
*/
-MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
- uint code, const char *msg)
+void
+Diagnostics_area::set_eof_status(THD *thd)
{
- MYSQL_ERROR *err= 0;
- DBUG_ENTER("push_warning");
- DBUG_PRINT("enter", ("code: %d, msg: %s", code, msg));
+ DBUG_ENTER("set_eof_status");
+ /* Only allowed to report eof if has not yet reported an error */
+ DBUG_ASSERT(! is_set());
+ /*
+ In production, refuse to overwrite an error or a custom response
+ with an EOF packet.
+ */
+ if (is_error() || is_disabled())
+ return;
+
+ m_server_status= thd->server_status;
+ /*
+ If inside a stored procedure, do not return the total
+ number of warnings, since they are not available to the client
+ anyway.
+ */
+ m_statement_warn_count= (thd->spcont ?
+ 0 : thd->warning_info->statement_warn_count());
+
+ m_status= DA_EOF;
+ DBUG_VOID_RETURN;
+}
- DBUG_ASSERT(code != 0);
- DBUG_ASSERT(msg != NULL);
+/**
+ Set ERROR status.
+*/
- if (level == MYSQL_ERROR::WARN_LEVEL_NOTE &&
- !(thd->options & OPTION_SQL_NOTES))
- DBUG_RETURN(0);
+void
+Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
+ const char *message_arg,
+ const char *sqlstate)
+{
+ DBUG_ENTER("set_error_status");
+ /*
+ Only allowed to report error if has not yet reported a success
+ The only exception is when we flush the message to the client,
+ an error can happen during the flush.
+ */
+ DBUG_ASSERT(! is_set() || can_overwrite_status);
+#ifdef DBUG_OFF
+ /*
+ In production, refuse to overwrite a custom response with an
+ ERROR packet.
+ */
+ if (is_disabled())
+ return;
+#endif
+
+ if (sqlstate == NULL)
+ sqlstate= mysql_errno_to_sqlstate(sql_errno_arg);
+
+ m_sql_errno= sql_errno_arg;
+ memcpy(m_sqlstate, sqlstate, SQLSTATE_LENGTH);
+ m_sqlstate[SQLSTATE_LENGTH]= '\0';
+ strmake(m_message, message_arg, sizeof(m_message)-1);
+
+ m_status= DA_ERROR;
+ DBUG_VOID_RETURN;
+}
- if (thd->query_id != thd->warn_id && !thd->spcont)
- mysql_reset_errors(thd, 0);
- thd->got_warning= 1;
- /* Abort if we are using strict mode and we are not using IGNORE */
- if ((int) level >= (int) MYSQL_ERROR::WARN_LEVEL_WARN &&
- thd->really_abort_on_warning())
- {
- /* Avoid my_message() calling push_warning */
- bool no_warnings_for_error= thd->no_warnings_for_error;
- sp_rcontext *spcont= thd->spcont;
+/**
+ Mark the diagnostics area as 'DISABLED'.
+
+ This is used in rare cases when the COM_ command at hand sends a response
+ in a custom format. One example is the query cache, another is
+ COM_STMT_PREPARE.
+*/
- thd->no_warnings_for_error= 1;
- thd->spcont= NULL;
+void
+Diagnostics_area::disable_status()
+{
+ DBUG_ASSERT(! is_set());
+ m_status= DA_DISABLED;
+}
- thd->killed= THD::KILL_BAD_DATA;
- my_message(code, msg, MYF(0));
+Warning_info::Warning_info(ulonglong warn_id_arg)
+ :m_statement_warn_count(0),
+ m_current_row_for_warning(1),
+ m_warn_id(warn_id_arg),
+ m_read_only(FALSE)
+{
+ /* Initialize sub structures */
+ init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
+ m_warn_list.empty();
+ bzero((char*) m_warn_count, sizeof(m_warn_count));
+}
- thd->spcont= spcont;
- thd->no_warnings_for_error= no_warnings_for_error;
- /* Store error in error list (as my_message() didn't do it) */
- level= MYSQL_ERROR::WARN_LEVEL_ERROR;
- }
- if (thd->handle_error(code, msg, level))
- DBUG_RETURN(NULL);
+Warning_info::~Warning_info()
+{
+ free_root(&m_warn_root,MYF(0));
+}
- if (thd->spcont &&
- thd->spcont->handle_error(code, level, thd))
+
+/**
+ Reset the warning information of this connection.
+*/
+
+void Warning_info::clear_warning_info(ulonglong warn_id_arg)
+{
+ m_warn_id= warn_id_arg;
+ free_root(&m_warn_root, MYF(0));
+ bzero((char*) m_warn_count, sizeof(m_warn_count));
+ m_warn_list.empty();
+ m_statement_warn_count= 0;
+ m_current_row_for_warning= 1; /* Start counting from the first row */
+}
+
+void Warning_info::reserve_space(THD *thd, uint count)
+{
+ /* Make room for count conditions */
+ while ((m_warn_list.elements > 0) &&
+ ((m_warn_list.elements + count) > thd->variables.max_error_count))
+ m_warn_list.pop();
+}
+
+/**
+ Append warnings only if the original contents of the routine
+ warning info was replaced.
+*/
+void Warning_info::merge_with_routine_info(THD *thd, Warning_info *source)
+{
+ /*
+ If a routine body is empty or if a routine did not
+ generate any warnings (thus m_warn_id didn't change),
+ do not duplicate our own contents by appending the
+ contents of the called routine. We know that the called
+ routine did not change its warning info.
+
+ On the other hand, if the routine body is not empty and
+ some statement in the routine generates a warning or
+ uses tables, m_warn_id is guaranteed to have changed.
+ In this case we know that the routine warning info
+ contains only new warnings, and thus we perform a copy.
+ */
+ if (m_warn_id != source->m_warn_id)
{
- DBUG_RETURN(NULL);
+ /*
+ If the invocation of the routine was a standalone statement,
+ rather than a sub-statement, in other words, if it's a CALL
+ of a procedure, rather than invocation of a function or a
+ trigger, we need to clear the current contents of the caller's
+ warning info.
+
+ This is per MySQL rules: if a statement generates a warning,
+ warnings from the previous statement are flushed. Normally
+ it's done in push_warning(). However, here we don't use
+ push_warning() to avoid invocation of condition handlers or
+ escalation of warnings to errors.
+ */
+ opt_clear_warning_info(thd->query_id);
+ append_warning_info(thd, source);
}
- query_cache_abort(&thd->net);
+}
+/**
+ Add a warning to the list of warnings. Increment the respective
+ counters.
+*/
+MYSQL_ERROR *Warning_info::push_warning(THD *thd,
+ uint sql_errno, const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char *msg)
+{
+ MYSQL_ERROR *cond= NULL;
- if (thd->warn_list.elements < thd->variables.max_error_count)
+ if (! m_read_only)
{
- /* We have to use warn_root, as mem_root is freed after each query */
- if ((err= new (&thd->warn_root) MYSQL_ERROR(thd, code, level, msg)))
- thd->warn_list.push_back(err, &thd->warn_root);
+ if (m_warn_list.elements < thd->variables.max_error_count)
+ {
+ cond= new (& m_warn_root) MYSQL_ERROR(& m_warn_root);
+ if (cond)
+ {
+ cond->set(sql_errno, sqlstate, level, msg);
+ m_warn_list.push_back(cond, &m_warn_root);
+ }
+ }
+ m_warn_count[(uint) level]++;
}
- thd->warn_count[(uint) level]++;
- thd->total_warn_count++;
- DBUG_RETURN(err);
+
+ m_statement_warn_count++;
+ return cond;
}
/*
- Push the warning/error to error list if there is still room in the list
+ Push the warning to error list if there is still room in the list
+
+ SYNOPSIS
+ push_warning()
+ thd Thread handle
+ level Severity of warning (note, warning)
+ code Error number
+ msg Clear error message
+*/
+
+void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *msg)
+{
+ DBUG_ENTER("push_warning");
+ DBUG_PRINT("enter", ("code: %d, msg: %s", code, msg));
+
+ /*
+ Calling push_warning/push_warning_printf with a
+ level of WARN_LEVEL_ERROR *is* a bug.
+ Either use my_error(), or WARN_LEVEL_WARN.
+ Please fix the calling code, and do *NOT*
+ add more work around code in the assert below.
+ */
+ DBUG_ASSERT( (level != MYSQL_ERROR::WARN_LEVEL_ERROR)
+ || (code == ER_CANT_CREATE_TABLE) /* See Bug#47233 */
+ || (code == ER_ILLEGAL_HA_CREATE_OPTION) /* See Bug#47233 */
+ );
+
+ if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
+ level= MYSQL_ERROR::WARN_LEVEL_WARN;
+
+ (void) thd->raise_condition(code, NULL, level, msg);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Push the warning to error list if there is still room in the list
SYNOPSIS
push_warning_printf()
thd Thread handle
- level Severity of warning (note, warning, error ...)
+ level Severity of warning (note, warning)
code Error number
msg Clear error message
*/
@@ -217,10 +662,12 @@ const LEX_STRING warning_level_names[]=
};
bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
-{
+{
List<Item> field_list;
DBUG_ENTER("mysqld_show_warnings");
+ DBUG_ASSERT(thd->warning_info->is_read_only());
+
field_list.push_back(new Item_empty_string("Level", 7));
field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));
@@ -232,29 +679,36 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
MYSQL_ERROR *err;
SELECT_LEX *sel= &thd->lex->select_lex;
SELECT_LEX_UNIT *unit= &thd->lex->unit;
- ha_rows idx= 0;
+ ulonglong idx= 0;
Protocol *protocol=thd->protocol;
unit->set_limit(sel);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
while ((err= it++))
{
/* Skip levels that the user is not interested in */
- if (!(levels_to_show & ((ulong) 1 << err->level)))
+ if (!(levels_to_show & ((ulong) 1 << err->get_level())))
continue;
if (++idx <= unit->offset_limit_cnt)
continue;
if (idx > unit->select_limit_cnt)
break;
protocol->prepare_for_resend();
- protocol->store(warning_level_names[err->level].str,
- warning_level_names[err->level].length, system_charset_info);
- protocol->store((uint32) err->code);
- protocol->store(err->msg, (uint) strlen(err->msg), system_charset_info);
+ protocol->store(warning_level_names[err->get_level()].str,
+ warning_level_names[err->get_level()].length,
+ system_charset_info);
+ protocol->store((uint32) err->get_sql_errno());
+ protocol->store(err->get_message_text(),
+ err->get_message_octet_length(),
+ system_charset_info);
if (protocol->write())
DBUG_RETURN(TRUE);
}
my_eof(thd);
+
+ thd->warning_info->set_read_only(FALSE);
+
DBUG_RETURN(FALSE);
}
+
diff --git a/sql/sql_error.h b/sql/sql_error.h
index f98264dce50..f7b0ff56efa 100644
--- a/sql/sql_error.h
+++ b/sql/sql_error.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB,
+ Copyright (C) 2008-2009 Sun Microsystems, Inc
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,31 +14,514 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-class MYSQL_ERROR: public Sql_alloc
+#ifndef SQL_ERROR_H
+#define SQL_ERROR_H
+
+#include "sql_list.h" /* Sql_alloc, MEM_ROOT */
+#include "m_string.h" /* LEX_STRING */
+#include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */
+
+class THD;
+
+/**
+ Stores status of the currently executed statement.
+ Cleared at the beginning of the statement, and then
+ can hold either OK, ERROR, or EOF status.
+ Can not be assigned twice per statement.
+*/
+
+class Diagnostics_area
+{
+public:
+ enum enum_diagnostics_status
+ {
+ /** The area is cleared at start of a statement. */
+ DA_EMPTY= 0,
+ /** Set whenever one calls my_ok(). */
+ DA_OK,
+ /** Set whenever one calls my_eof(). */
+ DA_EOF,
+ /** Set whenever one calls my_error() or my_message(). */
+ DA_ERROR,
+ /** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
+ DA_DISABLED
+ };
+ /** True if status information is sent to the client. */
+ bool is_sent;
+ /** Set to make set_error_status after set_{ok,eof}_status possible. */
+ bool can_overwrite_status;
+
+ void set_ok_status(THD *thd, ulonglong affected_rows_arg,
+ ulonglong last_insert_id_arg,
+ const char *message);
+ void set_eof_status(THD *thd);
+ void set_error_status(THD *thd, uint sql_errno_arg, const char *message_arg,
+ const char *sqlstate);
+
+ void disable_status();
+
+ void reset_diagnostics_area();
+
+ bool is_set() const { return m_status != DA_EMPTY; }
+ bool is_error() const { return m_status == DA_ERROR; }
+ bool is_eof() const { return m_status == DA_EOF; }
+ bool is_ok() const { return m_status == DA_OK; }
+ bool is_disabled() const { return m_status == DA_DISABLED; }
+ enum_diagnostics_status status() const { return m_status; }
+
+ const char *message() const
+ { DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }
+
+ uint sql_errno() const
+ { DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
+
+ const char* get_sqlstate() const
+ { DBUG_ASSERT(m_status == DA_ERROR); return m_sqlstate; }
+
+ uint server_status() const
+ {
+ DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
+ return m_server_status;
+ }
+
+ ulonglong affected_rows() const
+ { DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
+
+ ulonglong last_insert_id() const
+ { DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
+
+ uint statement_warn_count() const
+ {
+ DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
+ return m_statement_warn_count;
+ }
+
+ Diagnostics_area() { reset_diagnostics_area(); }
+
+private:
+ /** Message buffer. Can be used by OK or ERROR status. */
+ char m_message[MYSQL_ERRMSG_SIZE];
+ /**
+ SQL error number. One of ER_ codes from share/errmsg.txt.
+ Set by set_error_status.
+ */
+ uint m_sql_errno;
+
+ char m_sqlstate[SQLSTATE_LENGTH+1];
+
+ /**
+ Copied from thd->server_status when the diagnostics area is assigned.
+ We need this member as some places in the code use the following pattern:
+ thd->server_status|= ...
+ my_eof(thd);
+ thd->server_status&= ~...
+ Assigned by OK, EOF or ERROR.
+ */
+ uint m_server_status;
+ /**
+ The number of rows affected by the last statement. This is
+ semantically close to thd->row_count_func, but has a different
+ life cycle. thd->row_count_func stores the value returned by
+ function ROW_COUNT() and is cleared only by statements that
+ update its value, such as INSERT, UPDATE, DELETE and few others.
+ This member is cleared at the beginning of the next statement.
+
+ We could possibly merge the two, but life cycle of thd->row_count_func
+ can not be changed.
+ */
+ ulonglong m_affected_rows;
+ /**
+ Similarly to the previous member, this is a replacement of
+ thd->first_successful_insert_id_in_prev_stmt, which is used
+ to implement LAST_INSERT_ID().
+ */
+ ulonglong m_last_insert_id;
+ /**
+ Number of warnings of this last statement. May differ from
+ the number of warnings returned by SHOW WARNINGS e.g. in case
+ the statement doesn't clear the warnings, and doesn't generate
+ them.
+ */
+ uint m_statement_warn_count;
+ enum_diagnostics_status m_status;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Representation of a SQL condition.
+ A SQL condition can be a completion condition (note, warning),
+ or an exception condition (error, not found).
+ @note This class is named MYSQL_ERROR instead of SQL_condition for historical reasons,
+ to facilitate merging code with previous releases.
+*/
+class MYSQL_ERROR : public Sql_alloc
{
public:
+ /*
+ Enumeration value describing the severity of the error.
+
+ Note that these enumeration values must correspond to the indices
+ of the sql_print_message_handlers array.
+ */
enum enum_warning_level
{ WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
+ /**
+ Get the MESSAGE_TEXT of this condition.
+ @return the message text.
+ */
+ const char* get_message_text() const;
+
+ /**
+ Get the MESSAGE_OCTET_LENGTH of this condition.
+ @return the length in bytes of the message text.
+ */
+ int get_message_octet_length() const;
+
+ /**
+ Get the SQLSTATE of this condition.
+ @return the sql state.
+ */
+ const char* get_sqlstate() const
+ { return m_returned_sqlstate; }
+
+ /**
+ Get the SQL_ERRNO of this condition.
+ @return the sql error number condition item.
+ */
+ uint get_sql_errno() const
+ { return m_sql_errno; }
+
+ /**
+ Get the error level of this condition.
+ @return the error level condition item.
+ */
+ MYSQL_ERROR::enum_warning_level get_level() const
+ { return m_level; }
+
+private:
+ /*
+ The interface of MYSQL_ERROR is mostly private, by design,
+ so that only the following code:
+ - various raise_error() or raise_warning() methods in class THD,
+ - the implementation of SIGNAL / RESIGNAL
+ - catch / re-throw of SQL conditions in stored procedures (sp_rcontext)
+ is allowed to create / modify a SQL condition.
+ Enforcing this policy prevents confusion, since the only public
+ interface available to the rest of the server implementation
+ is the interface offered by the THD methods (THD::raise_error()),
+ which should be used.
+ */
+ friend class THD;
+ friend class Warning_info;
+ friend class Signal_common;
+ friend class Signal_statement;
+ friend class Resignal_statement;
+ friend class sp_rcontext;
+
+ /**
+ Default constructor.
+ This constructor is usefull when allocating arrays.
+ Note that the init() method should be called to complete the MYSQL_ERROR.
+ */
+ MYSQL_ERROR();
+
+ /**
+ Complete the MYSQL_ERROR initialisation.
+ @param mem_root The memory root to use for the condition items
+ of this condition
+ */
+ void init(MEM_ROOT *mem_root);
+
+ /**
+ Constructor.
+ @param mem_root The memory root to use for the condition items
+ of this condition
+ */
+ MYSQL_ERROR(MEM_ROOT *mem_root);
+
+ /** Destructor. */
+ ~MYSQL_ERROR()
+ {}
+
+ /**
+ Copy optional condition items attributes.
+ @param cond the condition to copy.
+ */
+ void copy_opt_attributes(const MYSQL_ERROR *cond);
+
+ /**
+ Set this condition area with a fixed message text.
+ @param thd the current thread.
+ @param code the error number for this condition.
+ @param str the message text for this condition.
+ @param level the error level for this condition.
+ @param MyFlags additional flags.
+ */
+ void set(uint sql_errno, const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg);
+
+ /**
+ Set the condition message test.
+ @param str Message text, expressed in the character set derived from
+ the server --language option
+ */
+ void set_builtin_message_text(const char* str);
+
+ /** Set the SQLSTATE of this condition. */
+ void set_sqlstate(const char* sqlstate);
+
+ /**
+ Clear this SQL condition.
+ */
+ void clear();
+
+private:
+ /** SQL CLASS_ORIGIN condition item. */
+ String m_class_origin;
+
+ /** SQL SUBCLASS_ORIGIN condition item. */
+ String m_subclass_origin;
+
+ /** SQL CONSTRAINT_CATALOG condition item. */
+ String m_constraint_catalog;
- uint code;
- enum_warning_level level;
- char *msg;
-
- MYSQL_ERROR(THD *thd, uint code_arg, enum_warning_level level_arg,
- const char *msg_arg)
- :code(code_arg), level(level_arg)
+ /** SQL CONSTRAINT_SCHEMA condition item. */
+ String m_constraint_schema;
+
+ /** SQL CONSTRAINT_NAME condition item. */
+ String m_constraint_name;
+
+ /** SQL CATALOG_NAME condition item. */
+ String m_catalog_name;
+
+ /** SQL SCHEMA_NAME condition item. */
+ String m_schema_name;
+
+ /** SQL TABLE_NAME condition item. */
+ String m_table_name;
+
+ /** SQL COLUMN_NAME condition item. */
+ String m_column_name;
+
+ /** SQL CURSOR_NAME condition item. */
+ String m_cursor_name;
+
+ /** Message text, expressed in the character set implied by --language. */
+ String m_message_text;
+
+ /** MySQL extension, MYSQL_ERRNO condition item. */
+ uint m_sql_errno;
+
+ /**
+ SQL RETURNED_SQLSTATE condition item.
+ This member is always NUL terminated.
+ */
+ char m_returned_sqlstate[SQLSTATE_LENGTH+1];
+
+ /** Severity (error, warning, note) of this condition. */
+ MYSQL_ERROR::enum_warning_level m_level;
+
+ /** Memory root to use to hold condition item values. */
+ MEM_ROOT *m_mem_root;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Information about warnings of the current connection.
+*/
+
+class Warning_info
+{
+ /** A memory root to allocate warnings and errors */
+ MEM_ROOT m_warn_root;
+ /** List of warnings of all severities (levels). */
+ List <MYSQL_ERROR> m_warn_list;
+ /** A break down of the number of warnings per severity (level). */
+ uint m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
+ /**
+ The number of warnings of the current statement. Warning_info
+ life cycle differs from statement life cycle -- it may span
+ multiple statements. In that case we get
+ m_statement_warn_count 0, whereas m_warn_list is not empty.
+ */
+ uint m_statement_warn_count;
+ /*
+ Row counter, to print in errors and warnings. Not increased in
+ create_sort_index(); may differ from examined_row_count.
+ */
+ ulong m_current_row_for_warning;
+ /** Used to optionally clear warnings only once per statement. */
+ ulonglong m_warn_id;
+
+private:
+ Warning_info(const Warning_info &rhs); /* Not implemented */
+ Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
+public:
+
+ Warning_info(ulonglong warn_id_arg);
+ ~Warning_info();
+
+ /**
+ Reset the warning information. Clear all warnings,
+ the number of warnings, reset current row counter
+ to point to the first row.
+ */
+ void clear_warning_info(ulonglong warn_id_arg);
+ /**
+ Only clear warning info if haven't yet done that already
+ for the current query. Allows to be issued at any time
+ during the query, without risk of clearing some warnings
+ that have been generated by the current statement.
+
+ @todo: This is a sign of sloppy coding. Instead we need to
+ designate one place in a statement life cycle where we call
+ clear_warning_info().
+ */
+ void opt_clear_warning_info(ulonglong query_id)
+ {
+ if (query_id != m_warn_id)
+ clear_warning_info(query_id);
+ }
+
+ void append_warning_info(THD *thd, Warning_info *source)
{
- if (msg_arg)
- set_msg(thd, msg_arg);
+ append_warnings(thd, & source->warn_list());
}
- void set_msg(THD *thd, const char *msg_arg);
+
+ /**
+ Concatenate the list of warnings.
+ It's considered tolerable to lose a warning.
+ */
+ void append_warnings(THD *thd, List<MYSQL_ERROR> *src)
+ {
+ MYSQL_ERROR *err;
+ MYSQL_ERROR *copy;
+ List_iterator_fast<MYSQL_ERROR> it(*src);
+ /*
+ Don't use ::push_warning() to avoid invocation of condition
+ handlers or escalation of warnings to errors.
+ */
+ while ((err= it++))
+ {
+ copy= Warning_info::push_warning(thd, err->get_sql_errno(), err->get_sqlstate(),
+ err->get_level(), err->get_message_text());
+ if (copy)
+ copy->copy_opt_attributes(err);
+ }
+ }
+
+ /**
+ Conditional merge of related warning information areas.
+ */
+ void merge_with_routine_info(THD *thd, Warning_info *source);
+
+ /**
+ Reset between two COM_ commands. Warnings are preserved
+ between commands, but statement_warn_count indicates
+ the number of warnings of this particular statement only.
+ */
+ void reset_for_next_command() { m_statement_warn_count= 0; }
+
+ /**
+ Used for @@warning_count system variable, which prints
+ the number of rows returned by SHOW WARNINGS.
+ */
+ ulong warn_count() const
+ {
+ /*
+ This may be higher than warn_list.elements if we have
+ had more warnings than thd->variables.max_error_count.
+ */
+ return (m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
+ m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
+ m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
+ }
+
+ /**
+ This is for iteration purposes. We return a non-constant reference
+ since List doesn't have constant iterators.
+ */
+ List<MYSQL_ERROR> &warn_list() { return m_warn_list; }
+
+ /**
+ The number of errors, or number of rows returned by SHOW ERRORS,
+ also the value of session variable @@error_count.
+ */
+ ulong error_count() const
+ {
+ return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
+ }
+
+ /** Id of the warning information area. */
+ ulonglong warn_id() const { return m_warn_id; }
+
+ /** Do we have any errors and warnings that we can *show*? */
+ bool is_empty() const { return m_warn_list.elements == 0; }
+
+ /** Increment the current row counter to point at the next row. */
+ void inc_current_row_for_warning() { m_current_row_for_warning++; }
+ /** Reset the current row counter. Start counting from the first row. */
+ void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
+ /** Return the current counter value. */
+ ulong current_row_for_warning() const { return m_current_row_for_warning; }
+
+ ulong statement_warn_count() const { return m_statement_warn_count; }
+
+ /**
+ Reserve some space in the condition area.
+ This is a privileged operation, reserved for the RESIGNAL implementation,
+ as only the RESIGNAL statement is allowed to remove conditions from
+ the condition area.
+ For other statements, new conditions are not added to the condition
+ area once the condition area is full.
+ @param thd The current thread
+ @param count The number of slots to reserve
+ */
+ void reserve_space(THD *thd, uint count);
+
+ /** Add a new condition to the current list. */
+ MYSQL_ERROR *push_warning(THD *thd,
+ uint sql_errno, const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg);
+
+ /**
+ Set the read only status for this statement area.
+ This is a privileged operation, reserved for the implementation of
+ diagnostics related statements, to enforce that the statement area is
+ left untouched during execution.
+ The diagnostics statements are:
+ - SHOW WARNINGS
+ - SHOW ERRORS
+ - GET DIAGNOSTICS
+ @param read_only the read only property to set
+ */
+ void set_read_only(bool read_only)
+ { m_read_only= read_only; }
+
+ /**
+ Read only status.
+ @return the read only property
+ */
+ bool is_read_only() const
+ { return m_read_only; }
+
+private:
+ /** Read only status. */
+ bool m_read_only;
+
+ friend class Resignal_statement;
};
-MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
- uint code, const char *msg);
+void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *msg);
void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *format, ...);
-void mysql_reset_errors(THD *thd, bool force);
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
extern const LEX_STRING warning_level_names[];
+
+#endif // SQL_ERROR_H
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b139eb83d07..1ef4d5827ec 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -810,7 +810,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
error=write_record(thd, table ,&info);
if (error)
break;
- thd->row_count++;
+ thd->warning_info->inc_current_row_for_warning();
}
free_underlaid_joins(thd, &thd->lex->select_lex);
@@ -949,10 +949,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (ignore)
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
(lock_type == TL_WRITE_DELAYED) ? (ulong) 0 :
- (ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
+ (ulong) (info.records - info.copied),
+ (ulong) thd->warning_info->statement_warn_count());
else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
- (ulong) (info.deleted + updated), (ulong) thd->cuted_fields);
+ (ulong) (info.deleted + updated),
+ (ulong) thd->warning_info->statement_warn_count());
thd->row_count_func= info.copied + info.deleted + updated;
::my_ok(thd, (ulong) thd->row_count_func, id, buff);
}
@@ -1955,7 +1957,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
main thread. Use of my_message will enable stored
procedures continue handlers.
*/
- my_message(di->thd.main_da.sql_errno(), di->thd.main_da.message(),
+ my_message(di->thd.stmt_da->sql_errno(), di->thd.stmt_da->message(),
MYF(0));
}
di->unlock();
@@ -2032,7 +2034,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
goto error;
if (dead)
{
- my_message(thd.main_da.sql_errno(), thd.main_da.message(), MYF(0));
+ my_message(thd.stmt_da->sql_errno(), thd.stmt_da->message(), MYF(0));
goto error;
}
}
@@ -2281,8 +2283,8 @@ static void handle_delayed_insert_impl(THD *thd, Delayed_insert *di)
if (init_thr_lock() || thd->store_globals())
{
/* Can't use my_error since store_globals has perhaps failed */
- thd->main_da.set_error_status(thd, ER_OUT_OF_RESOURCES,
- ER(ER_OUT_OF_RESOURCES));
+ thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES,
+ ER(ER_OUT_OF_RESOURCES), NULL);
thd->fatal_error();
goto err;
}
@@ -2496,21 +2498,16 @@ pthread_handler_t handle_delayed_insert(void *arg)
since it does not find one in the list.
*/
pthread_mutex_lock(&di->mutex);
-#if !defined( __WIN__) /* Win32 calls this in pthread_create */
if (my_thread_init())
{
/* Can't use my_error since store_globals has not yet been called */
- thd->main_da.set_error_status(thd, ER_OUT_OF_RESOURCES,
- ER(ER_OUT_OF_RESOURCES));
+ thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES,
+ ER(ER_OUT_OF_RESOURCES), NULL);
goto end;
}
-#endif
-
handle_delayed_insert_impl(thd, di);
-#ifndef __WIN__
end:
-#endif
/*
di should be unlinked from the thread handler list and have no active
clients
@@ -2753,7 +2750,7 @@ bool Delayed_insert::handle_inserts(void)
{
/* This should never happen */
table->file->print_error(error,MYF(0));
- sql_print_error("%s", thd.main_da.message());
+ sql_print_error("%s", thd.stmt_da->message());
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed in loop"));
goto err;
}
@@ -2795,7 +2792,7 @@ bool Delayed_insert::handle_inserts(void)
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{ // This shouldn't happen
table->file->print_error(error,MYF(0));
- sql_print_error("%s", thd.main_da.message());
+ sql_print_error("%s", thd.stmt_da->message());
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop"));
goto err;
}
@@ -3263,10 +3260,12 @@ bool select_insert::send_eof()
char buff[160];
if (info.ignore)
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
- (ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
+ (ulong) (info.records - info.copied),
+ (ulong) thd->warning_info->statement_warn_count());
else
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
- (ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields);
+ (ulong) (info.deleted+info.updated),
+ (ulong) thd->warning_info->statement_warn_count());
thd->row_count_func= info.copied + info.deleted +
((thd->client_capabilities & CLIENT_FOUND_ROWS) ?
info.touched : info.updated);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 76fd5354c51..47f66faf048 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -118,6 +118,7 @@ enum enum_sql_command {
SQLCOM_SHOW_CREATE_TRIGGER,
SQLCOM_ALTER_DB_UPGRADE,
SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
+ SQLCOM_SIGNAL, SQLCOM_RESIGNAL,
/*
When a command is added here, be sure it's also added in mysqld.cc
@@ -1518,6 +1519,62 @@ public:
CHARSET_INFO *m_underscore_cs;
};
+/**
+ Abstract representation of a statement.
+ This class is an interface between the parser and the runtime.
+ The parser builds the appropriate sub classes of Sql_statement
+ to represent a SQL statement in the parsed tree.
+ The execute() method in the sub classes contain the runtime implementation.
+ Note that this interface is used for SQL statement recently implemented,
+ the code for older statements tend to load the LEX structure with more
+ attributes instead.
+ The recommended way to implement new statements is to sub-class
+ Sql_statement, as this improves code modularity (see the 'big switch' in
+ dispatch_command()), and decrease the total size of the LEX structure
+ (therefore saving memory in stored programs).
+*/
+class Sql_statement : public Sql_alloc
+{
+public:
+ /**
+ Execute this SQL statement.
+ @param thd the current thread.
+ @return 0 on success.
+ */
+ virtual bool execute(THD *thd) = 0;
+
+protected:
+ /**
+ Constructor.
+ @param lex the LEX structure that represents parts of this statement.
+ */
+ Sql_statement(struct st_lex *lex)
+ : m_lex(lex)
+ {}
+
+ /** Destructor. */
+ virtual ~Sql_statement()
+ {
+ /*
+ Sql_statement objects are allocated in thd->mem_root.
+ In MySQL, the C++ destructor is never called, the underlying MEM_ROOT is
+ simply destroyed instead.
+ Do not rely on the destructor for any cleanup.
+ */
+ DBUG_ASSERT(FALSE);
+ }
+
+protected:
+ /**
+ The legacy LEX structure for this statement.
+ The LEX structure contains the existing properties of the parsed tree.
+ TODO: with time, attributes from LEX should move to sub classes of
+ Sql_statement, so that the parser only builds Sql_statement objects
+ with the minimum set of attributes, instead of a LEX structure that
+ contains the collection of every possible attribute.
+ */
+ struct st_lex *m_lex;
+};
/* The state of the lex parsing. This is saved in the THD struct */
@@ -1619,6 +1676,9 @@ typedef struct st_lex : public Query_tables_list
*/
nesting_map allow_sum_func;
enum_sql_command sql_command;
+
+ Sql_statement *m_stmt;
+
/*
Usually `expr` rule of yacc is quite reused but some commands better
not support subqueries which comes standard with this rule, like
@@ -1895,6 +1955,36 @@ typedef struct st_lex : public Query_tables_list
/**
+ Set_signal_information is a container used in the parsed tree to represent
+ the collection of assignments to condition items in the SIGNAL and RESIGNAL
+ statements.
+*/
+class Set_signal_information
+{
+public:
+ /** Constructor. */
+ Set_signal_information();
+
+ /** Copy constructor. */
+ Set_signal_information(const Set_signal_information& set);
+
+ /** Destructor. */
+ ~Set_signal_information()
+ {}
+
+ /** Clear all items. */
+ void clear();
+
+ /**
+ For each contition item assignment, m_item[] contains the parsed tree
+ that represents the expression assigned, if any.
+ m_item[] is an array indexed by Diag_condition_item_name.
+ */
+ Item *m_item[LAST_DIAG_SET_PROPERTY+1];
+};
+
+
+/**
The internal state of the syntax parser.
This object is only available during parsing,
and is private to the syntax parser implementation (sql_yacc.yy).
@@ -1920,6 +2010,12 @@ public:
*/
uchar *yacc_yyvs;
+ /**
+ Fragments of parsed tree,
+ used during the parsing of SIGNAL and RESIGNAL.
+ */
+ Set_signal_information m_set_signal_info;
+
/*
TODO: move more attributes from the LEX structure here.
*/
@@ -1976,6 +2072,6 @@ extern bool is_lex_native_function(const LEX_STRING *name);
@} (End of group Semantic_Analysis)
*/
-int my_missing_function_error(const LEX_STRING &token, const char *name);
+void my_missing_function_error(const LEX_STRING &token, const char *name);
#endif /* MYSQL_SERVER */
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index b7f33d51335..847417a31ed 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -15,6 +15,8 @@
/* Copy data from a textfile to table */
+/* 2006-12 Erik Wetterberg : LOAD XML added */
+
#include "mysql_priv.h"
#include <my_dir.h>
#include <m_ctype.h>
@@ -23,6 +25,23 @@
#include "sp_head.h"
#include "sql_trigger.h"
+class XML_TAG {
+public:
+ int level;
+ String field;
+ String value;
+ XML_TAG(int l, String f, String v);
+};
+
+
+XML_TAG::XML_TAG(int l, String f, String v)
+{
+ level= l;
+ field.append(f);
+ value.append(v);
+}
+
+
class READ_INFO {
File file;
uchar *buffer, /* Buffer for read text */
@@ -37,6 +56,7 @@ class READ_INFO {
bool need_end_io_cache;
IO_CACHE cache;
NET *io_net;
+ int level; /* for load xml */
public:
bool error,line_cuted,found_null,enclosed;
@@ -54,6 +74,12 @@ public:
char unescape(char chr);
int terminator(char *ptr,uint length);
bool find_start_of_fields();
+ /* load xml */
+ List<XML_TAG> taglist;
+ int read_value(int delim, String *val);
+ int read_xml();
+ int clear_level(int level);
+
/*
We need to force cache close before destructor is invoked to log
the last read block
@@ -82,6 +108,13 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
List<Item> &set_values, READ_INFO &read_info,
String &enclosed, ulong skip_lines,
bool ignore_check_option_errors);
+
+static int read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
+ List<Item> &fields_vars, List<Item> &set_fields,
+ List<Item> &set_values, READ_INFO &read_info,
+ String &enclosed, ulong skip_lines,
+ bool ignore_check_option_errors);
+
#ifndef EMBEDDED_LIBRARY
static bool write_execute_load_query_log_event(THD *thd,
bool duplicates, bool ignore,
@@ -390,7 +423,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */
thd->cuted_fields=0L;
/* Skip lines if there is a line terminator */
- if (ex->line_term->length())
+ if (ex->line_term->length() && ex->filetype != FILETYPE_XML)
{
/* ex->skip_lines needs to be preserved for logging */
while (skip_lines > 0)
@@ -421,7 +454,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
- if (!field_term->length() && !enclosed->length())
+ if (ex->filetype == FILETYPE_XML) /* load xml */
+ error= read_xml_field(thd, info, table_list, fields_vars,
+ set_fields, set_values, read_info,
+ *(ex->line_term), skip_lines, ignore);
+ else if (!field_term->length() && !enclosed->length())
error= read_fixed_length(thd, info, table_list, fields_vars,
set_fields, set_values, read_info,
skip_lines, ignore);
@@ -514,7 +551,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
goto err;
}
sprintf(name, ER(ER_LOAD_INFO), (ulong) info.records, (ulong) info.deleted,
- (ulong) (info.records - info.copied), (ulong) thd->cuted_fields);
+ (ulong) (info.records - info.copied),
+ (ulong) thd->warning_info->statement_warn_count());
if (thd->transaction.stmt.modified_non_trans_table)
thd->transaction.all.modified_non_trans_table= TRUE;
@@ -645,9 +683,10 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (pos == read_info.row_end)
{
thd->cuted_fields++; /* Not enough fields */
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_TOO_FEW_RECORDS,
- ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_TOO_FEW_RECORDS,
+ ER(ER_WARN_TOO_FEW_RECORDS),
+ thd->warning_info->current_row_for_warning());
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
}
@@ -668,9 +707,10 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (pos != read_info.row_end)
{
thd->cuted_fields++; /* To long row */
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_TOO_MANY_RECORDS,
- ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_TOO_MANY_RECORDS,
+ ER(ER_WARN_TOO_MANY_RECORDS),
+ thd->warning_info->current_row_for_warning());
}
if (thd->killed ||
@@ -703,11 +743,12 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (read_info.line_cuted)
{
thd->cuted_fields++; /* To long row */
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_TOO_MANY_RECORDS,
- ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_TOO_MANY_RECORDS,
+ ER(ER_WARN_TOO_MANY_RECORDS),
+ thd->warning_info->current_row_for_warning());
}
- thd->row_count++;
+ thd->warning_info->inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
@@ -773,7 +814,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
- thd->row_count);
+ thd->warning_info->current_row_for_warning());
DBUG_RETURN(1);
}
field->set_null();
@@ -841,7 +882,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
- thd->row_count);
+ thd->warning_info->current_row_for_warning());
DBUG_RETURN(1);
}
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
@@ -855,7 +896,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
thd->cuted_fields++;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
- ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
+ ER(ER_WARN_TOO_FEW_RECORDS),
+ thd->warning_info->current_row_for_warning());
}
else if (item->type() == Item::STRING_ITEM)
{
@@ -899,19 +941,184 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (read_info.line_cuted)
{
thd->cuted_fields++; /* To long row */
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
- thd->row_count);
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
+ thd->warning_info->current_row_for_warning());
if (thd->killed)
DBUG_RETURN(1);
}
- thd->row_count++;
+ thd->warning_info->inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
}
+/****************************************************************************
+** Read rows in xml format
+****************************************************************************/
+static int
+read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
+ List<Item> &fields_vars, List<Item> &set_fields,
+ List<Item> &set_values, READ_INFO &read_info,
+ String &row_tag, ulong skip_lines,
+ bool ignore_check_option_errors)
+{
+ List_iterator_fast<Item> it(fields_vars);
+ Item *item;
+ TABLE *table= table_list->table;
+ bool no_trans_update_stmt;
+ CHARSET_INFO *cs= read_info.read_charset;
+ DBUG_ENTER("read_xml_field");
+
+ no_trans_update_stmt= !table->file->has_transactions();
+
+ for ( ; ; it.rewind())
+ {
+ if (thd->killed)
+ {
+ thd->send_kill_message();
+ DBUG_RETURN(1);
+ }
+
+ // read row tag and save values into tag list
+ if (read_info.read_xml())
+ break;
+
+ List_iterator_fast<XML_TAG> xmlit(read_info.taglist);
+ xmlit.rewind();
+ XML_TAG *tag= NULL;
+
+#ifndef DBUG_OFF
+ DBUG_PRINT("read_xml_field", ("skip_lines=%d", (int) skip_lines));
+ while ((tag= xmlit++))
+ {
+ DBUG_PRINT("read_xml_field", ("got tag:%i '%s' '%s'",
+ tag->level, tag->field.c_ptr(),
+ tag->value.c_ptr()));
+ }
+#endif
+
+ restore_record(table, s->default_values);
+
+ while ((item= it++))
+ {
+ /* If this line is to be skipped we don't want to fill field or var */
+ if (skip_lines)
+ continue;
+
+ /* find field in tag list */
+ xmlit.rewind();
+ tag= xmlit++;
+
+ while(tag && strcmp(tag->field.c_ptr(), item->name) != 0)
+ tag= xmlit++;
+
+ if (!tag) // found null
+ {
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ Field *field= ((Item_field *) item)->field;
+ field->reset();
+ field->set_null();
+ if (field == table->next_number_field)
+ table->auto_increment_field_not_null= TRUE;
+ if (!field->maybe_null())
+ {
+ if (field->type() == FIELD_TYPE_TIMESTAMP)
+ ((Field_timestamp *) field)->set_time();
+ else if (field != table->next_number_field)
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_NULL_TO_NOTNULL, 1);
+ }
+ }
+ else
+ ((Item_user_var_as_out_param *) item)->set_null_value(cs);
+ continue;
+ }
+
+ if (item->type() == Item::FIELD_ITEM)
+ {
+
+ Field *field= ((Item_field *)item)->field;
+ field->set_notnull();
+ if (field == table->next_number_field)
+ table->auto_increment_field_not_null= TRUE;
+ field->store((char *) tag->value.ptr(), tag->value.length(), cs);
+ }
+ else
+ ((Item_user_var_as_out_param *) item)->set_value(
+ (char *) tag->value.ptr(),
+ tag->value.length(), cs);
+ }
+
+ if (read_info.error)
+ break;
+
+ if (skip_lines)
+ {
+ skip_lines--;
+ continue;
+ }
+
+ if (item)
+ {
+ /* Have not read any field, thus input file is simply ended */
+ if (item == fields_vars.head())
+ break;
+
+ for ( ; item; item= it++)
+ {
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ /*
+ QQ: We probably should not throw warning for each field.
+ But how about intention to always have the same number
+ of warnings in THD::cuted_fields (and get rid of cuted_fields
+ in the end ?)
+ */
+ thd->cuted_fields++;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_TOO_FEW_RECORDS,
+ ER(ER_WARN_TOO_FEW_RECORDS),
+ thd->warning_info->current_row_for_warning());
+ }
+ else
+ ((Item_user_var_as_out_param *)item)->set_null_value(cs);
+ }
+ }
+
+ if (thd->killed ||
+ fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
+ ignore_check_option_errors,
+ table->triggers,
+ TRG_EVENT_INSERT))
+ DBUG_RETURN(1);
+
+ switch (table_list->view_check_option(thd,
+ ignore_check_option_errors)) {
+ case VIEW_CHECK_SKIP:
+ read_info.next_line();
+ goto continue_loop;
+ case VIEW_CHECK_ERROR:
+ DBUG_RETURN(-1);
+ }
+
+ if (write_record(thd, table, &info))
+ DBUG_RETURN(1);
+
+ /*
+ We don't need to reset auto-increment field since we are restoring
+ its default value at the beginning of each loop iteration.
+ */
+ thd->transaction.stmt.modified_non_trans_table= no_trans_update_stmt;
+ thd->warning_info->inc_current_row_for_warning();
+ continue_loop:;
+ }
+ DBUG_RETURN(test(read_info.error) || thd->is_error());
+} /* load xml end */
+
+
/* Unescape all escape characters, mark \N as null */
char
@@ -950,6 +1157,7 @@ READ_INFO::READ_INFO(File file_par, uint tot_length, CHARSET_INFO *cs,
field_term_length= field_term.length();
line_term_ptr=(char*) line_term.ptr();
line_term_length= line_term.length();
+ level= 0; /* for load xml */
if (line_start.length() == 0)
{
line_start_ptr=0;
@@ -1025,6 +1233,10 @@ READ_INFO::~READ_INFO()
my_free((uchar*) buffer,MYF(0));
error=1;
}
+ List_iterator<XML_TAG> xmlit(taglist);
+ XML_TAG *t;
+ while ((t= xmlit++))
+ delete(t);
}
@@ -1357,3 +1569,319 @@ bool READ_INFO::find_start_of_fields()
}
return 0;
}
+
+
+/*
+ Clear taglist from tags with a specified level
+*/
+int READ_INFO::clear_level(int level)
+{
+ DBUG_ENTER("READ_INFO::read_xml clear_level");
+ List_iterator<XML_TAG> xmlit(taglist);
+ xmlit.rewind();
+ XML_TAG *tag;
+
+ while ((tag= xmlit++))
+ {
+ if(tag->level >= level)
+ {
+ xmlit.remove();
+ delete tag;
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Convert an XML entity to Unicode value.
+ Return -1 on error;
+*/
+static int
+my_xml_entity_to_char(const char *name, uint length)
+{
+ if (length == 2)
+ {
+ if (!memcmp(name, "gt", length))
+ return '>';
+ if (!memcmp(name, "lt", length))
+ return '<';
+ }
+ else if (length == 3)
+ {
+ if (!memcmp(name, "amp", length))
+ return '&';
+ }
+ else if (length == 4)
+ {
+ if (!memcmp(name, "quot", length))
+ return '"';
+ if (!memcmp(name, "apos", length))
+ return '\'';
+ }
+ return -1;
+}
+
+
+/**
+ @brief Convert newline, linefeed, tab to space
+
+ @param chr character
+
+ @details According to the "XML 1.0" standard,
+ only space (#x20) characters, carriage returns,
+ line feeds or tabs are considered as spaces.
+ Convert all of them to space (#x20) for parsing simplicity.
+*/
+static int
+my_tospace(int chr)
+{
+ return (chr == '\t' || chr == '\r' || chr == '\n') ? ' ' : chr;
+}
+
+
+/*
+ Read an xml value: handle multibyte and xml escape
+*/
+int READ_INFO::read_value(int delim, String *val)
+{
+ int chr;
+ String tmp;
+
+ for (chr= GET; my_tospace(chr) != delim && chr != my_b_EOF;)
+ {
+#ifdef USE_MB
+ if (my_mbcharlen(read_charset, chr) > 1)
+ {
+ DBUG_PRINT("read_xml",("multi byte"));
+ int i, ml= my_mbcharlen(read_charset, chr);
+ for (i= 1; i < ml; i++)
+ {
+ val->append(chr);
+ /*
+ Don't use my_tospace() in the middle of a multi-byte character
+ TODO: check that the multi-byte sequence is valid.
+ */
+ chr= GET;
+ if (chr == my_b_EOF)
+ return chr;
+ }
+ }
+#endif
+ if(chr == '&')
+ {
+ tmp.length(0);
+ for (chr= my_tospace(GET) ; chr != ';' ; chr= my_tospace(GET))
+ {
+ if (chr == my_b_EOF)
+ return chr;
+ tmp.append(chr);
+ }
+ if ((chr= my_xml_entity_to_char(tmp.ptr(), tmp.length())) >= 0)
+ val->append(chr);
+ else
+ {
+ val->append('&');
+ val->append(tmp);
+ val->append(';');
+ }
+ }
+ else
+ val->append(chr);
+ chr= GET;
+ }
+ return my_tospace(chr);
+}
+
+
+/*
+ Read a record in xml format
+ tags and attributes are stored in taglist
+ when tag set in ROWS IDENTIFIED BY is closed, we are ready and return
+*/
+int READ_INFO::read_xml()
+{
+ DBUG_ENTER("READ_INFO::read_xml");
+ int chr, chr2, chr3;
+ int delim= 0;
+ String tag, attribute, value;
+ bool in_tag= false;
+
+ tag.length(0);
+ attribute.length(0);
+ value.length(0);
+
+ for (chr= my_tospace(GET); chr != my_b_EOF ; )
+ {
+ switch(chr){
+ case '<': /* read tag */
+ /* TODO: check if this is a comment <!-- comment --> */
+ chr= my_tospace(GET);
+ if(chr == '!')
+ {
+ chr2= GET;
+ chr3= GET;
+
+ if(chr2 == '-' && chr3 == '-')
+ {
+ chr2= 0;
+ chr3= 0;
+ chr= my_tospace(GET);
+
+ while(chr != '>' || chr2 != '-' || chr3 != '-')
+ {
+ if(chr == '-')
+ {
+ chr3= chr2;
+ chr2= chr;
+ }
+ else if (chr2 == '-')
+ {
+ chr2= 0;
+ chr3= 0;
+ }
+ chr= my_tospace(GET);
+ if (chr == my_b_EOF)
+ goto found_eof;
+ }
+ break;
+ }
+ }
+
+ tag.length(0);
+ while(chr != '>' && chr != ' ' && chr != '/' && chr != my_b_EOF)
+ {
+ if(chr != delim) /* fix for the '<field name =' format */
+ tag.append(chr);
+ chr= my_tospace(GET);
+ }
+
+ // row tag should be in ROWS IDENTIFIED BY '<row>' - stored in line_term
+ if((tag.length() == line_term_length -2) &&
+ (strncmp(tag.c_ptr_safe(), line_term_ptr + 1, tag.length()) == 0))
+ {
+ DBUG_PRINT("read_xml", ("start-of-row: %i %s %s",
+ level,tag.c_ptr_safe(), line_term_ptr));
+ }
+
+ if(chr == ' ' || chr == '>')
+ {
+ level++;
+ clear_level(level + 1);
+ }
+
+ if (chr == ' ')
+ in_tag= true;
+ else
+ in_tag= false;
+ break;
+
+ case ' ': /* read attribute */
+ while(chr == ' ') /* skip blanks */
+ chr= my_tospace(GET);
+
+ if(!in_tag)
+ break;
+
+ while(chr != '=' && chr != '/' && chr != '>' && chr != my_b_EOF)
+ {
+ attribute.append(chr);
+ chr= my_tospace(GET);
+ }
+ break;
+
+ case '>': /* end tag - read tag value */
+ in_tag= false;
+ chr= read_value('<', &value);
+ if(chr == my_b_EOF)
+ goto found_eof;
+
+ /* save value to list */
+ if(tag.length() > 0 && value.length() > 0)
+ {
+ DBUG_PRINT("read_xml", ("lev:%i tag:%s val:%s",
+ level,tag.c_ptr_safe(), value.c_ptr_safe()));
+ taglist.push_front( new XML_TAG(level, tag, value));
+ }
+ tag.length(0);
+ value.length(0);
+ attribute.length(0);
+ break;
+
+ case '/': /* close tag */
+ level--;
+ chr= my_tospace(GET);
+ if(chr != '>') /* if this is an empty tag <tag /> */
+ tag.length(0); /* we should keep tag value */
+ while(chr != '>' && chr != my_b_EOF)
+ {
+ tag.append(chr);
+ chr= my_tospace(GET);
+ }
+
+ if((tag.length() == line_term_length -2) &&
+ (strncmp(tag.c_ptr_safe(), line_term_ptr + 1, tag.length()) == 0))
+ {
+ DBUG_PRINT("read_xml", ("found end-of-row %i %s",
+ level, tag.c_ptr_safe()));
+ DBUG_RETURN(0); //normal return
+ }
+ chr= my_tospace(GET);
+ break;
+
+ case '=': /* attribute name end - read the value */
+ //check for tag field and attribute name
+ if(!memcmp(tag.c_ptr_safe(), STRING_WITH_LEN("field")) &&
+ !memcmp(attribute.c_ptr_safe(), STRING_WITH_LEN("name")))
+ {
+ /*
+ this is format <field name="xx">xx</field>
+ where actual fieldname is in attribute
+ */
+ delim= my_tospace(GET);
+ tag.length(0);
+ attribute.length(0);
+ chr= '<'; /* we pretend that it is a tag */
+ level--;
+ break;
+ }
+
+ //check for " or '
+ chr= GET;
+ if (chr == my_b_EOF)
+ goto found_eof;
+ if(chr == '"' || chr == '\'')
+ {
+ delim= chr;
+ }
+ else
+ {
+ delim= ' '; /* no delimiter, use space */
+ PUSH(chr);
+ }
+
+ chr= read_value(delim, &value);
+ if(attribute.length() > 0 && value.length() > 0)
+ {
+ DBUG_PRINT("read_xml", ("lev:%i att:%s val:%s\n",
+ level + 1,
+ attribute.c_ptr_safe(),
+ value.c_ptr_safe()));
+ taglist.push_front(new XML_TAG(level + 1, attribute, value));
+ }
+ attribute.length(0);
+ value.length(0);
+ if (chr != ' ')
+ chr= my_tospace(GET);
+ break;
+
+ default:
+ chr= my_tospace(GET);
+ } /* end switch */
+ } /* end while */
+
+found_eof:
+ DBUG_PRINT("read_xml",("Found eof"));
+ eof= 1;
+ DBUG_RETURN(1);
+}
diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc
index 3def9864c29..fcfd60e72e6 100644
--- a/sql/sql_locale.cc
+++ b/sql/sql_locale.cc
@@ -51,7 +51,10 @@ MY_LOCALE my_locale_ar_AE
&my_locale_typelib_day_names_ar_AE,
&my_locale_typelib_ab_day_names_ar_AE,
6,
- 8
+ 8,
+ '.', /* decimal point ar_AE */
+ ',', /* thousands_sep ar_AE */
+ "\x03" /* grouping ar_AE */
);
/***** LOCALE END ar_AE *****/
@@ -83,7 +86,10 @@ MY_LOCALE my_locale_ar_BH
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_BH */
+ ',', /* thousands_sep ar_BH */
+ "\x03" /* grouping ar_BH */
);
/***** LOCALE END ar_BH *****/
@@ -115,7 +121,10 @@ MY_LOCALE my_locale_ar_JO
&my_locale_typelib_day_names_ar_JO,
&my_locale_typelib_ab_day_names_ar_JO,
12,
- 8
+ 8,
+ '.', /* decimal point ar_JO */
+ ',', /* thousands_sep ar_JO */
+ "\x03" /* grouping ar_JO */
);
/***** LOCALE END ar_JO *****/
@@ -147,7 +156,10 @@ MY_LOCALE my_locale_ar_SA
&my_locale_typelib_day_names_ar_SA,
&my_locale_typelib_ab_day_names_ar_SA,
12,
- 8
+ 8,
+ '.', /* decimal point ar_SA */
+ '\0', /* thousands_sep ar_SA */
+ "\x80" /* grouping ar_SA */
);
/***** LOCALE END ar_SA *****/
@@ -179,7 +191,10 @@ MY_LOCALE my_locale_ar_SY
&my_locale_typelib_day_names_ar_SY,
&my_locale_typelib_ab_day_names_ar_SY,
12,
- 8
+ 8,
+ '.', /* decimal point ar_SY */
+ ',', /* thousands_sep ar_SY */
+ "\x03" /* grouping ar_SY */
);
/***** LOCALE END ar_SY *****/
@@ -211,7 +226,10 @@ MY_LOCALE my_locale_be_BY
&my_locale_typelib_day_names_be_BY,
&my_locale_typelib_ab_day_names_be_BY,
10,
- 10
+ 10,
+ ',', /* decimal point be_BY */
+ '.', /* thousands_sep be_BY */
+ "\x03\x03" /* grouping be_BY */
);
/***** LOCALE END be_BY *****/
@@ -243,7 +261,10 @@ MY_LOCALE my_locale_bg_BG
&my_locale_typelib_day_names_bg_BG,
&my_locale_typelib_ab_day_names_bg_BG,
9,
- 10
+ 10,
+ ',', /* decimal point bg_BG */
+ '\0', /* thousands_sep bg_BG */
+ "\x03\x03" /* grouping bg_BG */
);
/***** LOCALE END bg_BG *****/
@@ -275,7 +296,11 @@ MY_LOCALE my_locale_ca_ES
&my_locale_typelib_day_names_ca_ES,
&my_locale_typelib_ab_day_names_ca_ES,
8,
- 9
+ 9,
+ ',', /* decimal point ca_ES */
+ '\0', /* thousands_sep ca_ES */
+ "\x80\x80" /* grouping ca_ES */
+
);
/***** LOCALE END ca_ES *****/
@@ -307,7 +332,10 @@ MY_LOCALE my_locale_cs_CZ
&my_locale_typelib_day_names_cs_CZ,
&my_locale_typelib_ab_day_names_cs_CZ,
8,
- 7
+ 7,
+ ',', /* decimal point cs_CZ */
+ ' ', /* thousands_sep cs_CZ */
+ "\x03\x03" /* grouping cs_CZ */
);
/***** LOCALE END cs_CZ *****/
@@ -339,7 +367,10 @@ MY_LOCALE my_locale_da_DK
&my_locale_typelib_day_names_da_DK,
&my_locale_typelib_ab_day_names_da_DK,
9,
- 7
+ 7,
+ ',', /* decimal point da_DK */
+ '.', /* thousands_sep da_DK */
+ "\x03\x03" /* grouping da_DK */
);
/***** LOCALE END da_DK *****/
@@ -371,7 +402,10 @@ MY_LOCALE my_locale_de_AT
&my_locale_typelib_day_names_de_AT,
&my_locale_typelib_ab_day_names_de_AT,
9,
- 10
+ 10,
+ ',', /* decimal point de_AT */
+ '\0', /* thousands_sep de_AT */
+ "\x80\x80" /* grouping de_AT */
);
/***** LOCALE END de_AT *****/
@@ -403,7 +437,10 @@ MY_LOCALE my_locale_de_DE
&my_locale_typelib_day_names_de_DE,
&my_locale_typelib_ab_day_names_de_DE,
9,
- 10
+ 10,
+ ',', /* decimal point de_DE */
+ '.', /* thousands_sep de_DE */
+ "\x03\x03" /* grouping de_DE */
);
/***** LOCALE END de_DE *****/
@@ -435,7 +472,10 @@ MY_LOCALE my_locale_en_US
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_US */
+ ',', /* thousands_sep en_US */
+ "\x03\x03" /* grouping en_US */
);
/***** LOCALE END en_US *****/
@@ -467,7 +507,10 @@ MY_LOCALE my_locale_es_ES
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_ES */
+ '\0', /* thousands_sep es_ES */
+ "\x80\x80" /* grouping es_ES */
);
/***** LOCALE END es_ES *****/
@@ -499,7 +542,10 @@ MY_LOCALE my_locale_et_EE
&my_locale_typelib_day_names_et_EE,
&my_locale_typelib_ab_day_names_et_EE,
9,
- 9
+ 9,
+ ',', /* decimal point et_EE */
+ ' ', /* thousands_sep et_EE */
+ "\x03\x03" /* grouping et_EE */
);
/***** LOCALE END et_EE *****/
@@ -531,7 +577,10 @@ MY_LOCALE my_locale_eu_ES
&my_locale_typelib_day_names_eu_ES,
&my_locale_typelib_ab_day_names_eu_ES,
9,
- 10
+ 10,
+ ',', /* decimal point eu_ES */
+ '\0', /* thousands_sep eu_ES */
+ "\x80\x80" /* grouping eu_ES */
);
/***** LOCALE END eu_ES *****/
@@ -563,7 +612,10 @@ MY_LOCALE my_locale_fi_FI
&my_locale_typelib_day_names_fi_FI,
&my_locale_typelib_ab_day_names_fi_FI,
9,
- 11
+ 11,
+ ',', /* decimal point fi_FI */
+ ' ', /* thousands_sep fi_FI */
+ "\x03\x03" /* grouping fi_FI */
);
/***** LOCALE END fi_FI *****/
@@ -595,7 +647,10 @@ MY_LOCALE my_locale_fo_FO
&my_locale_typelib_day_names_fo_FO,
&my_locale_typelib_ab_day_names_fo_FO,
9,
- 12
+ 12,
+ ',', /* decimal point fo_FO */
+ '.', /* thousands_sep fo_FO */
+ "\x03\x03" /* grouping fo_FO */
);
/***** LOCALE END fo_FO *****/
@@ -627,7 +682,10 @@ MY_LOCALE my_locale_fr_FR
&my_locale_typelib_day_names_fr_FR,
&my_locale_typelib_ab_day_names_fr_FR,
9,
- 8
+ 8,
+ ',', /* decimal point fr_FR */
+ '\0', /* thousands_sep fr_FR */
+ "\x80\x80" /* grouping fr_FR */
);
/***** LOCALE END fr_FR *****/
@@ -659,7 +717,10 @@ MY_LOCALE my_locale_gl_ES
&my_locale_typelib_day_names_gl_ES,
&my_locale_typelib_ab_day_names_gl_ES,
8,
- 8
+ 8,
+ ',', /* decimal point gl_ES */
+ '\0', /* thousands_sep gl_ES */
+ "\x80\x80" /* grouping gl_ES */
);
/***** LOCALE END gl_ES *****/
@@ -691,7 +752,10 @@ MY_LOCALE my_locale_gu_IN
&my_locale_typelib_day_names_gu_IN,
&my_locale_typelib_ab_day_names_gu_IN,
10,
- 8
+ 8,
+ '.', /* decimal point gu_IN */
+ ',', /* thousands_sep gu_IN */
+ "\x03" /* grouping gu_IN */
);
/***** LOCALE END gu_IN *****/
@@ -723,7 +787,10 @@ MY_LOCALE my_locale_he_IL
&my_locale_typelib_day_names_he_IL,
&my_locale_typelib_ab_day_names_he_IL,
7,
- 5
+ 5,
+ '.', /* decimal point he_IL */
+ ',', /* thousands_sep he_IL */
+ "\x03\x03" /* grouping he_IL */
);
/***** LOCALE END he_IL *****/
@@ -755,7 +822,10 @@ MY_LOCALE my_locale_hi_IN
&my_locale_typelib_day_names_hi_IN,
&my_locale_typelib_ab_day_names_hi_IN,
7,
- 9
+ 9,
+ '.', /* decimal point hi_IN */
+ ',', /* thousands_sep hi_IN */
+ "\x03" /* grouping hi_IN */
);
/***** LOCALE END hi_IN *****/
@@ -787,7 +857,10 @@ MY_LOCALE my_locale_hr_HR
&my_locale_typelib_day_names_hr_HR,
&my_locale_typelib_ab_day_names_hr_HR,
8,
- 11
+ 11,
+ ',', /* decimal point hr_HR */
+ '\0', /* thousands_sep hr_HR */
+ "\x80\x80" /* grouping hr_HR */
);
/***** LOCALE END hr_HR *****/
@@ -819,7 +892,10 @@ MY_LOCALE my_locale_hu_HU
&my_locale_typelib_day_names_hu_HU,
&my_locale_typelib_ab_day_names_hu_HU,
10,
- 9
+ 9,
+ ',', /* decimal point hu_HU */
+ '.', /* thousands_sep hu_HU */
+ "\x03\x03" /* grouping hu_HU */
);
/***** LOCALE END hu_HU *****/
@@ -851,7 +927,10 @@ MY_LOCALE my_locale_id_ID
&my_locale_typelib_day_names_id_ID,
&my_locale_typelib_ab_day_names_id_ID,
9,
- 6
+ 6,
+ ',', /* decimal point id_ID */
+ '.', /* thousands_sep id_ID */
+ "\x03\x03" /* grouping id_ID */
);
/***** LOCALE END id_ID *****/
@@ -883,7 +962,10 @@ MY_LOCALE my_locale_is_IS
&my_locale_typelib_day_names_is_IS,
&my_locale_typelib_ab_day_names_is_IS,
9,
- 12
+ 12,
+ ',', /* decimal point is_IS */
+ '.', /* thousands_sep is_IS */
+ "\x03\x03" /* grouping is_IS */
);
/***** LOCALE END is_IS *****/
@@ -915,7 +997,10 @@ MY_LOCALE my_locale_it_CH
&my_locale_typelib_day_names_it_CH,
&my_locale_typelib_ab_day_names_it_CH,
9,
- 9
+ 9,
+ ',', /* decimal point it_CH */
+ '\'', /* thousands_sep it_CH */
+ "\x03\x03" /* grouping it_CH */
);
/***** LOCALE END it_CH *****/
@@ -947,7 +1032,10 @@ MY_LOCALE my_locale_ja_JP
&my_locale_typelib_day_names_ja_JP,
&my_locale_typelib_ab_day_names_ja_JP,
3,
- 3
+ 3,
+ '.', /* decimal point ja_JP */
+ ',', /* thousands_sep ja_JP */
+ "\x03" /* grouping ja_JP */
);
/***** LOCALE END ja_JP *****/
@@ -979,7 +1067,10 @@ MY_LOCALE my_locale_ko_KR
&my_locale_typelib_day_names_ko_KR,
&my_locale_typelib_ab_day_names_ko_KR,
3,
- 3
+ 3,
+ '.', /* decimal point ko_KR */
+ ',', /* thousands_sep ko_KR */
+ "\x03\x03" /* grouping ko_KR */
);
/***** LOCALE END ko_KR *****/
@@ -1011,7 +1102,10 @@ MY_LOCALE my_locale_lt_LT
&my_locale_typelib_day_names_lt_LT,
&my_locale_typelib_ab_day_names_lt_LT,
9,
- 14
+ 14,
+ ',', /* decimal point lt_LT */
+ '.', /* thousands_sep lt_LT */
+ "\x03\x03" /* grouping lt_LT */
);
/***** LOCALE END lt_LT *****/
@@ -1043,7 +1137,10 @@ MY_LOCALE my_locale_lv_LV
&my_locale_typelib_day_names_lv_LV,
&my_locale_typelib_ab_day_names_lv_LV,
10,
- 11
+ 11,
+ ',', /* decimal point lv_LV */
+ ' ', /* thousands_sep lv_LV */
+ "\x03\x03" /* grouping lv_LV */
);
/***** LOCALE END lv_LV *****/
@@ -1075,7 +1172,10 @@ MY_LOCALE my_locale_mk_MK
&my_locale_typelib_day_names_mk_MK,
&my_locale_typelib_ab_day_names_mk_MK,
9,
- 10
+ 10,
+ ',', /* decimal point mk_MK */
+ ' ', /* thousands_sep mk_MK */
+ "\x03\x03" /* grouping mk_MK */
);
/***** LOCALE END mk_MK *****/
@@ -1107,7 +1207,10 @@ MY_LOCALE my_locale_mn_MN
&my_locale_typelib_day_names_mn_MN,
&my_locale_typelib_ab_day_names_mn_MN,
18,
- 6
+ 6,
+ ',', /* decimal point mn_MN */
+ '.', /* thousands_sep mn_MN */
+ "\x03\x03" /* grouping mn_MN */
);
/***** LOCALE END mn_MN *****/
@@ -1139,7 +1242,10 @@ MY_LOCALE my_locale_ms_MY
&my_locale_typelib_day_names_ms_MY,
&my_locale_typelib_ab_day_names_ms_MY,
9,
- 6
+ 6,
+ '.', /* decimal point ms_MY */
+ ',', /* thousands_sep ms_MY */
+ "\x03" /* grouping ms_MY */
);
/***** LOCALE END ms_MY *****/
@@ -1171,7 +1277,10 @@ MY_LOCALE my_locale_nb_NO
&my_locale_typelib_day_names_nb_NO,
&my_locale_typelib_ab_day_names_nb_NO,
9,
- 7
+ 7,
+ ',', /* decimal point nb_NO */
+ '.', /* thousands_sep nb_NO */
+ "\x03\x03" /* grouping nb_NO */
);
/***** LOCALE END nb_NO *****/
@@ -1203,7 +1312,10 @@ MY_LOCALE my_locale_nl_NL
&my_locale_typelib_day_names_nl_NL,
&my_locale_typelib_ab_day_names_nl_NL,
9,
- 9
+ 9,
+ ',', /* decimal point nl_NL */
+ '\0', /* thousands_sep nl_NL */
+ "\x80\x80" /* grouping nl_NL */
);
/***** LOCALE END nl_NL *****/
@@ -1235,7 +1347,10 @@ MY_LOCALE my_locale_pl_PL
&my_locale_typelib_day_names_pl_PL,
&my_locale_typelib_ab_day_names_pl_PL,
11,
- 12
+ 12,
+ ',', /* decimal point pl_PL */
+ '\0', /* thousands_sep pl_PL */
+ "\x80\x80" /* grouping pl_PL */
);
/***** LOCALE END pl_PL *****/
@@ -1267,7 +1382,10 @@ MY_LOCALE my_locale_pt_BR
&my_locale_typelib_day_names_pt_BR,
&my_locale_typelib_ab_day_names_pt_BR,
9,
- 7
+ 7,
+ ',', /* decimal point pt_BR */
+ '\0', /* thousands_sep pt_BR */
+ "\x80\x80" /* grouping pt_BR */
);
/***** LOCALE END pt_BR *****/
@@ -1299,7 +1417,10 @@ MY_LOCALE my_locale_pt_PT
&my_locale_typelib_day_names_pt_PT,
&my_locale_typelib_ab_day_names_pt_PT,
9,
- 7
+ 7,
+ ',', /* decimal point pt_PT */
+ '\0', /* thousands_sep pt_PT */
+ "\x80\x80" /* grouping pt_PT */
);
/***** LOCALE END pt_PT *****/
@@ -1331,7 +1452,10 @@ MY_LOCALE my_locale_ro_RO
&my_locale_typelib_day_names_ro_RO,
&my_locale_typelib_ab_day_names_ro_RO,
10,
- 8
+ 8,
+ ',', /* decimal point ro_RO */
+ '.', /* thousands_sep ro_RO */
+ "\x03\x03" /* grouping ro_RO */
);
/***** LOCALE END ro_RO *****/
@@ -1363,7 +1487,10 @@ MY_LOCALE my_locale_ru_RU
&my_locale_typelib_day_names_ru_RU,
&my_locale_typelib_ab_day_names_ru_RU,
8,
- 11
+ 11,
+ ',', /* decimal point ru_RU */
+ ' ', /* thousands_sep ru_RU */
+ "\x03\x03" /* grouping ru_RU */
);
/***** LOCALE END ru_RU *****/
@@ -1395,7 +1522,10 @@ MY_LOCALE my_locale_ru_UA
&my_locale_typelib_day_names_ru_UA,
&my_locale_typelib_ab_day_names_ru_UA,
8,
- 11
+ 11,
+ ',', /* decimal point ru_UA */
+ '.', /* thousands_sep ru_UA */
+ "\x03\x03" /* grouping ru_UA */
);
/***** LOCALE END ru_UA *****/
@@ -1427,7 +1557,10 @@ MY_LOCALE my_locale_sk_SK
&my_locale_typelib_day_names_sk_SK,
&my_locale_typelib_ab_day_names_sk_SK,
9,
- 8
+ 8,
+ ',', /* decimal point sk_SK */
+ ' ', /* thousands_sep sk_SK */
+ "\x03\x03" /* grouping sk_SK */
);
/***** LOCALE END sk_SK *****/
@@ -1459,7 +1592,10 @@ MY_LOCALE my_locale_sl_SI
&my_locale_typelib_day_names_sl_SI,
&my_locale_typelib_ab_day_names_sl_SI,
9,
- 10
+ 10,
+ ',', /* decimal point sl_SI */
+ ' ', /* thousands_sep sl_SI */
+ "\x80\x80" /* grouping sl_SI */
);
/***** LOCALE END sl_SI *****/
@@ -1491,7 +1627,10 @@ MY_LOCALE my_locale_sq_AL
&my_locale_typelib_day_names_sq_AL,
&my_locale_typelib_ab_day_names_sq_AL,
7,
- 10
+ 10,
+ ',', /* decimal point sq_AL */
+ '.', /* thousands_sep sq_AL */
+ "\x03" /* grouping sq_AL */
);
/***** LOCALE END sq_AL *****/
@@ -1523,7 +1662,10 @@ MY_LOCALE my_locale_sr_YU
&my_locale_typelib_day_names_sr_YU,
&my_locale_typelib_ab_day_names_sr_YU,
9,
- 10
+ 10,
+ '.', /* decimal point sr_YU */
+ '\0', /* thousands_sep sr_YU */
+ "\x80" /* grouping sr_YU */
);
/***** LOCALE END sr_YU *****/
@@ -1555,7 +1697,10 @@ MY_LOCALE my_locale_sv_SE
&my_locale_typelib_day_names_sv_SE,
&my_locale_typelib_ab_day_names_sv_SE,
9,
- 7
+ 7,
+ ',', /* decimal point sv_SE */
+ ' ', /* thousands_sep sv_SE */
+ "\x03\x03" /* grouping sv_SE */
);
/***** LOCALE END sv_SE *****/
@@ -1587,7 +1732,10 @@ MY_LOCALE my_locale_ta_IN
&my_locale_typelib_day_names_ta_IN,
&my_locale_typelib_ab_day_names_ta_IN,
10,
- 8
+ 8,
+ '.', /* decimal point ta_IN */
+ ',', /* thousands_sep ta_IN */
+ "\x03\x02" /* grouping ta_IN */
);
/***** LOCALE END ta_IN *****/
@@ -1619,7 +1767,10 @@ MY_LOCALE my_locale_te_IN
&my_locale_typelib_day_names_te_IN,
&my_locale_typelib_ab_day_names_te_IN,
10,
- 9
+ 9,
+ '.', /* decimal point te_IN */
+ ',', /* thousands_sep te_IN */
+ "\x03\x02" /* grouping te_IN */
);
/***** LOCALE END te_IN *****/
@@ -1651,7 +1802,10 @@ MY_LOCALE my_locale_th_TH
&my_locale_typelib_day_names_th_TH,
&my_locale_typelib_ab_day_names_th_TH,
10,
- 8
+ 8,
+ '.', /* decimal point th_TH */
+ ',', /* thousands_sep th_TH */
+ "\x03" /* grouping th_TH */
);
/***** LOCALE END th_TH *****/
@@ -1683,7 +1837,10 @@ MY_LOCALE my_locale_tr_TR
&my_locale_typelib_day_names_tr_TR,
&my_locale_typelib_ab_day_names_tr_TR,
7,
- 9
+ 9,
+ ',', /* decimal point tr_TR */
+ '.', /* thousands_sep tr_TR */
+ "\x03\x03" /* grouping tr_TR */
);
/***** LOCALE END tr_TR *****/
@@ -1715,7 +1872,10 @@ MY_LOCALE my_locale_uk_UA
&my_locale_typelib_day_names_uk_UA,
&my_locale_typelib_ab_day_names_uk_UA,
8,
- 9
+ 9,
+ ',', /* decimal point uk_UA */
+ '.', /* thousands_sep uk_UA */
+ "\x03\x03" /* grouping uk_UA */
);
/***** LOCALE END uk_UA *****/
@@ -1747,7 +1907,10 @@ MY_LOCALE my_locale_ur_PK
&my_locale_typelib_day_names_ur_PK,
&my_locale_typelib_ab_day_names_ur_PK,
6,
- 6
+ 6,
+ '.', /* decimal point ur_PK */
+ ',', /* thousands_sep ur_PK */
+ "\x03\x03" /* grouping ur_PK */
);
/***** LOCALE END ur_PK *****/
@@ -1779,7 +1942,10 @@ MY_LOCALE my_locale_vi_VN
&my_locale_typelib_day_names_vi_VN,
&my_locale_typelib_ab_day_names_vi_VN,
16,
- 11
+ 11,
+ ',', /* decimal point vi_VN */
+ '.', /* thousands_sep vi_VN */
+ "\x03\x03" /* grouping vi_VN */
);
/***** LOCALE END vi_VN *****/
@@ -1811,7 +1977,10 @@ MY_LOCALE my_locale_zh_CN
&my_locale_typelib_day_names_zh_CN,
&my_locale_typelib_ab_day_names_zh_CN,
3,
- 3
+ 3,
+ '.', /* decimal point zh_CN */
+ ',', /* thousands_sep zh_CN */
+ "\x03" /* grouping zh_CN */
);
/***** LOCALE END zh_CN *****/
@@ -1843,7 +2012,10 @@ MY_LOCALE my_locale_zh_TW
&my_locale_typelib_day_names_zh_TW,
&my_locale_typelib_ab_day_names_zh_TW,
3,
- 2
+ 2,
+ '.', /* decimal point zh_TW */
+ ',', /* thousands_sep zh_TW */
+ "\x03" /* grouping zh_TW */
);
/***** LOCALE END zh_TW *****/
@@ -1859,7 +2031,10 @@ MY_LOCALE my_locale_ar_DZ
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_DZ */
+ ',', /* thousands_sep ar_DZ */
+ "\x03" /* grouping ar_DZ */
);
/***** LOCALE END ar_DZ *****/
@@ -1875,7 +2050,10 @@ MY_LOCALE my_locale_ar_EG
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_EG */
+ ',', /* thousands_sep ar_EG */
+ "\x03" /* grouping ar_EG */
);
/***** LOCALE END ar_EG *****/
@@ -1891,7 +2069,10 @@ MY_LOCALE my_locale_ar_IN
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_IN */
+ ',', /* thousands_sep ar_IN */
+ "\x03" /* grouping ar_IN */
);
/***** LOCALE END ar_IN *****/
@@ -1907,7 +2088,10 @@ MY_LOCALE my_locale_ar_IQ
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_IQ */
+ ',', /* thousands_sep ar_IQ */
+ "\x03" /* grouping ar_IQ */
);
/***** LOCALE END ar_IQ *****/
@@ -1923,7 +2107,10 @@ MY_LOCALE my_locale_ar_KW
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_KW */
+ ',', /* thousands_sep ar_KW */
+ "\x03" /* grouping ar_KW */
);
/***** LOCALE END ar_KW *****/
@@ -1939,7 +2126,10 @@ MY_LOCALE my_locale_ar_LB
&my_locale_typelib_day_names_ar_JO,
&my_locale_typelib_ab_day_names_ar_JO,
12,
- 8
+ 8,
+ '.', /* decimal point ar_LB */
+ ',', /* thousands_sep ar_LB */
+ "\x03" /* grouping ar_LB */
);
/***** LOCALE END ar_LB *****/
@@ -1955,7 +2145,10 @@ MY_LOCALE my_locale_ar_LY
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_LY */
+ ',', /* thousands_sep ar_LY */
+ "\x03" /* grouping ar_LY */
);
/***** LOCALE END ar_LY *****/
@@ -1971,7 +2164,10 @@ MY_LOCALE my_locale_ar_MA
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_MA */
+ ',', /* thousands_sep ar_MA */
+ "\x03" /* grouping ar_MA */
);
/***** LOCALE END ar_MA *****/
@@ -1987,7 +2183,10 @@ MY_LOCALE my_locale_ar_OM
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_OM */
+ ',', /* thousands_sep ar_OM */
+ "\x03" /* grouping ar_OM */
);
/***** LOCALE END ar_OM *****/
@@ -2003,7 +2202,10 @@ MY_LOCALE my_locale_ar_QA
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_QA */
+ ',', /* thousands_sep ar_QA */
+ "\x03" /* grouping ar_QA */
);
/***** LOCALE END ar_QA *****/
@@ -2019,7 +2221,10 @@ MY_LOCALE my_locale_ar_SD
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_SD */
+ ',', /* thousands_sep ar_SD */
+ "\x03" /* grouping ar_SD */
);
/***** LOCALE END ar_SD *****/
@@ -2035,7 +2240,10 @@ MY_LOCALE my_locale_ar_TN
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_TN */
+ ',', /* thousands_sep ar_TN */
+ "\x03" /* grouping ar_TN */
);
/***** LOCALE END ar_TN *****/
@@ -2051,7 +2259,10 @@ MY_LOCALE my_locale_ar_YE
&my_locale_typelib_day_names_ar_BH,
&my_locale_typelib_ab_day_names_ar_BH,
6,
- 8
+ 8,
+ '.', /* decimal point ar_YE */
+ ',', /* thousands_sep ar_YE */
+ "\x03" /* grouping ar_YE */
);
/***** LOCALE END ar_YE *****/
@@ -2067,7 +2278,10 @@ MY_LOCALE my_locale_de_BE
&my_locale_typelib_day_names_de_DE,
&my_locale_typelib_ab_day_names_de_DE,
9,
- 10
+ 10,
+ ',', /* decimal point de_BE */
+ '.', /* thousands_sep de_BE */
+ "\x03\x03" /* grouping de_BE */
);
/***** LOCALE END de_BE *****/
@@ -2083,7 +2297,10 @@ MY_LOCALE my_locale_de_CH
&my_locale_typelib_day_names_de_DE,
&my_locale_typelib_ab_day_names_de_DE,
9,
- 10
+ 10,
+ '.', /* decimal point de_CH */
+ '\'', /* thousands_sep de_CH */
+ "\x03\x03" /* grouping de_CH */
);
/***** LOCALE END de_CH *****/
@@ -2099,7 +2316,10 @@ MY_LOCALE my_locale_de_LU
&my_locale_typelib_day_names_de_DE,
&my_locale_typelib_ab_day_names_de_DE,
9,
- 10
+ 10,
+ ',', /* decimal point de_LU */
+ '.', /* thousands_sep de_LU */
+ "\x03\x03" /* grouping de_LU */
);
/***** LOCALE END de_LU *****/
@@ -2115,7 +2335,10 @@ MY_LOCALE my_locale_en_AU
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_AU */
+ ',', /* thousands_sep en_AU */
+ "\x03\x03" /* grouping en_AU */
);
/***** LOCALE END en_AU *****/
@@ -2131,7 +2354,10 @@ MY_LOCALE my_locale_en_CA
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_CA */
+ ',', /* thousands_sep en_CA */
+ "\x03\x03" /* grouping en_CA */
);
/***** LOCALE END en_CA *****/
@@ -2147,7 +2373,10 @@ MY_LOCALE my_locale_en_GB
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_GB */
+ ',', /* thousands_sep en_GB */
+ "\x03\x03" /* grouping en_GB */
);
/***** LOCALE END en_GB *****/
@@ -2163,7 +2392,10 @@ MY_LOCALE my_locale_en_IN
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_IN */
+ ',', /* thousands_sep en_IN */
+ "\x03\x02" /* grouping en_IN */
);
/***** LOCALE END en_IN *****/
@@ -2179,7 +2411,10 @@ MY_LOCALE my_locale_en_NZ
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_NZ */
+ ',', /* thousands_sep en_NZ */
+ "\x03\x03" /* grouping en_NZ */
);
/***** LOCALE END en_NZ *****/
@@ -2195,7 +2430,10 @@ MY_LOCALE my_locale_en_PH
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_PH */
+ ',', /* thousands_sep en_PH */
+ "\x03" /* grouping en_PH */
);
/***** LOCALE END en_PH *****/
@@ -2211,7 +2449,10 @@ MY_LOCALE my_locale_en_ZA
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_ZA */
+ ',', /* thousands_sep en_ZA */
+ "\x03\x03" /* grouping en_ZA */
);
/***** LOCALE END en_ZA *****/
@@ -2227,7 +2468,10 @@ MY_LOCALE my_locale_en_ZW
&my_locale_typelib_day_names_en_US,
&my_locale_typelib_ab_day_names_en_US,
9,
- 9
+ 9,
+ '.', /* decimal point en_ZW */
+ ',', /* thousands_sep en_ZW */
+ "\x03\x03" /* grouping en_ZW */
);
/***** LOCALE END en_ZW *****/
@@ -2243,7 +2487,10 @@ MY_LOCALE my_locale_es_AR
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_AR */
+ '.', /* thousands_sep es_AR */
+ "\x03\x03" /* grouping es_AR */
);
/***** LOCALE END es_AR *****/
@@ -2259,7 +2506,10 @@ MY_LOCALE my_locale_es_BO
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_BO */
+ '\0', /* thousands_sep es_BO */
+ "\x80\x80" /* grouping es_BO */
);
/***** LOCALE END es_BO *****/
@@ -2275,7 +2525,10 @@ MY_LOCALE my_locale_es_CL
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_CL */
+ '\0', /* thousands_sep es_CL */
+ "\x80\x80" /* grouping es_CL */
);
/***** LOCALE END es_CL *****/
@@ -2291,7 +2544,10 @@ MY_LOCALE my_locale_es_CO
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_CO */
+ '\0', /* thousands_sep es_CO */
+ "\x80\x80" /* grouping es_CO */
);
/***** LOCALE END es_CO *****/
@@ -2307,7 +2563,10 @@ MY_LOCALE my_locale_es_CR
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_CR */
+ '\0', /* thousands_sep es_CR */
+ "\x80\x80" /* grouping es_CR */
);
/***** LOCALE END es_CR *****/
@@ -2323,7 +2582,10 @@ MY_LOCALE my_locale_es_DO
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_DO */
+ '\0', /* thousands_sep es_DO */
+ "\x80\x80" /* grouping es_DO */
);
/***** LOCALE END es_DO *****/
@@ -2339,7 +2601,10 @@ MY_LOCALE my_locale_es_EC
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_EC */
+ '\0', /* thousands_sep es_EC */
+ "\x80\x80" /* grouping es_EC */
);
/***** LOCALE END es_EC *****/
@@ -2355,7 +2620,10 @@ MY_LOCALE my_locale_es_GT
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_GT */
+ '\0', /* thousands_sep es_GT */
+ "\x80\x80" /* grouping es_GT */
);
/***** LOCALE END es_GT *****/
@@ -2371,7 +2639,10 @@ MY_LOCALE my_locale_es_HN
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_HN */
+ '\0', /* thousands_sep es_HN */
+ "\x80\x80" /* grouping es_HN */
);
/***** LOCALE END es_HN *****/
@@ -2387,7 +2658,10 @@ MY_LOCALE my_locale_es_MX
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_MX */
+ '\0', /* thousands_sep es_MX */
+ "\x80\x80" /* grouping es_MX */
);
/***** LOCALE END es_MX *****/
@@ -2403,7 +2677,10 @@ MY_LOCALE my_locale_es_NI
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_NI */
+ '\0', /* thousands_sep es_NI */
+ "\x80\x80" /* grouping es_NI */
);
/***** LOCALE END es_NI *****/
@@ -2419,7 +2696,10 @@ MY_LOCALE my_locale_es_PA
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_PA */
+ '\0', /* thousands_sep es_PA */
+ "\x80\x80" /* grouping es_PA */
);
/***** LOCALE END es_PA *****/
@@ -2435,7 +2715,10 @@ MY_LOCALE my_locale_es_PE
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_PE */
+ '\0', /* thousands_sep es_PE */
+ "\x80\x80" /* grouping es_PE */
);
/***** LOCALE END es_PE *****/
@@ -2451,7 +2734,10 @@ MY_LOCALE my_locale_es_PR
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_PR */
+ '\0', /* thousands_sep es_PR */
+ "\x80\x80" /* grouping es_PR */
);
/***** LOCALE END es_PR *****/
@@ -2467,7 +2753,10 @@ MY_LOCALE my_locale_es_PY
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_PY */
+ '\0', /* thousands_sep es_PY */
+ "\x80\x80" /* grouping es_PY */
);
/***** LOCALE END es_PY *****/
@@ -2483,7 +2772,10 @@ MY_LOCALE my_locale_es_SV
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_SV */
+ '\0', /* thousands_sep es_SV */
+ "\x80\x80" /* grouping es_SV */
);
/***** LOCALE END es_SV *****/
@@ -2499,7 +2791,10 @@ MY_LOCALE my_locale_es_US
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ '.', /* decimal point es_US */
+ ',', /* thousands_sep es_US */
+ "\x03\x03" /* grouping es_US */
);
/***** LOCALE END es_US *****/
@@ -2515,7 +2810,10 @@ MY_LOCALE my_locale_es_UY
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_UY */
+ '\0', /* thousands_sep es_UY */
+ "\x80\x80" /* grouping es_UY */
);
/***** LOCALE END es_UY *****/
@@ -2531,7 +2829,10 @@ MY_LOCALE my_locale_es_VE
&my_locale_typelib_day_names_es_ES,
&my_locale_typelib_ab_day_names_es_ES,
10,
- 9
+ 9,
+ ',', /* decimal point es_VE */
+ '\0', /* thousands_sep es_VE */
+ "\x80\x80" /* grouping es_VE */
);
/***** LOCALE END es_VE *****/
@@ -2547,7 +2848,10 @@ MY_LOCALE my_locale_fr_BE
&my_locale_typelib_day_names_fr_FR,
&my_locale_typelib_ab_day_names_fr_FR,
9,
- 8
+ 8,
+ ',', /* decimal point fr_BE */
+ '.', /* thousands_sep fr_BE */
+ "\x80\x80" /* grouping fr_BE */
);
/***** LOCALE END fr_BE *****/
@@ -2563,7 +2867,10 @@ MY_LOCALE my_locale_fr_CA
&my_locale_typelib_day_names_fr_FR,
&my_locale_typelib_ab_day_names_fr_FR,
9,
- 8
+ 8,
+ ',', /* decimal point fr_CA */
+ ' ', /* thousands_sep fr_CA */
+ "\x80\x80" /* grouping fr_CA */
);
/***** LOCALE END fr_CA *****/
@@ -2579,7 +2886,10 @@ MY_LOCALE my_locale_fr_CH
&my_locale_typelib_day_names_fr_FR,
&my_locale_typelib_ab_day_names_fr_FR,
9,
- 8
+ 8,
+ ',', /* decimal point fr_CH */
+ '\0', /* thousands_sep fr_CH */
+ "\x80\x80" /* grouping fr_CH */
);
/***** LOCALE END fr_CH *****/
@@ -2595,7 +2905,10 @@ MY_LOCALE my_locale_fr_LU
&my_locale_typelib_day_names_fr_FR,
&my_locale_typelib_ab_day_names_fr_FR,
9,
- 8
+ 8,
+ ',', /* decimal point fr_LU */
+ '\0', /* thousands_sep fr_LU */
+ "\x80\x80" /* grouping fr_LU */
);
/***** LOCALE END fr_LU *****/
@@ -2611,7 +2924,10 @@ MY_LOCALE my_locale_it_IT
&my_locale_typelib_day_names_it_CH,
&my_locale_typelib_ab_day_names_it_CH,
9,
- 9
+ 9,
+ ',', /* decimal point it_IT */
+ '\0', /* thousands_sep it_IT */
+ "\x80\x80" /* grouping it_IT */
);
/***** LOCALE END it_IT *****/
@@ -2627,7 +2943,10 @@ MY_LOCALE my_locale_nl_BE
&my_locale_typelib_day_names_nl_NL,
&my_locale_typelib_ab_day_names_nl_NL,
9,
- 9
+ 9,
+ ',', /* decimal point nl_BE */
+ '.', /* thousands_sep nl_BE */
+ "\x80\x80" /* grouping nl_BE */
);
/***** LOCALE END nl_BE *****/
@@ -2643,7 +2962,10 @@ MY_LOCALE my_locale_no_NO
&my_locale_typelib_day_names_nb_NO,
&my_locale_typelib_ab_day_names_nb_NO,
9,
- 7
+ 7,
+ ',', /* decimal point no_NO */
+ '.', /* thousands_sep no_NO */
+ "\x03\x03" /* grouping no_NO */
);
/***** LOCALE END no_NO *****/
@@ -2659,7 +2981,10 @@ MY_LOCALE my_locale_sv_FI
&my_locale_typelib_day_names_sv_SE,
&my_locale_typelib_ab_day_names_sv_SE,
9,
- 7
+ 7,
+ ',', /* decimal point sv_FI */
+ ' ', /* thousands_sep sv_FI */
+ "\x03\x03" /* grouping sv_FI */
);
/***** LOCALE END sv_FI *****/
@@ -2675,11 +3000,86 @@ MY_LOCALE my_locale_zh_HK
&my_locale_typelib_day_names_zh_CN,
&my_locale_typelib_ab_day_names_zh_CN,
3,
- 3
+ 3,
+ '.', /* decimal point zh_HK */
+ ',', /* thousands_sep zh_HK */
+ "\x03" /* grouping zh_HK */
+
);
/***** LOCALE END zh_HK *****/
+/***** LOCALE BEGIN el_GR: Greek - Greece *****/
+static const char *my_locale_month_names_el_GR[13]=
+{
+ "ΙανουάÏιος", "ΦεβÏουάÏιος", "ΜάÏτιος",
+ "ΑπÏίλιος", "Μάιος", "ΙοÏνιος",
+ "ΙοÏλιος", "ΑÏγουστος", "ΣεπτέμβÏιος",
+ "ΟκτώβÏιος", "ÎοέμβÏιος", "ΔεκέμβÏιος", NullS
+};
+
+static const char *my_locale_ab_month_names_el_GR[13]=
+{
+ "Ιαν", "Φεβ", "ΜάÏ",
+ "ΑπÏ", "Μάι", "ΙοÏν",
+ "ΙοÏλ","ΑÏγ", "Σεπ",
+ "Οκτ", "Îοέ", "Δεκ", NullS
+};
+
+static const char *my_locale_day_names_el_GR[8] =
+{
+ "ΔευτέÏα", "ΤÏίτη", "ΤετάÏτη", "Πέμπτη",
+ "ΠαÏασκευή", "Σάββατο", "ΚυÏιακή", NullS
+};
+
+static const char *my_locale_ab_day_names_el_GR[8]=
+{
+ "Δευ", "ΤÏί", "Τετ", "Πέμ",
+ "ΠαÏ", "Σάβ", "ΚυÏ", NullS
+};
+
+static TYPELIB my_locale_typelib_month_names_el_GR=
+{
+ array_elements(my_locale_month_names_el_GR) - 1,
+ "", my_locale_month_names_el_GR, NULL
+};
+
+static TYPELIB my_locale_typelib_ab_month_names_el_GR=
+{
+ array_elements(my_locale_ab_month_names_el_GR)-1,
+ "", my_locale_ab_month_names_el_GR, NULL
+};
+
+static TYPELIB my_locale_typelib_day_names_el_GR=
+{
+ array_elements(my_locale_day_names_el_GR)-1,
+ "", my_locale_day_names_el_GR, NULL
+};
+
+static TYPELIB my_locale_typelib_ab_day_names_el_GR=
+{
+ array_elements(my_locale_ab_day_names_el_GR) - 1,
+ "", my_locale_ab_day_names_el_GR, NULL
+};
+
+MY_LOCALE my_locale_el_GR
+(
+ 109,
+ "el_GR",
+ "Greek - Greece",
+ FALSE,
+ &my_locale_typelib_month_names_el_GR,
+ &my_locale_typelib_ab_month_names_el_GR,
+ &my_locale_typelib_day_names_el_GR,
+ &my_locale_typelib_ab_day_names_el_GR,
+ 11, /* max mon name length */
+ 9, /* max day name length */
+ ',', /* decimal point el_GR */
+ '.', /* thousands_sep el_GR */
+ "\x80" /* grouping el_GR */
+);
+/***** LOCALE END el_GR *****/
+
/*
The list of all locales.
Note, locales must be ordered according to their
@@ -2797,6 +3197,7 @@ MY_LOCALE *my_locales[]=
&my_locale_no_NO,
&my_locale_sv_FI,
&my_locale_zh_HK,
+ &my_locale_el_GR,
NULL
};
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 455b2727056..5a4af9afbb1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -305,8 +305,8 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_AUTHORS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CONTRIBUTORS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PRIVILEGES]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND | CF_DIAGNOSTIC_STMT;
+ sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND | CF_DIAGNOSTIC_STMT;
sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_ENGINE_MUTEX]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_ENGINE_LOGS]= CF_STATUS_COMMAND;
@@ -801,7 +801,7 @@ bool do_command(THD *thd)
Consider moving to init_connect() instead.
*/
thd->clear_error(); // Clear error message
- thd->main_da.reset_diagnostics_area();
+ thd->stmt_da->reset_diagnostics_area();
net_new_transaction(net);
@@ -1064,7 +1064,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
tbl_name= strmake(db.str, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len);
if (mysql_table_dump(thd, &db, tbl_name) == 0)
- thd->main_da.disable_status();
+ thd->stmt_da->disable_status();
break;
}
case COM_CHANGE_USER:
@@ -1359,7 +1359,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* We don't calculate statistics for this command */
general_log_print(thd, command, NullS);
net->error=0; // Don't give 'abort' message
- thd->main_da.disable_status(); // Don't send anything back
+ thd->stmt_da->disable_status(); // Don't send anything back
error=TRUE; // End server
break;
@@ -1527,7 +1527,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#ifndef EMBEDDED_LIBRARY
VOID(my_net_write(net, (uchar*) buff, length));
VOID(net_flush(net));
- thd->main_da.disable_status();
+ thd->stmt_da->disable_status();
#endif
break;
}
@@ -1593,7 +1593,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* report error issued during command execution */
if (thd->killed_errno())
{
- if (! thd->main_da.is_set())
+ if (! thd->stmt_da->is_set())
thd->send_kill_message();
}
if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
@@ -1603,9 +1603,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
/* If commit fails, we should be able to reset the OK status. */
- thd->main_da.can_overwrite_status= TRUE;
+ thd->stmt_da->can_overwrite_status= TRUE;
ha_autocommit_or_rollback(thd, thd->is_error());
- thd->main_da.can_overwrite_status= FALSE;
+ thd->stmt_da->can_overwrite_status= FALSE;
thd->transaction.stmt.reset();
@@ -2046,8 +2046,14 @@ mysql_execute_command(THD *thd)
variables, but for now this is probably good enough.
Don't reset warnings when executing a stored routine.
*/
- if ((all_tables || !lex->is_single_level_stmt()) && !thd->spcont)
- mysql_reset_errors(thd, 0);
+ if ((sql_command_flags[lex->sql_command] & CF_DIAGNOSTIC_STMT) != 0)
+ thd->warning_info->set_read_only(TRUE);
+ else
+ {
+ thd->warning_info->set_read_only(FALSE);
+ if (all_tables)
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
+ }
#ifdef HAVE_REPLICATION
if (unlikely(thd->slave_thread))
@@ -4424,12 +4430,6 @@ create_sp_error:
So just execute the statement.
*/
res= sp->execute_procedure(thd, &lex->value_list);
- /*
- If warnings have been cleared, we have to clear total_warn_count
- too, otherwise the clients get confused.
- */
- if (thd->warn_list.is_empty())
- thd->total_warn_count= 0;
thd->variables.select_limit= select_limit;
@@ -4460,7 +4460,7 @@ create_sp_error:
else
sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
&thd->sp_func_cache, FALSE);
- mysql_reset_errors(thd, 0);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
if (! sp)
{
if (lex->spname->m_db.str)
@@ -4535,7 +4535,7 @@ create_sp_error:
TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION);
sp_result= sp_routine_exists_in_table(thd, type, lex->spname);
- mysql_reset_errors(thd, 0);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
if (sp_result == SP_OK)
{
char *db= lex->spname->m_db.str;
@@ -4986,6 +4986,11 @@ create_sp_error:
my_ok(thd, 1);
break;
}
+ case SQLCOM_SIGNAL:
+ case SQLCOM_RESIGNAL:
+ DBUG_ASSERT(lex->m_stmt != NULL);
+ res= lex->m_stmt->execute(thd);
+ break;
default:
#ifndef EMBEDDED_LIBRARY
DBUG_ASSERT(0); /* Impossible */
@@ -5735,8 +5740,8 @@ void mysql_reset_thd_for_next_command(THD *thd)
thd->user_var_events_alloc= thd->mem_root;
}
thd->clear_error();
- thd->main_da.reset_diagnostics_area();
- thd->total_warn_count=0; // Warnings for this query
+ thd->stmt_da->reset_diagnostics_area();
+ thd->warning_info->reset_for_next_command();
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 08ff2daacb9..a67ed1cf3af 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -4185,13 +4185,15 @@ uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
/*
Mark the partition.
I.e mark the partition as a partition to be "changed" by
- analyzing/optimizing/rebuilding/checking/repairing
+ analyzing/optimizing/rebuilding/checking/repairing/...
*/
no_parts_found++;
part_elem->part_state= part_state;
DBUG_PRINT("info", ("Setting part_state to %u for partition %s",
part_state, part_elem->partition_name));
}
+ else
+ part_elem->part_state= PART_NORMAL;
} while (++part_count < tab_part_info->no_parts);
return no_parts_found;
}
@@ -6848,7 +6850,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
/* See get_part_iter_for_interval_via_walking for definition of what this is */
-#define MAX_RANGE_TO_WALK 10
+#define MAX_RANGE_TO_WALK 32
/*
@@ -6884,16 +6886,6 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
Intervals with +inf/-inf, and [NULL, c1] interval can be processed but
that is more tricky and I don't have time to do it right now.
- Additionally we have these requirements:
- * number of values in the interval must be less then number of
- [sub]partitions, and
- * Number of values in the interval must be less then MAX_RANGE_TO_WALK.
-
- The rationale behind these requirements is that if they are not met
- we're likely to hit most of the partitions and traversing the interval
- will only add overhead. So it's better return "all partitions used" in
- that case.
-
RETURN
0 - No matching partitions, iterator not initialized
1 - Some partitions would match, iterator intialized for traversing them
@@ -6987,8 +6979,24 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
a += test(flags & NEAR_MIN);
b += test(!(flags & NEAR_MAX));
ulonglong n_values= b - a;
-
- if (n_values > total_parts || n_values > MAX_RANGE_TO_WALK)
+
+ /*
+ Will it pay off to enumerate all values in the [a..b] range and evaluate
+ the partitioning function for every value? It depends on
+ 1. whether we'll be able to infer that some partitions are not used
+ 2. if time savings from not scanning these partitions will be greater
+ than time spent in enumeration.
+ We will assume that the cost of accessing one extra partition is greater
+ than the cost of evaluating the partitioning function O(#partitions).
+ This means we should jump at any chance to eliminate a partition, which
+ gives us this logic:
+
+ Do the enumeration if
+ - the number of values to enumerate is comparable to the number of
+ partitions, or
+ - there are not many values to enumerate.
+ */
+ if ((n_values > 2*total_parts) && n_values > MAX_RANGE_TO_WALK)
return -1;
part_iter->field_vals.start= part_iter->field_vals.cur= a;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 350b5fdd38c..75a0c538e04 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -250,7 +250,7 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
int2store(buff+5, columns);
int2store(buff+7, stmt->param_count);
buff[9]= 0; // Guard against a 4.1 client
- tmp= min(stmt->thd->total_warn_count, 65535);
+ tmp= min(stmt->thd->warning_info->statement_warn_count(), 65535);
int2store(buff+10, tmp);
/*
@@ -265,7 +265,7 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
Protocol::SEND_EOF);
}
/* Flag that a response has already been sent */
- thd->main_da.disable_status();
+ thd->stmt_da->disable_status();
DBUG_RETURN(error);
}
#else
@@ -277,7 +277,7 @@ static bool send_prep_stmt(Prepared_statement *stmt,
thd->client_stmt_id= stmt->id;
thd->client_param_count= stmt->param_count;
thd->clear_error();
- thd->main_da.disable_status();
+ thd->stmt_da->disable_status();
return 0;
}
@@ -1835,6 +1835,10 @@ static bool check_prepared_statement(Prepared_statement *stmt)
lex->select_lex.context.resolve_in_table_list_only(select_lex->
get_table_list());
+ /* Reset warning count for each query that uses tables */
+ if (tables)
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
+
switch (sql_command) {
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
@@ -2082,8 +2086,6 @@ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length)
DBUG_VOID_RETURN;
}
- /* Reset warnings from previous command */
- mysql_reset_errors(thd, 0);
sp_cache_flush_obsolete(&thd->sp_proc_cache);
sp_cache_flush_obsolete(&thd->sp_func_cache);
@@ -2656,7 +2658,7 @@ void mysqld_stmt_close(THD *thd, char *packet)
Prepared_statement *stmt;
DBUG_ENTER("mysqld_stmt_close");
- thd->main_da.disable_status();
+ thd->stmt_da->disable_status();
if (!(stmt= find_prepared_statement(thd, stmt_id)))
DBUG_VOID_RETURN;
@@ -2731,7 +2733,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
status_var_increment(thd->status_var.com_stmt_send_long_data);
- thd->main_da.disable_status();
+ thd->stmt_da->disable_status();
#ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */
if (packet_length < MYSQL_LONG_DATA_HEADER)
@@ -2822,6 +2824,30 @@ Select_fetch_protocol_binary::send_data(List<Item> &fields)
return rc;
}
+/*******************************************************************
+* Reprepare_observer
+*******************************************************************/
+/** Push an error to the error stack and return TRUE for now. */
+
+bool
+Reprepare_observer::report_error(THD *thd)
+{
+ /*
+ This 'error' is purely internal to the server:
+ - No exception handler is invoked,
+ - No condition is added in the condition area (warn_list).
+ The diagnostics area is set to an error status to enforce
+ that this thread execution stops and returns to the caller,
+ backtracking all the way to Prepared_statement::execute_loop().
+ */
+ thd->stmt_da->set_error_status(thd, ER_NEED_REPREPARE,
+ ER(ER_NEED_REPREPARE), "HY000");
+ m_invalidated= TRUE;
+
+ return TRUE;
+}
+
+
/***************************************************************************
Prepared_statement
****************************************************************************/
@@ -3262,7 +3288,7 @@ reexecute:
reprepare_observer.is_invalidated() &&
reprepare_attempt++ < MAX_REPREPARE_ATTEMPTS)
{
- DBUG_ASSERT(thd->main_da.sql_errno() == ER_NEED_REPREPARE);
+ DBUG_ASSERT(thd->stmt_da->sql_errno() == ER_NEED_REPREPARE);
thd->clear_error();
error= reprepare();
@@ -3325,12 +3351,12 @@ Prepared_statement::reprepare()
#endif
/*
Clear possible warnings during reprepare, it has to be completely
- transparent to the user. We use mysql_reset_errors() since
+ transparent to the user. We use clear_warning_info() since
there were no separate query id issued for re-prepare.
Sic: we can't simply silence warnings during reprepare, because if
it's failed, we need to return all the warnings to the user.
*/
- mysql_reset_errors(thd, TRUE);
+ thd->warning_info->clear_warning_info(thd->query_id);
}
return error;
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 0ec8d91214c..b6ae8860cf5 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -796,7 +796,7 @@ err:
@param mi Pointer to Master_info object for the slave's IO thread.
- @param net_report If true, saves the exit status into thd->main_da.
+ @param net_report If true, saves the exit status into thd->stmt_da.
@retval 0 success
@retval 1 error
@@ -934,7 +934,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report)
@param mi Pointer to Master_info object for the slave's IO thread.
- @param net_report If true, saves the exit status into thd->main_da.
+ @param net_report If true, saves the exit status into thd->stmt_da.
@retval 0 success
@retval 1 error
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a82137222e5..3e2d85e4951 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -222,6 +222,7 @@ static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
+static bool prepare_sum_aggregators(Item_sum **func_ptr, bool need_distinct);
static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
@@ -1232,7 +1233,11 @@ JOIN::optimize()
if (test_if_subpart(group_list, order) ||
(!group_list && tmp_table_param.sum_func_count))
+ {
order=0;
+ if (is_indexed_agg_distinct(this, NULL))
+ sort_and_group= 0;
+ }
// Can't use sort on head table if using row cache
if (full_join)
@@ -1410,8 +1415,16 @@ JOIN::optimize()
single table queries, thus it is sufficient to test only the first
join_tab element of the plan for its access method.
*/
+ bool need_distinct= TRUE;
if (join_tab->is_using_loose_index_scan())
+ {
tmp_table_param.precomputed_group_by= TRUE;
+ if (join_tab->is_using_agg_loose_index_scan())
+ {
+ need_distinct= FALSE;
+ tmp_table_param.precomputed_group_by= FALSE;
+ }
+ }
/* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp)
@@ -1472,6 +1485,7 @@ JOIN::optimize()
HA_POS_ERROR, HA_POS_ERROR, FALSE) ||
alloc_group_fields(this, group_list) ||
make_sum_func_list(all_fields, fields_list, 1) ||
+ prepare_sum_aggregators(sum_funcs, need_distinct) ||
setup_sum_funcs(thd, sum_funcs))
{
DBUG_RETURN(1);
@@ -1481,6 +1495,7 @@ JOIN::optimize()
else
{
if (make_sum_func_list(all_fields, fields_list, 0) ||
+ prepare_sum_aggregators(sum_funcs, need_distinct) ||
setup_sum_funcs(thd, sum_funcs))
{
DBUG_RETURN(1);
@@ -1953,7 +1968,9 @@ JOIN::exec()
}
}
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
- 1, TRUE))
+ 1, TRUE) ||
+ prepare_sum_aggregators(curr_join->sum_funcs,
+ !curr_join->join_tab->is_using_agg_loose_index_scan()))
DBUG_VOID_RETURN;
curr_join->group_list= 0;
if (!curr_join->sort_and_group &&
@@ -2056,6 +2073,8 @@ JOIN::exec()
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1, TRUE) ||
+ prepare_sum_aggregators (curr_join->sum_funcs, !curr_join->join_tab ||
+ !curr_join->join_tab->is_using_agg_loose_index_scan()) ||
setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
thd->is_fatal_error)
DBUG_VOID_RETURN;
@@ -3938,6 +3957,82 @@ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
/**
+ Check for the presence of AGGFN(DISTINCT a) queries that may be subject
+ to loose index scan.
+
+
+ Check if the query is a subject to AGGFN(DISTINCT) using loose index scan
+ (QUICK_GROUP_MIN_MAX_SELECT).
+ Optionally (if out_args is supplied) will push the arguments of
+ AGGFN(DISTINCT) to the list
+
+ @param join the join to check
+ @param[out] out_args list of aggregate function arguments
+ @return does the query qualify for indexed AGGFN(DISTINCT)
+ @retval true it does
+ @retval false AGGFN(DISTINCT) must apply distinct in it.
+*/
+
+bool
+is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args)
+{
+ Item_sum **sum_item_ptr;
+ bool result= false;
+
+ if (join->tables != 1 || /* reference more than 1 table */
+ join->select_distinct || /* or a DISTINCT */
+ join->select_lex->olap == ROLLUP_TYPE) /* Check (B3) for ROLLUP */
+ return false;
+
+ if (join->make_sum_func_list(join->all_fields, join->fields_list, 1))
+ return false;
+
+ for (sum_item_ptr= join->sum_funcs; *sum_item_ptr; sum_item_ptr++)
+ {
+ Item_sum *sum_item= *sum_item_ptr;
+ Item *expr;
+ /* aggregate is not AGGFN(DISTINCT) or more than 1 argument to it */
+ switch (sum_item->sum_func())
+ {
+ case Item_sum::MIN_FUNC:
+ case Item_sum::MAX_FUNC:
+ continue;
+ case Item_sum::COUNT_DISTINCT_FUNC:
+ break;
+ case Item_sum::AVG_DISTINCT_FUNC:
+ case Item_sum::SUM_DISTINCT_FUNC:
+ if (sum_item->get_arg_count() == 1)
+ break;
+ /* fall through */
+ default: return false;
+ }
+ /*
+ We arrive here for every COUNT(DISTINCT),AVG(DISTINCT) or SUM(DISTINCT).
+ Collect the arguments of the aggregate functions to a list.
+ We don't worry about duplicates as these will be sorted out later in
+ get_best_group_min_max
+ */
+ for (uint i= 0; i < sum_item->get_arg_count(); i++)
+ {
+ expr= sum_item->get_arg(i);
+ /* The AGGFN(DISTINCT) arg is not an attribute? */
+ if (expr->real_item()->type() != Item::FIELD_ITEM)
+ return false;
+
+ /*
+ If we came to this point the AGGFN(DISTINCT) loose index scan
+ optimization is applicable
+ */
+ if (out_args)
+ out_args->push_back((Item_field *) expr);
+ result= true;
+ }
+ }
+ return result;
+}
+
+
+/**
Discover the indexes that can be used for GROUP BY or DISTINCT queries.
If the query has a GROUP BY clause, find all indexes that contain all
@@ -3979,6 +4074,10 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
item->walk(&Item::collect_item_field_processor, 0,
(uchar*) &indexed_fields);
}
+ else if (is_indexed_agg_distinct(join, &indexed_fields))
+ {
+ join->sort_and_group= 1;
+ }
else
return;
@@ -10377,6 +10476,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
bzero(share, sizeof(*share));
table->field= field;
table->s= share;
+ table->temp_pool_slot= MY_BIT_NONE;
share->blob_field= blob_field;
share->fields= field_count;
share->blob_ptr_size= portable_sizeof_char_ptr;
@@ -10874,7 +10974,6 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
so we don't touch it here.
*/
join->examined_rows++;
- join->thd->row_count++;
DBUG_ASSERT(join->examined_rows <= 1);
}
else if (join->send_row_on_empty_set())
@@ -11128,7 +11227,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
/* Set first_unmatched for the last inner table of this group */
join_tab->last_inner->first_unmatched= join_tab;
}
- join->thd->row_count= 0;
+ join->thd->warning_info->reset_current_row_for_warning();
error= (*join_tab->read_first_record)(join_tab);
rc= evaluate_join_record(join, join_tab, error);
@@ -11238,7 +11337,6 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
(See above join->return_tab= tab).
*/
join->examined_rows++;
- join->thd->row_count++;
DBUG_PRINT("counts", ("join->examined_rows++: %lu",
(ulong) join->examined_rows));
@@ -11247,6 +11345,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
enum enum_nested_loop_state rc;
/* A match from join_tab is found for the current partial join. */
rc= (*join_tab->next_select)(join, join_tab+1, 0);
+ join->thd->warning_info->inc_current_row_for_warning();
if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
return rc;
if (join->return_tab < join_tab)
@@ -11260,7 +11359,10 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
return NESTED_LOOP_NO_MORE_ROWS;
}
else
+ {
+ join->thd->warning_info->inc_current_row_for_warning();
join_tab->read_record.file->unlock_row();
+ }
}
else
{
@@ -11269,7 +11371,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
with the beginning coinciding with the current partial join.
*/
join->examined_rows++;
- join->thd->row_count++;
+ join->thd->warning_info->inc_current_row_for_warning();
join_tab->read_record.file->unlock_row();
}
return NESTED_LOOP_OK;
@@ -14530,7 +14632,7 @@ setup_new_fields(THD *thd, List<Item> &fields,
optimize away 'order by'.
*/
-static ORDER *
+ORDER *
create_distinct_group(THD *thd, Item **ref_pointer_array,
ORDER *order_list, List<Item> &fields,
List<Item> &all_fields,
@@ -15332,7 +15434,22 @@ static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
DBUG_ENTER("setup_sum_funcs");
while ((func= *(func_ptr++)))
{
- if (func->setup(thd))
+ if (func->aggregator_setup(thd))
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+static bool prepare_sum_aggregators(Item_sum **func_ptr, bool need_distinct)
+{
+ Item_sum *func;
+ DBUG_ENTER("setup_sum_funcs");
+ while ((func= *(func_ptr++)))
+ {
+ if (func->set_aggregator(need_distinct && func->with_distinct ?
+ Aggregator::DISTINCT_AGGREGATOR :
+ Aggregator::SIMPLE_AGGREGATOR))
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
@@ -15382,7 +15499,7 @@ init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
/* If rollup, calculate the upper sum levels */
for ( ; *func_ptr ; func_ptr++)
{
- if ((*func_ptr)->add())
+ if ((*func_ptr)->aggregator_add())
return 1;
}
return 0;
@@ -15394,7 +15511,7 @@ update_sum_func(Item_sum **func_ptr)
{
Item_sum *func;
for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
- if (func->add())
+ if (func->aggregator_add())
return 1;
return 0;
}
@@ -16311,7 +16428,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (key_read)
{
if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
+ {
+ QUICK_GROUP_MIN_MAX_SELECT *qgs=
+ (QUICK_GROUP_MIN_MAX_SELECT *) tab->select->quick;
extra.append(STRING_WITH_LEN("; Using index for group-by"));
+ qgs->append_loose_scan_type(&extra);
+ }
else
extra.append(STRING_WITH_LEN("; Using index"));
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index a0366d47149..bb751c600ed 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -218,6 +218,11 @@ typedef struct st_join_table {
(select->quick->get_type() ==
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX));
}
+ bool is_using_agg_loose_index_scan ()
+ {
+ return (is_using_loose_index_scan() &&
+ ((QUICK_GROUP_MIN_MAX_SELECT *)select->quick)->is_agg_distinct());
+ }
} JOIN_TAB;
enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool
@@ -564,6 +569,8 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field,
const char *name, TABLE *table,
Item_field *item, uint convert_blob_length);
+bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
+
/* functions from opt_sum.cc */
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds);
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index f8a8dea18ff..33058887952 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -242,7 +242,7 @@ bool servers_reload(THD *thd)
if (simple_open_n_lock_tables(thd, tables))
{
sql_print_error("Can't open and lock privilege tables: %s",
- thd->main_da.message());
+ thd->stmt_da->message());
goto end;
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 5c2c351652b..b16f050dea6 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -598,7 +598,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
if (open_normal_and_derived_tables(thd, table_list, 0))
{
if (!table_list->view ||
- (thd->is_error() && thd->main_da.sql_errno() != ER_VIEW_INVALID))
+ (thd->is_error() && thd->stmt_da->sql_errno() != ER_VIEW_INVALID))
DBUG_RETURN(TRUE);
/*
@@ -606,7 +606,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
issue a warning with 'warning' level status in
case of invalid view and last error is ER_VIEW_INVALID
*/
- mysql_reset_errors(thd, true);
+ thd->warning_info->clear_warning_info(thd->query_id);
thd->clear_error();
push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -2986,7 +2986,7 @@ static int fill_schema_table_names(THD *thd, TABLE *table,
default:
DBUG_ASSERT(0);
}
- if (thd->is_error() && thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
+ if (thd->is_error() && thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE)
{
thd->clear_error();
return 0;
@@ -3350,10 +3350,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
can return an error without setting an error message
in THD, which is a hack. This is why we have to
check for res, then for thd->is_error() only then
- for thd->main_da.sql_errno().
+ for thd->stmt_da->sql_errno().
*/
if (res && thd->is_error() &&
- thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
+ thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE)
{
/*
Hide error for not existing table.
@@ -3507,7 +3507,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
/*
there was errors during opening tables
*/
- const char *error= thd->is_error() ? thd->main_da.message() : "";
+ const char *error= thd->is_error() ? thd->stmt_da->message() : "";
if (tables->view)
table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
else if (tables->schema_table)
@@ -3711,7 +3711,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
*/
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- thd->main_da.sql_errno(), thd->main_da.message());
+ thd->stmt_da->sql_errno(), thd->stmt_da->message());
thd->clear_error();
res= 0;
}
@@ -4223,7 +4223,7 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
*/
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- thd->main_da.sql_errno(), thd->main_da.message());
+ thd->stmt_da->sql_errno(), thd->stmt_da->message());
thd->clear_error();
res= 0;
}
@@ -4436,7 +4436,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
DBUG_RETURN(1);
if (res && thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- thd->main_da.sql_errno(), thd->main_da.message());
+ thd->stmt_da->sql_errno(), thd->stmt_da->message());
}
if (res)
thd->clear_error();
@@ -4469,7 +4469,7 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
{
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- thd->main_da.sql_errno(), thd->main_da.message());
+ thd->stmt_da->sql_errno(), thd->stmt_da->message());
thd->clear_error();
DBUG_RETURN(0);
}
@@ -4574,7 +4574,7 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
{
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- thd->main_da.sql_errno(), thd->main_da.message());
+ thd->stmt_da->sql_errno(), thd->stmt_da->message());
thd->clear_error();
DBUG_RETURN(0);
}
@@ -4653,7 +4653,7 @@ static int get_schema_key_column_usage_record(THD *thd,
{
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- thd->main_da.sql_errno(), thd->main_da.message());
+ thd->stmt_da->sql_errno(), thd->stmt_da->message());
thd->clear_error();
DBUG_RETURN(0);
}
@@ -4848,7 +4848,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
{
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- thd->main_da.sql_errno(), thd->main_da.message());
+ thd->stmt_da->sql_errno(), thd->stmt_da->message());
thd->clear_error();
DBUG_RETURN(0);
}
@@ -5386,7 +5386,7 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
{
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- thd->main_da.sql_errno(), thd->main_da.message());
+ thd->stmt_da->sql_errno(), thd->stmt_da->message());
thd->clear_error();
DBUG_RETURN(0);
}
diff --git a/sql/sql_signal.cc b/sql/sql_signal.cc
new file mode 100644
index 00000000000..c9ab37272b8
--- /dev/null
+++ b/sql/sql_signal.cc
@@ -0,0 +1,510 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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 "mysql_priv.h"
+#include "sp_head.h"
+#include "sp_pcontext.h"
+#include "sp_rcontext.h"
+#include "sql_signal.h"
+
+/*
+ The parser accepts any error code (desired)
+ The runtime internally supports any error code (desired)
+ The client server protocol is limited to 16 bits error codes (restriction)
+ Enforcing the 65535 limit in the runtime until the protocol can change.
+*/
+#define MAX_MYSQL_ERRNO UINT_MAX16
+
+const LEX_STRING Diag_condition_item_names[]=
+{
+ { C_STRING_WITH_LEN("CLASS_ORIGIN") },
+ { C_STRING_WITH_LEN("SUBCLASS_ORIGIN") },
+ { C_STRING_WITH_LEN("CONSTRAINT_CATALOG") },
+ { C_STRING_WITH_LEN("CONSTRAINT_SCHEMA") },
+ { C_STRING_WITH_LEN("CONSTRAINT_NAME") },
+ { C_STRING_WITH_LEN("CATALOG_NAME") },
+ { C_STRING_WITH_LEN("SCHEMA_NAME") },
+ { C_STRING_WITH_LEN("TABLE_NAME") },
+ { C_STRING_WITH_LEN("COLUMN_NAME") },
+ { C_STRING_WITH_LEN("CURSOR_NAME") },
+ { C_STRING_WITH_LEN("MESSAGE_TEXT") },
+ { C_STRING_WITH_LEN("MYSQL_ERRNO") },
+
+ { C_STRING_WITH_LEN("CONDITION_IDENTIFIER") },
+ { C_STRING_WITH_LEN("CONDITION_NUMBER") },
+ { C_STRING_WITH_LEN("CONNECTION_NAME") },
+ { C_STRING_WITH_LEN("MESSAGE_LENGTH") },
+ { C_STRING_WITH_LEN("MESSAGE_OCTET_LENGTH") },
+ { C_STRING_WITH_LEN("PARAMETER_MODE") },
+ { C_STRING_WITH_LEN("PARAMETER_NAME") },
+ { C_STRING_WITH_LEN("PARAMETER_ORDINAL_POSITION") },
+ { C_STRING_WITH_LEN("RETURNED_SQLSTATE") },
+ { C_STRING_WITH_LEN("ROUTINE_CATALOG") },
+ { C_STRING_WITH_LEN("ROUTINE_NAME") },
+ { C_STRING_WITH_LEN("ROUTINE_SCHEMA") },
+ { C_STRING_WITH_LEN("SERVER_NAME") },
+ { C_STRING_WITH_LEN("SPECIFIC_NAME") },
+ { C_STRING_WITH_LEN("TRIGGER_CATALOG") },
+ { C_STRING_WITH_LEN("TRIGGER_NAME") },
+ { C_STRING_WITH_LEN("TRIGGER_SCHEMA") }
+};
+
+const LEX_STRING Diag_statement_item_names[]=
+{
+ { C_STRING_WITH_LEN("NUMBER") },
+ { C_STRING_WITH_LEN("MORE") },
+ { C_STRING_WITH_LEN("COMMAND_FUNCTION") },
+ { C_STRING_WITH_LEN("COMMAND_FUNCTION_CODE") },
+ { C_STRING_WITH_LEN("DYNAMIC_FUNCTION") },
+ { C_STRING_WITH_LEN("DYNAMIC_FUNCTION_CODE") },
+ { C_STRING_WITH_LEN("ROW_COUNT") },
+ { C_STRING_WITH_LEN("TRANSACTIONS_COMMITTED") },
+ { C_STRING_WITH_LEN("TRANSACTIONS_ROLLED_BACK") },
+ { C_STRING_WITH_LEN("TRANSACTION_ACTIVE") }
+};
+
+Set_signal_information::Set_signal_information()
+{
+ clear();
+}
+
+Set_signal_information::Set_signal_information(
+ const Set_signal_information& set)
+{
+ memcpy(m_item, set.m_item, sizeof(m_item));
+}
+
+void Set_signal_information::clear()
+{
+ memset(m_item, 0, sizeof(m_item));
+}
+
+void Signal_common::assign_defaults(MYSQL_ERROR *cond,
+ bool set_level_code,
+ MYSQL_ERROR::enum_warning_level level,
+ int sqlcode)
+{
+ if (set_level_code)
+ {
+ cond->m_level= level;
+ cond->m_sql_errno= sqlcode;
+ }
+ if (! cond->get_message_text())
+ cond->set_builtin_message_text(ER(sqlcode));
+}
+
+void Signal_common::eval_defaults(THD *thd, MYSQL_ERROR *cond)
+{
+ DBUG_ASSERT(cond);
+
+ const char* sqlstate;
+ bool set_defaults= (m_cond != 0);
+
+ if (set_defaults)
+ {
+ /*
+ SIGNAL is restricted in sql_yacc.yy to only signal SQLSTATE conditions.
+ */
+ DBUG_ASSERT(m_cond->type == sp_cond_type::state);
+ sqlstate= m_cond->sqlstate;
+ cond->set_sqlstate(sqlstate);
+ }
+ else
+ sqlstate= cond->get_sqlstate();
+
+ DBUG_ASSERT(sqlstate);
+ /* SQLSTATE class "00": illegal, rejected in the parser. */
+ DBUG_ASSERT((sqlstate[0] != '0') || (sqlstate[1] != '0'));
+
+ if ((sqlstate[0] == '0') && (sqlstate[1] == '1'))
+ {
+ /* SQLSTATE class "01": warning. */
+ assign_defaults(cond, set_defaults,
+ MYSQL_ERROR::WARN_LEVEL_WARN, ER_SIGNAL_WARN);
+ }
+ else if ((sqlstate[0] == '0') && (sqlstate[1] == '2'))
+ {
+ /* SQLSTATE class "02": not found. */
+ assign_defaults(cond, set_defaults,
+ MYSQL_ERROR::WARN_LEVEL_ERROR, ER_SIGNAL_NOT_FOUND);
+ }
+ else
+ {
+ /* other SQLSTATE classes : error. */
+ assign_defaults(cond, set_defaults,
+ MYSQL_ERROR::WARN_LEVEL_ERROR, ER_SIGNAL_EXCEPTION);
+ }
+}
+
+static bool assign_fixed_string(MEM_ROOT *mem_root,
+ CHARSET_INFO *dst_cs,
+ size_t max_char,
+ String *dst,
+ const String* src)
+{
+ bool truncated;
+ size_t numchars;
+ CHARSET_INFO *src_cs;
+ const char* src_str;
+ const char* src_end;
+ size_t src_len;
+ size_t to_copy;
+ char* dst_str;
+ size_t dst_len;
+ size_t dst_copied;
+ uint32 dummy_offset;
+
+ src_str= src->ptr();
+ if (src_str == NULL)
+ {
+ dst->set((const char*) NULL, 0, dst_cs);
+ return false;
+ }
+
+ src_cs= src->charset();
+ src_len= src->length();
+ src_end= src_str + src_len;
+ numchars= src_cs->cset->numchars(src_cs, src_str, src_end);
+
+ if (numchars <= max_char)
+ {
+ to_copy= src->length();
+ truncated= false;
+ }
+ else
+ {
+ numchars= max_char;
+ to_copy= dst_cs->cset->charpos(dst_cs, src_str, src_end, numchars);
+ truncated= true;
+ }
+
+ if (String::needs_conversion(to_copy, src_cs, dst_cs, & dummy_offset))
+ {
+ dst_len= numchars * dst_cs->mbmaxlen;
+ dst_str= (char*) alloc_root(mem_root, dst_len + 1);
+ if (dst_str)
+ {
+ const char* well_formed_error_pos;
+ const char* cannot_convert_error_pos;
+ const char* from_end_pos;
+
+ dst_copied= well_formed_copy_nchars(dst_cs, dst_str, dst_len,
+ src_cs, src_str, src_len,
+ numchars,
+ & well_formed_error_pos,
+ & cannot_convert_error_pos,
+ & from_end_pos);
+ DBUG_ASSERT(dst_copied <= dst_len);
+ dst_len= dst_copied; /* In case the copy truncated the data */
+ dst_str[dst_copied]= '\0';
+ }
+ }
+ else
+ {
+ dst_len= to_copy;
+ dst_str= (char*) alloc_root(mem_root, dst_len + 1);
+ if (dst_str)
+ {
+ memcpy(dst_str, src_str, to_copy);
+ dst_str[to_copy]= '\0';
+ }
+ }
+ dst->set(dst_str, dst_len, dst_cs);
+
+ return truncated;
+}
+
+static int assign_condition_item(MEM_ROOT *mem_root, const char* name, THD *thd,
+ Item *set, String *ci)
+{
+ char str_buff[(64+1)*4]; /* Room for a null terminated UTF8 String 64 */
+ String str_value(str_buff, sizeof(str_buff), & my_charset_utf8_bin);
+ String *str;
+ bool truncated;
+
+ DBUG_ENTER("assign_condition_item");
+
+ if (set->is_null())
+ {
+ thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR, name, "NULL");
+ DBUG_RETURN(1);
+ }
+
+ str= set->val_str(& str_value);
+ truncated= assign_fixed_string(mem_root, & my_charset_utf8_bin, 64, ci, str);
+ if (truncated)
+ {
+ if (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES))
+ {
+ thd->raise_error_printf(ER_COND_ITEM_TOO_LONG, name);
+ DBUG_RETURN(1);
+ }
+
+ thd->raise_warning_printf(WARN_COND_ITEM_TRUNCATED, name);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+int Signal_common::eval_signal_informations(THD *thd, MYSQL_ERROR *cond)
+{
+ struct cond_item_map
+ {
+ enum enum_diag_condition_item_name m_item;
+ String MYSQL_ERROR::*m_member;
+ };
+
+ static cond_item_map map[]=
+ {
+ { DIAG_CLASS_ORIGIN, & MYSQL_ERROR::m_class_origin },
+ { DIAG_SUBCLASS_ORIGIN, & MYSQL_ERROR::m_subclass_origin },
+ { DIAG_CONSTRAINT_CATALOG, & MYSQL_ERROR::m_constraint_catalog },
+ { DIAG_CONSTRAINT_SCHEMA, & MYSQL_ERROR::m_constraint_schema },
+ { DIAG_CONSTRAINT_NAME, & MYSQL_ERROR::m_constraint_name },
+ { DIAG_CATALOG_NAME, & MYSQL_ERROR::m_catalog_name },
+ { DIAG_SCHEMA_NAME, & MYSQL_ERROR::m_schema_name },
+ { DIAG_TABLE_NAME, & MYSQL_ERROR::m_table_name },
+ { DIAG_COLUMN_NAME, & MYSQL_ERROR::m_column_name },
+ { DIAG_CURSOR_NAME, & MYSQL_ERROR::m_cursor_name }
+ };
+
+ Item *set;
+ String str_value;
+ String *str;
+ int i;
+ uint j;
+ int result= 1;
+ enum enum_diag_condition_item_name item_enum;
+ String *member;
+ const LEX_STRING *name;
+
+ DBUG_ENTER("Signal_common::eval_signal_informations");
+
+ for (i= FIRST_DIAG_SET_PROPERTY;
+ i <= LAST_DIAG_SET_PROPERTY;
+ i++)
+ {
+ set= m_set_signal_information.m_item[i];
+ if (set)
+ {
+ if (! set->fixed)
+ {
+ if (set->fix_fields(thd, & set))
+ goto end;
+ m_set_signal_information.m_item[i]= set;
+ }
+ }
+ }
+
+ /*
+ Generically assign all the UTF8 String 64 condition items
+ described in the map.
+ */
+ for (j= 0; j < array_elements(map); j++)
+ {
+ item_enum= map[j].m_item;
+ set= m_set_signal_information.m_item[item_enum];
+ if (set != NULL)
+ {
+ member= & (cond->* map[j].m_member);
+ name= & Diag_condition_item_names[item_enum];
+ if (assign_condition_item(cond->m_mem_root, name->str, thd, set, member))
+ goto end;
+ }
+ }
+
+ /*
+ Assign the remaining attributes.
+ */
+
+ set= m_set_signal_information.m_item[DIAG_MESSAGE_TEXT];
+ if (set != NULL)
+ {
+ if (set->is_null())
+ {
+ thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR,
+ "MESSAGE_TEXT", "NULL");
+ goto end;
+ }
+ /*
+ Enforce that SET MESSAGE_TEXT = <value> evaluates the value
+ as VARCHAR(128) CHARACTER SET UTF8.
+ */
+ bool truncated;
+ String utf8_text;
+ str= set->val_str(& str_value);
+ truncated= assign_fixed_string(thd->mem_root, & my_charset_utf8_bin, 128,
+ & utf8_text, str);
+ if (truncated)
+ {
+ if (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES |
+ MODE_STRICT_ALL_TABLES))
+ {
+ thd->raise_error_printf(ER_COND_ITEM_TOO_LONG,
+ "MESSAGE_TEXT");
+ goto end;
+ }
+
+ thd->raise_warning_printf(WARN_COND_ITEM_TRUNCATED,
+ "MESSAGE_TEXT");
+ }
+
+ /*
+ See the comments
+ "Design notes about MYSQL_ERROR::m_message_text."
+ in file sql_error.cc
+ */
+ String converted_text;
+ converted_text.set_charset(error_message_charset_info);
+ converted_text.append(utf8_text.ptr(), utf8_text.length(),
+ utf8_text.charset());
+ cond->set_builtin_message_text(converted_text.c_ptr_safe());
+ }
+
+ set= m_set_signal_information.m_item[DIAG_MYSQL_ERRNO];
+ if (set != NULL)
+ {
+ if (set->is_null())
+ {
+ thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR,
+ "MYSQL_ERRNO", "NULL");
+ goto end;
+ }
+ longlong code= set->val_int();
+ if ((code <= 0) || (code > MAX_MYSQL_ERRNO))
+ {
+ str= set->val_str(& str_value);
+ thd->raise_error_printf(ER_WRONG_VALUE_FOR_VAR,
+ "MYSQL_ERRNO", str->c_ptr_safe());
+ goto end;
+ }
+ cond->m_sql_errno= (int) code;
+ }
+
+ /*
+ The various item->val_xxx() methods don't return an error code,
+ but flag thd in case of failure.
+ */
+ if (! thd->is_error())
+ result= 0;
+
+end:
+ for (i= FIRST_DIAG_SET_PROPERTY;
+ i <= LAST_DIAG_SET_PROPERTY;
+ i++)
+ {
+ set= m_set_signal_information.m_item[i];
+ if (set)
+ {
+ if (set->fixed)
+ set->cleanup();
+ }
+ }
+
+ DBUG_RETURN(result);
+}
+
+bool Signal_common::raise_condition(THD *thd, MYSQL_ERROR *cond)
+{
+ bool result= TRUE;
+
+ DBUG_ENTER("Signal_common::raise_condition");
+
+ DBUG_ASSERT(m_lex->query_tables == NULL);
+
+ eval_defaults(thd, cond);
+ if (eval_signal_informations(thd, cond))
+ DBUG_RETURN(result);
+
+ /* SIGNAL should not signal WARN_LEVEL_NOTE */
+ DBUG_ASSERT((cond->m_level == MYSQL_ERROR::WARN_LEVEL_WARN) ||
+ (cond->m_level == MYSQL_ERROR::WARN_LEVEL_ERROR));
+
+ MYSQL_ERROR *raised= NULL;
+ raised= thd->raise_condition(cond->get_sql_errno(),
+ cond->get_sqlstate(),
+ cond->get_level(),
+ cond->get_message_text());
+ if (raised)
+ raised->copy_opt_attributes(cond);
+
+ if (cond->m_level == MYSQL_ERROR::WARN_LEVEL_WARN)
+ {
+ my_ok(thd);
+ result= FALSE;
+ }
+
+ DBUG_RETURN(result);
+}
+
+bool Signal_statement::execute(THD *thd)
+{
+ bool result= TRUE;
+ MYSQL_ERROR cond(thd->mem_root);
+
+ DBUG_ENTER("Signal_statement::execute");
+
+ thd->stmt_da->reset_diagnostics_area();
+ thd->row_count_func= 0;
+ thd->warning_info->clear_warning_info(thd->query_id);
+
+ result= raise_condition(thd, &cond);
+
+ DBUG_RETURN(result);
+}
+
+
+bool Resignal_statement::execute(THD *thd)
+{
+ MYSQL_ERROR *signaled;
+ int result= TRUE;
+
+ DBUG_ENTER("Resignal_statement::execute");
+
+ thd->warning_info->m_warn_id= thd->query_id;
+
+ if (! thd->spcont || ! (signaled= thd->spcont->raised_condition()))
+ {
+ thd->raise_error(ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER);
+ DBUG_RETURN(result);
+ }
+
+ if (m_cond == NULL)
+ {
+ /* RESIGNAL without signal_value */
+ result= raise_condition(thd, signaled);
+ DBUG_RETURN(result);
+ }
+
+ /* RESIGNAL with signal_value */
+
+ /* Make room for 2 conditions */
+ thd->warning_info->reserve_space(thd, 2);
+
+ MYSQL_ERROR *raised= NULL;
+ raised= thd->raise_condition_no_handler(signaled->get_sql_errno(),
+ signaled->get_sqlstate(),
+ signaled->get_level(),
+ signaled->get_message_text());
+ if (raised)
+ raised->copy_opt_attributes(signaled);
+
+ result= raise_condition(thd, signaled);
+
+ DBUG_RETURN(result);
+}
+
diff --git a/sql/sql_signal.h b/sql/sql_signal.h
new file mode 100644
index 00000000000..c9c1517f4ad
--- /dev/null
+++ b/sql/sql_signal.h
@@ -0,0 +1,152 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ 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 */
+
+#ifndef SQL_SIGNAL_H
+#define SQL_SIGNAL_H
+
+/**
+ Signal_common represents the common properties of the SIGNAL and RESIGNAL
+ statements.
+*/
+class Signal_common : public Sql_statement
+{
+protected:
+ /**
+ Constructor.
+ @param lex the LEX structure for this statement.
+ @param cond the condition signaled if any, or NULL.
+ @param set collection of signal condition item assignments.
+ */
+ Signal_common(LEX *lex,
+ const sp_cond_type_t *cond,
+ const Set_signal_information& set)
+ : Sql_statement(lex),
+ m_cond(cond),
+ m_set_signal_information(set)
+ {}
+
+ virtual ~Signal_common()
+ {}
+
+ /**
+ Assign the condition items 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
+ default values of a condition.
+ @param cond the condition to update.
+ @param set_level_code true if 'level' and 'MYSQL_ERRNO' needs to be overwritten
+ @param level the level to assign
+ @param sqlcode the sql code to assign
+ */
+ static void assign_defaults(MYSQL_ERROR *cond,
+ bool set_level_code,
+ MYSQL_ERROR::enum_warning_level level,
+ int sqlcode);
+
+ /**
+ Evaluate the condition items 'SQLSTATE', 'MYSQL_ERRNO', 'level' and 'MESSAGE_TEXT'
+ default values for this statement.
+ @param thd the current thread.
+ @param cond the condition to update.
+ */
+ void eval_defaults(THD *thd, MYSQL_ERROR *cond);
+
+ /**
+ Evaluate each signal condition items for this statement.
+ @param thd the current thread.
+ @param cond the condition to update.
+ @return 0 on success.
+ */
+ int eval_signal_informations(THD *thd, MYSQL_ERROR *cond);
+
+ /**
+ Raise a SQL condition.
+ @param thd the current thread.
+ @param cond the condition to raise.
+ @return false on success.
+ */
+ bool raise_condition(THD *thd, MYSQL_ERROR *cond);
+
+ /**
+ The condition to signal or resignal.
+ This member is optional and can be NULL (RESIGNAL).
+ */
+ const sp_cond_type_t *m_cond;
+
+ /**
+ Collection of 'SET item = value' assignments in the
+ SIGNAL/RESIGNAL statement.
+ */
+ Set_signal_information m_set_signal_information;
+};
+
+/**
+ Signal_statement represents a SIGNAL statement.
+*/
+class Signal_statement : public Signal_common
+{
+public:
+ /**
+ Constructor, used to represent a SIGNAL statement.
+ @param lex the LEX structure for this statement.
+ @param cond the SQL condition to signal (required).
+ @param set the collection of signal informations to signal.
+ */
+ Signal_statement(LEX *lex,
+ const sp_cond_type_t *cond,
+ const Set_signal_information& set)
+ : Signal_common(lex, cond, set)
+ {}
+
+ virtual ~Signal_statement()
+ {}
+
+ /**
+ Execute a SIGNAL statement at runtime.
+ @param thd the current thread.
+ @return false on success.
+ */
+ virtual bool execute(THD *thd);
+};
+
+/**
+ Resignal_statement represents a RESIGNAL statement.
+*/
+class Resignal_statement : public Signal_common
+{
+public:
+ /**
+ Constructor, used to represent a RESIGNAL statement.
+ @param lex the LEX structure for this statement.
+ @param cond the SQL condition to resignal (optional, may be NULL).
+ @param set the collection of signal informations to resignal.
+ */
+ Resignal_statement(LEX *lex,
+ const sp_cond_type_t *cond,
+ const Set_signal_information& set)
+ : Signal_common(lex, cond, set)
+ {}
+
+ virtual ~Resignal_statement()
+ {}
+
+ /**
+ Execute a RESIGNAL statement at runtime.
+ @param thd the current thread.
+ @return 0 on success.
+ */
+ virtual bool execute(THD *thd);
+};
+
+#endif
+
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 7c9793b273b..593450cacd5 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -794,10 +794,11 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
*/
-uint32
-copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
- const char *from, uint32 from_length, CHARSET_INFO *from_cs,
- uint *errors)
+static uint32
+copy_and_convert_extended(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length,
+ CHARSET_INFO *from_cs,
+ uint *errors)
{
int cnvres;
my_wc_t wc;
@@ -849,6 +850,65 @@ outp:
}
+/*
+ Optimized for quick copying of ASCII characters in the range 0x00..0x7F.
+*/
+uint32
+copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
+ const char *from, uint32 from_length, CHARSET_INFO *from_cs,
+ uint *errors)
+{
+ /*
+ If any of the character sets is not ASCII compatible,
+ immediately switch to slow mb_wc->wc_mb method.
+ */
+ if ((to_cs->state | from_cs->state) & MY_CS_NONASCII)
+ return copy_and_convert_extended(to, to_length, to_cs,
+ from, from_length, from_cs, errors);
+
+ uint32 length= min(to_length, from_length), length2= length;
+
+#if defined(__i386__)
+ /*
+ Special loop for i386, it allows to refer to a
+ non-aligned memory block as UINT32, which makes
+ it possible to copy four bytes at once. This
+ gives about 10% performance improvement comparing
+ to byte-by-byte loop.
+ */
+ for ( ; length >= 4; length-= 4, from+= 4, to+= 4)
+ {
+ if ((*(uint32*)from) & 0x80808080)
+ break;
+ *((uint32*) to)= *((const uint32*) from);
+ }
+#endif
+
+ for (; ; *to++= *from++, length--)
+ {
+ if (!length)
+ {
+ *errors= 0;
+ return length2;
+ }
+ if (*((unsigned char*) from) > 0x7F) /* A non-ASCII character */
+ {
+ uint32 copied_length= length2 - length;
+ to_length-= copied_length;
+ from_length-= copied_length;
+ return copied_length + copy_and_convert_extended(to, to_length,
+ to_cs,
+ from, from_length,
+ from_cs,
+ errors);
+ }
+ }
+
+ DBUG_ASSERT(FALSE); // Should never get to here
+ return 0; // Make compiler happy
+}
+
+
/**
Copy string with HEX-encoding of "bad" characters.
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 41e76211dd8..37c897aca3b 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4567,6 +4567,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/*
Set up which partitions that should be processed
if ALTER TABLE t ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION ..
+ CACHE INDEX/LOAD INDEX for specified partitions
*/
Alter_info *alter_info= &lex->alter_info;
@@ -4580,7 +4581,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
uint no_parts_found;
uint no_parts_opt= alter_info->partition_names.elements;
no_parts_found= set_part_state(alter_info, table->table->part_info,
- PART_CHANGED);
+ PART_ADMIN);
if (no_parts_found != no_parts_opt &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
{
@@ -4638,17 +4639,17 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (!table->table)
{
DBUG_PRINT("admin", ("open table failed"));
- if (!thd->warn_list.elements)
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ if (thd->warning_info->is_empty())
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
/* if it was a view will check md5 sum */
if (table->view &&
view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
- if (thd->main_da.is_error() &&
- (thd->main_da.sql_errno() == ER_NO_SUCH_TABLE ||
- thd->main_da.sql_errno() == ER_FILE_NOT_FOUND))
+ if (thd->stmt_da->is_error() &&
+ (thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE ||
+ thd->stmt_da->sql_errno() == ER_FILE_NOT_FOUND))
/* A missing table is just issued as a failed command */
result_code= HA_ADMIN_FAILED;
else
@@ -4690,7 +4691,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->table=0; // For query cache
if (protocol->write())
goto err;
- thd->main_da.reset_diagnostics_area();
+ thd->stmt_da->reset_diagnostics_area();
continue;
/* purecov: end */
}
@@ -4750,8 +4751,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
we will store the error message in a result set row
and then clear.
*/
- if (thd->main_da.is_ok())
- thd->main_da.reset_diagnostics_area();
+ if (thd->stmt_da->is_ok())
+ thd->stmt_da->reset_diagnostics_area();
goto send_result;
}
}
@@ -4765,21 +4766,21 @@ send_result:
lex->cleanup_after_one_table_open();
thd->clear_error(); // these errors shouldn't get client
{
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
while ((err= it++))
{
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store((char*) operator_name, system_charset_info);
- protocol->store(warning_level_names[err->level].str,
- warning_level_names[err->level].length,
+ protocol->store(warning_level_names[err->get_level()].str,
+ warning_level_names[err->get_level()].length,
system_charset_info);
- protocol->store(err->msg, system_charset_info);
+ protocol->store(err->get_message_text(), system_charset_info);
if (protocol->write())
goto err;
}
- mysql_reset_errors(thd, true);
+ thd->warning_info->clear_warning_info(thd->query_id);
}
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@@ -4874,8 +4875,8 @@ send_result_message:
we will store the error message in a result set row
and then clear.
*/
- if (thd->main_da.is_ok())
- thd->main_da.reset_diagnostics_area();
+ if (thd->stmt_da->is_ok())
+ thd->stmt_da->reset_diagnostics_area();
ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
if (!result_code) // recreation went ok
@@ -4893,7 +4894,7 @@ send_result_message:
DBUG_ASSERT(thd->is_error());
if (thd->is_error())
{
- const char *err_msg= thd->main_da.message();
+ const char *err_msg= thd->stmt_da->message();
if (!thd->vio_ok())
{
sql_print_error("%s", err_msg);
@@ -7493,7 +7494,8 @@ err:
the table to be altered isn't empty.
Report error here.
*/
- if (alter_info->error_if_not_empty && thd->row_count)
+ if (alter_info->error_if_not_empty &&
+ thd->warning_info->current_row_for_warning())
{
const char *f_val= 0;
enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
@@ -7514,7 +7516,7 @@ err:
}
bool save_abort_on_warning= thd->abort_on_warning;
thd->abort_on_warning= TRUE;
- make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
f_val, strlength(f_val), t_type,
alter_info->datetime_field->field_name);
thd->abort_on_warning= save_abort_on_warning;
@@ -7661,7 +7663,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE);
if (ignore)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- thd->row_count= 0;
+ thd->warning_info->reset_current_row_for_warning();
restore_record(to, s->default_values); // Create empty record
while (!(error=info.read_record(&info)))
{
@@ -7671,7 +7673,6 @@ copy_data_between_tables(TABLE *from,TABLE *to,
error= 1;
break;
}
- thd->row_count++;
/* Return error if source table isn't empty. */
if (error_if_not_empty)
{
@@ -7721,6 +7722,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
}
else
found_count++;
+ thd->warning_info->inc_current_row_for_warning();
}
end_read_record(&info);
free_io_cache(from);
diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc
index 9fec0e3bc63..3549a44807e 100644
--- a/sql/sql_tablespace.cc
+++ b/sql/sql_tablespace.cc
@@ -31,7 +31,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info)
{
hton= ha_default_handlerton(thd);
if (ts_info->storage_engine != 0)
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_USING_OTHER_HANDLER,
ER(ER_WARN_USING_OTHER_HANDLER),
ha_resolve_storage_engine_name(hton),
@@ -60,7 +60,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info)
}
else
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
ER(ER_ILLEGAL_HA_CREATE_OPTION),
ha_resolve_storage_engine_name(hton),
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index d4c1acabe11..f5c4b85e904 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -725,7 +725,7 @@ int mysql_update(THD *thd,
}
else
table->file->unlock_row();
- thd->row_count++;
+ thd->warning_info->inc_current_row_for_warning();
if (thd->is_error())
{
error= 1;
@@ -831,8 +831,9 @@ int mysql_update(THD *thd,
if (error < 0)
{
char buff[STRING_BUFFER_USUAL_SIZE];
- my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
- (ulong) thd->cuted_fields);
+ my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found,
+ (ulong) updated,
+ (ulong) thd->warning_info->statement_warn_count());
thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
my_ok(thd, (ulong) thd->row_count_func, id, buff);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index db97e77bbd0..f8650d83bc6 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -43,6 +43,7 @@
#include "sp_pcontext.h"
#include "sp_rcontext.h"
#include "sp.h"
+#include "sql_signal.h"
#include "event_parse_data.h"
#include <myisam.h>
#include <myisammrg.h>
@@ -507,6 +508,8 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
sp_head *sphead;
struct p_elem_val *p_elem_value;
enum index_hint_type index_hint;
+ enum enum_filetype filetype;
+ Diag_condition_item_name diag_condition_item_name;
}
%{
@@ -588,6 +591,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CASCADED /* SQL-2003-R */
%token CASE_SYM /* SQL-2003-R */
%token CAST_SYM /* SQL-2003-R */
+%token CATALOG_NAME_SYM /* SQL-2003-N */
%token CHAIN_SYM /* SQL-2003-N */
%token CHANGE
%token CHANGED
@@ -596,6 +600,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CHECKSUM_SYM
%token CHECK_SYM /* SQL-2003-R */
%token CIPHER_SYM
+%token CLASS_ORIGIN_SYM /* SQL-2003-N */
%token CLIENT_SYM
%token CLOSE_SYM /* SQL-2003-R */
%token COALESCE /* SQL-2003-N */
@@ -604,6 +609,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token COLLATION_SYM /* SQL-2003-N */
%token COLUMNS
%token COLUMN_SYM /* SQL-2003-R */
+%token COLUMN_NAME_SYM /* SQL-2003-N */
%token COMMENT_SYM
%token COMMITTED_SYM /* SQL-2003-N */
%token COMMIT_SYM /* SQL-2003-R */
@@ -611,10 +617,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token COMPLETION_SYM
%token COMPRESSED_SYM
%token CONCURRENT
-%token CONDITION_SYM /* SQL-2003-N */
+%token CONDITION_SYM /* SQL-2003-R, SQL-2008-R */
%token CONNECTION_SYM
%token CONSISTENT_SYM
%token CONSTRAINT /* SQL-2003-R */
+%token CONSTRAINT_CATALOG_SYM /* SQL-2003-N */
+%token CONSTRAINT_NAME_SYM /* SQL-2003-N */
+%token CONSTRAINT_SCHEMA_SYM /* SQL-2003-N */
%token CONTAINS_SYM /* SQL-2003-N */
%token CONTEXT_SYM
%token CONTINUE_SYM /* SQL-2003-R */
@@ -628,6 +637,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CURDATE /* MYSQL-FUNC */
%token CURRENT_USER /* SQL-2003-R */
%token CURSOR_SYM /* SQL-2003-R */
+%token CURSOR_NAME_SYM /* SQL-2003-N */
%token CURTIME /* MYSQL-FUNC */
%token DATABASE
%token DATABASES
@@ -829,6 +839,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MEDIUM_SYM
%token MEMORY_SYM
%token MERGE_SYM /* SQL-2003-R */
+%token MESSAGE_TEXT_SYM /* SQL-2003-N */
%token MICROSECOND_SYM /* MYSQL-FUNC */
%token MIGRATE_SYM
%token MINUTE_MICROSECOND_SYM
@@ -845,6 +856,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token MULTIPOINT
%token MULTIPOLYGON
%token MUTEX_SYM
+%token MYSQL_ERRNO_SYM
%token NAMES_SYM /* SQL-2003-N */
%token NAME_SYM /* SQL-2003-N */
%token NATIONAL_SYM /* SQL-2003-R */
@@ -945,6 +957,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token REPLICATION
%token REQUIRE_SYM
%token RESET_SYM
+%token RESIGNAL_SYM /* SQL-2003-R */
%token RESOURCES
%token RESTORE_SYM
%token RESTRICT
@@ -962,6 +975,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token RTREE_SYM
%token SAVEPOINT_SYM /* SQL-2003-R */
%token SCHEDULE_SYM
+%token SCHEMA_NAME_SYM /* SQL-2003-N */
%token SECOND_MICROSECOND_SYM
%token SECOND_SYM /* SQL-2003-R */
%token SECURITY_SYM /* SQL-2003-N */
@@ -980,6 +994,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SHIFT_RIGHT /* OPERATOR */
%token SHOW
%token SHUTDOWN
+%token SIGNAL_SYM /* SQL-2003-R */
%token SIGNED_SYM
%token SIMPLE_SYM /* SQL-2003-N */
%token SLAVE
@@ -1013,6 +1028,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token STORAGE_SYM
%token STRAIGHT_JOIN
%token STRING_SYM
+%token SUBCLASS_ORIGIN_SYM /* SQL-2003-N */
%token SUBDATE_SYM
%token SUBJECT_SYM
%token SUBPARTITIONS_SYM
@@ -1029,6 +1045,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token TABLE_REF_PRIORITY
%token TABLE_SYM /* SQL-2003-R */
%token TABLE_CHECKSUM_SYM
+%token TABLE_NAME_SYM /* SQL-2003-N */
%token TEMPORARY /* SQL-2003-N */
%token TEMPTABLE_SYM
%token TERMINATED
@@ -1100,6 +1117,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token WRITE_SYM /* SQL-2003-N */
%token X509_SYM
%token XA_SYM
+%token XML_SYM
%token XOR
%token YEAR_MONTH_SYM
%token YEAR_SYM /* SQL-2003-R */
@@ -1186,6 +1204,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
function_call_nonkeyword
function_call_generic
function_call_conflict
+ signal_allowed_expr
%type <item_num>
NUM_literal
@@ -1261,7 +1280,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
slave master_def master_defs master_file_def slave_until_opts
repair restore backup analyze check start checksum
field_list field_list_item field_spec kill column_def key_def
- keycache_list assign_to_keycache preload_list preload_keys
+ keycache_list keycache_list_or_parts assign_to_keycache
+ assign_to_keycache_parts
+ preload_list preload_list_or_parts preload_keys preload_keys_parts
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
@@ -1290,7 +1311,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
prepare prepare_src execute deallocate
statement sp_suid
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
- load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
+ opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
view_replace_or_algorithm view_replace
view_algorithm view_or_trigger_or_sp_or_event
definer_tail no_definer_tail
@@ -1313,12 +1334,16 @@ END_OF_INPUT
%type <NONE> case_stmt_specification simple_case_stmt searched_case_stmt
%type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list
-%type <spcondtype> sp_cond sp_hcond
+%type <spcondtype> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decls sp_decl
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <index_hint> index_hint_type
%type <num> index_hint_clause
+%type <filetype> data_or_xml
+
+%type <NONE> signal_stmt resignal_stmt
+%type <diag_condition_item_name> signal_condition_information_item_name
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
@@ -1440,12 +1465,14 @@ statement:
| repair
| replace
| reset
+ | resignal_stmt
| restore
| revoke
| rollback
| savepoint
| select
| set
+ | signal_stmt
| show
| slave
| start
@@ -2340,12 +2367,12 @@ sp_decl:
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
- if (spc->find_cond(&$2, TRUE))
- {
- my_error(ER_SP_DUP_COND, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
- if(YYTHD->lex->spcont->push_cond(&$2, $5))
+ if (spc->find_cond(&$2, TRUE))
+ {
+ my_error(ER_SP_DUP_COND, MYF(0), $2.str);
+ MYSQL_YYABORT;
+ }
+ if(YYTHD->lex->spcont->push_cond(&$2, $5))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
$$.conds= 1;
@@ -2360,9 +2387,9 @@ sp_decl:
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
- ctx->current_var_count());
+ ctx->current_var_count());
if (i == NULL ||
- sp->add_instr(i) ||
+ sp->add_instr(i) ||
sp->push_backpatch(i, ctx->push_label((char *)"", 0)))
MYSQL_YYABORT;
}
@@ -2379,15 +2406,15 @@ sp_decl:
i= new sp_instr_hreturn(sp->instructions(), ctx,
ctx->current_var_count());
if (i == NULL ||
- sp->add_instr(i))
+ sp->add_instr(i))
MYSQL_YYABORT;
}
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
i= new sp_instr_hreturn(sp->instructions(), ctx, 0);
if (i == NULL ||
- sp->add_instr(i) ||
- sp->push_backpatch(i, lex->spcont->last_label())) /* Block end */
+ sp->add_instr(i) ||
+ sp->push_backpatch(i, lex->spcont->last_label())) /* Block end */
MYSQL_YYABORT;
}
lex->sphead->backpatch(hlab);
@@ -2414,9 +2441,9 @@ sp_decl:
}
i= new sp_instr_cpush(sp->instructions(), ctx, $5,
ctx->current_cursor_count());
- if (i == NULL ||
+ if (i == NULL ||
sp->add_instr(i) ||
- ctx->push_cursor(&$2))
+ ctx->push_cursor(&$2))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
@@ -2484,13 +2511,22 @@ sp_hcond_element:
sp_cond:
ulong_num
{ /* mysql errno */
+ if ($1 == 0)
+ {
+ my_error(ER_WRONG_VALUE, MYF(0), "CONDITION", "0");
+ MYSQL_YYABORT;
+ }
$$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
if ($$ == NULL)
MYSQL_YYABORT;
$$->type= sp_cond_type_t::number;
$$->mysqlerr= $1;
}
- | SQLSTATE_SYM opt_value TEXT_STRING_literal
+ | sqlstate
+ ;
+
+sqlstate:
+ SQLSTATE_SYM opt_value TEXT_STRING_literal
{ /* SQLSTATE */
if (!sp_cond_check(&$3))
{
@@ -2501,8 +2537,8 @@ sp_cond:
if ($$ == NULL)
MYSQL_YYABORT;
$$->type= sp_cond_type_t::state;
- memcpy($$->sqlstate, $3.str, 5);
- $$->sqlstate[5]= '\0';
+ memcpy($$->sqlstate, $3.str, SQLSTATE_LENGTH);
+ $$->sqlstate[SQLSTATE_LENGTH]= '\0';
}
;
@@ -2548,6 +2584,160 @@ sp_hcond:
}
;
+signal_stmt:
+ SIGNAL_SYM signal_value opt_set_signal_information
+ {
+ THD *thd= YYTHD;
+ LEX *lex= thd->lex;
+ Yacc_state *state= & thd->m_parser_state->m_yacc;
+
+ lex->sql_command= SQLCOM_SIGNAL;
+ lex->m_stmt= new (thd->mem_root) Signal_statement(lex, $2,
+ state->m_set_signal_info);
+ if (lex->m_stmt == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
+signal_value:
+ ident
+ {
+ LEX *lex= Lex;
+ sp_cond_type_t *cond;
+ if (lex->spcont == NULL)
+ {
+ /* SIGNAL foo cannot be used outside of stored programs */
+ my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
+ MYSQL_YYABORT;
+ }
+ cond= lex->spcont->find_cond(&$1);
+ if (cond == NULL)
+ {
+ my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
+ MYSQL_YYABORT;
+ }
+ if (cond->type != sp_cond_type_t::state)
+ {
+ my_error(ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0));
+ MYSQL_YYABORT;
+ }
+ $$= cond;
+ }
+ | sqlstate
+ { $$= $1; }
+ ;
+
+opt_signal_value:
+ /* empty */
+ { $$= NULL; }
+ | signal_value
+ { $$= $1; }
+ ;
+
+opt_set_signal_information:
+ /* empty */
+ {
+ YYTHD->m_parser_state->m_yacc.m_set_signal_info.clear();
+ }
+ | SET signal_information_item_list
+ ;
+
+signal_information_item_list:
+ signal_condition_information_item_name EQ signal_allowed_expr
+ {
+ Set_signal_information *info;
+ info= & YYTHD->m_parser_state->m_yacc.m_set_signal_info;
+ int index= (int) $1;
+ info->clear();
+ info->m_item[index]= $3;
+ }
+ | signal_information_item_list ','
+ signal_condition_information_item_name EQ signal_allowed_expr
+ {
+ Set_signal_information *info;
+ info= & YYTHD->m_parser_state->m_yacc.m_set_signal_info;
+ int index= (int) $3;
+ if (info->m_item[index] != NULL)
+ {
+ my_error(ER_DUP_SIGNAL_SET, MYF(0),
+ Diag_condition_item_names[index].str);
+ MYSQL_YYABORT;
+ }
+ info->m_item[index]= $5;
+ }
+ ;
+
+/*
+ Only a limited subset of <expr> are allowed in SIGNAL/RESIGNAL.
+*/
+signal_allowed_expr:
+ literal
+ { $$= $1; }
+ | variable
+ {
+ if ($1->type() == Item::FUNC_ITEM)
+ {
+ Item_func *item= (Item_func*) $1;
+ if (item->functype() == Item_func::SUSERVAR_FUNC)
+ {
+ /*
+ Don't allow the following syntax:
+ SIGNAL/RESIGNAL ...
+ SET <signal condition item name> = @foo := expr
+ */
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ }
+ $$= $1;
+ }
+ | simple_ident
+ { $$= $1; }
+ ;
+
+/* conditions that can be set in signal / resignal */
+signal_condition_information_item_name:
+ CLASS_ORIGIN_SYM
+ { $$= DIAG_CLASS_ORIGIN; }
+ | SUBCLASS_ORIGIN_SYM
+ { $$= DIAG_SUBCLASS_ORIGIN; }
+ | CONSTRAINT_CATALOG_SYM
+ { $$= DIAG_CONSTRAINT_CATALOG; }
+ | CONSTRAINT_SCHEMA_SYM
+ { $$= DIAG_CONSTRAINT_SCHEMA; }
+ | CONSTRAINT_NAME_SYM
+ { $$= DIAG_CONSTRAINT_NAME; }
+ | CATALOG_NAME_SYM
+ { $$= DIAG_CATALOG_NAME; }
+ | SCHEMA_NAME_SYM
+ { $$= DIAG_SCHEMA_NAME; }
+ | TABLE_NAME_SYM
+ { $$= DIAG_TABLE_NAME; }
+ | COLUMN_NAME_SYM
+ { $$= DIAG_COLUMN_NAME; }
+ | CURSOR_NAME_SYM
+ { $$= DIAG_CURSOR_NAME; }
+ | MESSAGE_TEXT_SYM
+ { $$= DIAG_MESSAGE_TEXT; }
+ | MYSQL_ERRNO_SYM
+ { $$= DIAG_MYSQL_ERRNO; }
+ ;
+
+resignal_stmt:
+ RESIGNAL_SYM opt_signal_value opt_set_signal_information
+ {
+ THD *thd= YYTHD;
+ LEX *lex= thd->lex;
+ Yacc_state *state= & thd->m_parser_state->m_yacc;
+
+ lex->sql_command= SQLCOM_RESIGNAL;
+ lex->m_stmt= new (thd->mem_root) Resignal_statement(lex, $2,
+ state->m_set_signal_info);
+ if (lex->m_stmt == NULL)
+ MYSQL_YYABORT;
+ }
+ ;
+
sp_decl_idents:
ident
{
@@ -2684,7 +2874,7 @@ sp_proc_stmt_return:
i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3,
sp->m_return_field_def.sql_type, lex);
if (i == NULL ||
- sp->add_instr(i))
+ sp->add_instr(i))
MYSQL_YYABORT;
sp->m_flags|= sp_head::HAS_RETURN;
}
@@ -2924,7 +3114,7 @@ sp_if:
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx,
$2, lex);
if (i == NULL ||
- sp->push_backpatch(i, ctx->push_label((char *)"", 0)) ||
+ sp->push_backpatch(i, ctx->push_label((char *)"", 0)) ||
sp->add_cont_backpatch(i) ||
sp->add_instr(i))
MYSQL_YYABORT;
@@ -3206,7 +3396,7 @@ sp_unlabeled_control:
if (i == NULL ||
lex->sphead->add_instr(i))
MYSQL_YYABORT;
- }
+ }
| WHILE_SYM
{ Lex->sphead->reset_lex(YYTHD); }
expr DO_SYM
@@ -3217,7 +3407,7 @@ sp_unlabeled_control:
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
$3, lex);
if (i == NULL ||
- /* Jumping forward */
+ /* Jumping forward */
sp->push_backpatch(i, lex->spcont->last_label()) ||
sp->new_cont_backpatch(i) ||
sp->add_instr(i))
@@ -3748,17 +3938,9 @@ opt_partitioning:
;
partitioning:
- PARTITION_SYM
+ PARTITION_SYM have_partitioning
{
-#ifdef WITH_PARTITION_STORAGE_ENGINE
LEX *lex= Lex;
- LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
- if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
- "--skip-partition");
- MYSQL_YYABORT;
- }
lex->part_info= new partition_info();
if (!lex->part_info)
{
@@ -3769,14 +3951,27 @@ partitioning:
{
lex->alter_info.flags|= ALTER_PARTITION;
}
+ }
+ partition
+ ;
+
+have_partitioning:
+ /* empty */
+ {
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+ LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
+ if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
+ {
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition");
+ MYSQL_YYABORT;
+ }
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- "partitioning", "--with-partition");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition");
MYSQL_YYABORT;
#endif
-
}
- partition
;
partition_entry:
@@ -5024,6 +5219,7 @@ field_length:
opt_field_length:
/* empty */ { Lex->length=(char*) 0; /* use default length */ }
| field_length { }
+ ;
opt_precision:
/* empty */ {}
@@ -5438,7 +5634,6 @@ alter:
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
TL_OPTION_UPDATING))
MYSQL_YYABORT;
- lex->alter_info.reset();
lex->col_list.empty();
lex->select_lex.init_order();
lex->select_lex.db=
@@ -5672,7 +5867,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
- lex->sql_command = SQLCOM_OPTIMIZE;
+ lex->sql_command= SQLCOM_OPTIMIZE;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@@ -5682,7 +5877,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
- lex->sql_command = SQLCOM_ANALYZE;
+ lex->sql_command= SQLCOM_ANALYZE;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@@ -5690,7 +5885,7 @@ alter_commands:
| CHECK_SYM PARTITION_SYM all_or_alt_part_name_list
{
LEX *lex= Lex;
- lex->sql_command = SQLCOM_CHECK;
+ lex->sql_command= SQLCOM_CHECK;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->check_opt.init();
}
@@ -5699,7 +5894,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
- lex->sql_command = SQLCOM_REPAIR;
+ lex->sql_command= SQLCOM_REPAIR;
lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
@@ -5712,6 +5907,13 @@ alter_commands:
lex->no_write_to_binlog= $3;
lex->alter_info.no_parts= $4;
}
+ | TRUNCATE_SYM PARTITION_SYM all_or_alt_part_name_list
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_TRUNCATE;
+ lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
+ lex->check_opt.init();
+ }
| reorg_partition_rule
;
@@ -6297,14 +6499,23 @@ table_to_table:
;
keycache:
- CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name
+ CACHE_SYM INDEX_SYM
+ {
+ Lex->alter_info.reset();
+ }
+ keycache_list_or_parts IN_SYM key_cache_name
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE;
- lex->ident= $5;
+ lex->ident= $6;
}
;
+keycache_list_or_parts:
+ keycache_list
+ | assign_to_keycache_parts
+ ;
+
keycache_list:
assign_to_keycache
| keycache_list ',' assign_to_keycache
@@ -6319,6 +6530,15 @@ assign_to_keycache:
}
;
+assign_to_keycache_parts:
+ table_ident adm_partition cache_keys_spec
+ {
+ if (!Select->add_table_to_list(YYTHD, $1, NULL, 0, TL_READ,
+ Select->pop_index_hints()))
+ MYSQL_YYABORT;
+ }
+ ;
+
key_cache_name:
ident { $$= $1; }
| DEFAULT { $$ = default_key_cache_base; }
@@ -6329,11 +6549,17 @@ preload:
{
LEX *lex=Lex;
lex->sql_command=SQLCOM_PRELOAD_KEYS;
+ lex->alter_info.reset();
}
- preload_list
+ preload_list_or_parts
{}
;
+preload_list_or_parts:
+ preload_keys_parts
+ | preload_list
+ ;
+
preload_list:
preload_keys
| preload_list ',' preload_keys
@@ -6348,6 +6574,23 @@ preload_keys:
}
;
+preload_keys_parts:
+ table_ident adm_partition cache_keys_spec opt_ignore_leaves
+ {
+ if (!Select->add_table_to_list(YYTHD, $1, NULL, $4, TL_READ,
+ Select->pop_index_hints()))
+ MYSQL_YYABORT;
+ }
+ ;
+
+adm_partition:
+ PARTITION_SYM have_partitioning
+ {
+ Lex->alter_info.flags|= ALTER_ADMIN_PARTITION;
+ }
+ '(' all_or_alt_part_name_list ')'
+ ;
+
cache_keys_spec:
{
Lex->select_lex.alloc_index_hints(YYTHD);
@@ -6411,7 +6654,7 @@ select_paren:
sel->olap != UNSPECIFIED_OLAP_TYPE &&
sel->master_unit()->fake_select_lex)
{
- my_error(ER_WRONG_USAGE, MYF(0),
+ my_error(ER_WRONG_USAGE, MYF(0),
"CUBE/ROLLUP", "ORDER BY");
MYSQL_YYABORT;
}
@@ -7942,7 +8185,7 @@ sum_expr:
}
| AVG_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_avg_distinct($4);
+ $$= new (YYTHD->mem_root) Item_sum_avg($4, TRUE);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -7985,7 +8228,7 @@ sum_expr:
{ Select->in_sum_expr--; }
')'
{
- $$= new (YYTHD->mem_root) Item_sum_count_distinct(* $5);
+ $$= new (YYTHD->mem_root) Item_sum_count(* $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8050,7 +8293,7 @@ sum_expr:
}
| SUM_SYM '(' DISTINCT in_sum_expr ')'
{
- $$= new (YYTHD->mem_root) Item_sum_sum_distinct($4);
+ $$= new (YYTHD->mem_root) Item_sum_sum($4, TRUE);
if ($$ == NULL)
MYSQL_YYABORT;
}
@@ -8712,24 +8955,25 @@ interval:
;
interval_time_stamp:
- interval_time_st {}
- | FRAC_SECOND_SYM {
- $$=INTERVAL_MICROSECOND;
- /*
- FRAC_SECOND was mistakenly implemented with
- a wrong resolution. According to the ODBC
- standard it should be nanoseconds, not
- microseconds. Changing it to nanoseconds
- in MySQL would mean making TIMESTAMPDIFF
- and TIMESTAMPADD to return DECIMAL, since
- the return value would be too big for BIGINT
- Hence we just deprecate the incorrect
- implementation without changing its
- resolution.
- */
- WARN_DEPRECATED(yythd, "6.2", "FRAC_SECOND", "MICROSECOND");
- }
- ;
+ interval_time_st {}
+ | FRAC_SECOND_SYM
+ {
+ $$=INTERVAL_MICROSECOND;
+ /*
+ FRAC_SECOND was mistakenly implemented with
+ a wrong resolution. According to the ODBC
+ standard it should be nanoseconds, not
+ microseconds. Changing it to nanoseconds
+ in MySQL would mean making TIMESTAMPDIFF
+ and TIMESTAMPADD to return DECIMAL, since
+ the return value would be too big for BIGINT
+ Hence we just deprecate the incorrect
+ implementation without changing its
+ resolution.
+ */
+ WARN_DEPRECATED(yythd, "6.2", "FRAC_SECOND", "MICROSECOND");
+ }
+ ;
interval_time_st:
DAY_SYM { $$=INTERVAL_DAY; }
@@ -9766,6 +10010,7 @@ truncate:
{
LEX* lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
+ lex->alter_info.reset();
lex->select_lex.options= 0;
lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
lex->select_lex.init_order();
@@ -10421,7 +10666,7 @@ use:
/* import, export of files */
load:
- LOAD DATA_SYM
+ LOAD data_or_xml
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
@@ -10429,39 +10674,21 @@ load:
if (lex->sphead)
{
- my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
- MYSQL_YYABORT;
- }
- lex->fname_start= lip->get_ptr();
- }
- load_data
- {}
- | LOAD TABLE_SYM table_ident FROM MASTER_SYM
- {
- LEX *lex=Lex;
- WARN_DEPRECATED(yythd, "6.0", "LOAD TABLE FROM MASTER",
- "MySQL Administrator (mysqldump, mysql)");
- if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD TABLE");
+ my_error(ER_SP_BADSTATEMENT, MYF(0),
+ $2 == FILETYPE_CSV ? "LOAD DATA" : "LOAD XML");
MYSQL_YYABORT;
}
- lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
- if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
- MYSQL_YYABORT;
+ lex->fname_start= lip->get_tok_end();
}
- ;
-
-load_data:
load_data_lock opt_local INFILE TEXT_STRING_filesystem
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD;
- lex->lock_option= $1;
- lex->local_file= $2;
+ lex->lock_option= $4;
+ lex->local_file= $5;
lex->duplicates= DUP_ERROR;
lex->ignore= 0;
- if (!(lex->exchange= new sql_exchange($4.str, 0)))
+ if (!(lex->exchange= new sql_exchange($7.str, 0, $2)))
MYSQL_YYABORT;
}
opt_duplicate INTO
@@ -10471,7 +10698,7 @@ load_data:
TABLE_SYM table_ident
{
LEX *lex=Lex;
- if (!Select->add_table_to_list(YYTHD, $10, NULL, TL_OPTION_UPDATING,
+ if (!Select->add_table_to_list(YYTHD, $13, NULL, TL_OPTION_UPDATING,
lex->lock_option))
MYSQL_YYABORT;
lex->field_list.empty();
@@ -10479,12 +10706,35 @@ load_data:
lex->value_list.empty();
}
opt_load_data_charset
- { Lex->exchange->cs= $12; }
+ { Lex->exchange->cs= $15; }
+ opt_xml_rows_identified_by
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
opt_load_data_set_spec
{}
- | FROM MASTER_SYM
+ | LOAD TABLE_SYM table_ident FROM MASTER_SYM
{
+ LEX *lex=Lex;
+ WARN_DEPRECATED(yythd, "6.0", "LOAD TABLE FROM MASTER",
+ "MySQL Administrator (mysqldump, mysql)");
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD TABLE");
+ MYSQL_YYABORT;
+ }
+ lex->sql_command = SQLCOM_LOAD_MASTER_TABLE;
+ if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING))
+ MYSQL_YYABORT;
+ }
+ | LOAD DATA_SYM FROM MASTER_SYM
+ {
+ THD *thd= YYTHD;
+ LEX *lex= thd->lex;
+
+ if (lex->sphead)
+ {
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
+ MYSQL_YYABORT;
+ }
Lex->sql_command = SQLCOM_LOAD_MASTER_DATA;
WARN_DEPRECATED(yythd, "6.0", "LOAD DATA FROM MASTER",
"mysqldump or future "
@@ -10492,6 +10742,11 @@ load_data:
}
;
+data_or_xml:
+ DATA_SYM { $$= FILETYPE_CSV; }
+ | XML_SYM { $$= FILETYPE_XML; }
+ ;
+
opt_local:
/* empty */ { $$=0;}
| LOCAL_SYM { $$=1;}
@@ -10578,15 +10833,25 @@ line_term:
}
;
+opt_xml_rows_identified_by:
+ /* empty */ { }
+ | ROWS_SYM IDENTIFIED_SYM BY text_string
+ { Lex->exchange->line_term = $4; };
+
opt_ignore_lines:
/* empty */
- | IGNORE_SYM NUM LINES
+ | IGNORE_SYM NUM lines_or_rows
{
DBUG_ASSERT(Lex->exchange != 0);
Lex->exchange->skip_lines= atol($2.str);
}
;
+lines_or_rows:
+ LINES { }
+ | ROWS_SYM { }
+ ;
+
opt_field_or_var_spec:
/* empty */ {}
| '(' fields_or_vars ')' {}
@@ -11431,13 +11696,16 @@ keyword_sp:
| BOOLEAN_SYM {}
| BTREE_SYM {}
| CASCADED {}
+ | CATALOG_NAME_SYM {}
| CHAIN_SYM {}
| CHANGED {}
| CIPHER_SYM {}
| CLIENT_SYM {}
+ | CLASS_ORIGIN_SYM {}
| COALESCE {}
| CODE_SYM {}
| COLLATION_SYM {}
+ | COLUMN_NAME_SYM {}
| COLUMNS {}
| COMMITTED_SYM {}
| COMPACT_SYM {}
@@ -11446,10 +11714,14 @@ keyword_sp:
| CONCURRENT {}
| CONNECTION_SYM {}
| CONSISTENT_SYM {}
+ | CONSTRAINT_CATALOG_SYM {}
+ | CONSTRAINT_SCHEMA_SYM {}
+ | CONSTRAINT_NAME_SYM {}
| CONTEXT_SYM {}
| CONTRIBUTORS_SYM {}
| CPU_SYM {}
| CUBE_SYM {}
+ | CURSOR_NAME_SYM {}
| DATA_SYM {}
| DATAFILE_SYM {}
| DATETIME {}
@@ -11541,6 +11813,7 @@ keyword_sp:
| MEDIUM_SYM {}
| MEMORY_SYM {}
| MERGE_SYM {}
+ | MESSAGE_TEXT_SYM {}
| MICROSECOND_SYM {}
| MIGRATE_SYM {}
| MINUTE_SYM {}
@@ -11552,6 +11825,7 @@ keyword_sp:
| MULTIPOINT {}
| MULTIPOLYGON {}
| MUTEX_SYM {}
+ | MYSQL_ERRNO_SYM {}
| NAME_SYM {}
| NAMES_SYM {}
| NATIONAL_SYM {}
@@ -11611,6 +11885,7 @@ keyword_sp:
| ROW_SYM {}
| RTREE_SYM {}
| SCHEDULE_SYM {}
+ | SCHEMA_NAME_SYM {}
| SECOND_SYM {}
| SERIAL_SYM {}
| SERIALIZABLE_SYM {}
@@ -11629,6 +11904,7 @@ keyword_sp:
| STATUS_SYM {}
| STORAGE_SYM {}
| STRING_SYM {}
+ | SUBCLASS_ORIGIN_SYM {}
| SUBDATE_SYM {}
| SUBJECT_SYM {}
| SUBPARTITION_SYM {}
@@ -11637,6 +11913,7 @@ keyword_sp:
| SUSPEND_SYM {}
| SWAPS_SYM {}
| SWITCHES_SYM {}
+ | TABLE_NAME_SYM {}
| TABLES {}
| TABLE_CHECKSUM_SYM {}
| TABLESPACE {}
@@ -11670,6 +11947,7 @@ keyword_sp:
| WEEK_SYM {}
| WORK_SYM {}
| X509_SYM {}
+ | XML_SYM {}
| YEAR_SYM {}
;
diff --git a/sql/table.cc b/sql/table.cc
index 4442243ec14..d71a3ecd9bb 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1262,7 +1262,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
"Please do \"ALTER TABLE '%s' FORCE\" to fix it!",
share->fieldnames.type_names[i], share->table_name.str,
share->table_name.str);
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CRASHED_ON_USAGE,
"Found incompatible DECIMAL field '%s' in %s; "
"Please do \"ALTER TABLE '%s' FORCE\" to fix it!",
@@ -1464,7 +1464,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
"Please do \"ALTER TABLE '%s' FORCE \" to fix it!",
share->table_name.str,
share->table_name.str);
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CRASHED_ON_USAGE,
"Found wrong key definition in %s; "
"Please do \"ALTER TABLE '%s' FORCE\" to fix "
@@ -3351,20 +3351,20 @@ void TABLE_LIST::hide_view_error(THD *thd)
/* Hide "Unknown column" or "Unknown function" error */
DBUG_ASSERT(thd->is_error());
- if (thd->main_da.sql_errno() == ER_BAD_FIELD_ERROR ||
- thd->main_da.sql_errno() == ER_SP_DOES_NOT_EXIST ||
- thd->main_da.sql_errno() == ER_FUNC_INEXISTENT_NAME_COLLISION ||
- thd->main_da.sql_errno() == ER_PROCACCESS_DENIED_ERROR ||
- thd->main_da.sql_errno() == ER_COLUMNACCESS_DENIED_ERROR ||
- thd->main_da.sql_errno() == ER_TABLEACCESS_DENIED_ERROR ||
- thd->main_da.sql_errno() == ER_TABLE_NOT_LOCKED ||
- thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
+ if (thd->stmt_da->sql_errno() == ER_BAD_FIELD_ERROR ||
+ thd->stmt_da->sql_errno() == ER_SP_DOES_NOT_EXIST ||
+ thd->stmt_da->sql_errno() == ER_FUNC_INEXISTENT_NAME_COLLISION ||
+ thd->stmt_da->sql_errno() == ER_PROCACCESS_DENIED_ERROR ||
+ thd->stmt_da->sql_errno() == ER_COLUMNACCESS_DENIED_ERROR ||
+ thd->stmt_da->sql_errno() == ER_TABLEACCESS_DENIED_ERROR ||
+ thd->stmt_da->sql_errno() == ER_TABLE_NOT_LOCKED ||
+ thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE)
{
TABLE_LIST *top= top_table();
thd->clear_error();
my_error(ER_VIEW_INVALID, MYF(0), top->view_db.str, top->view_name.str);
}
- else if (thd->main_da.sql_errno() == ER_NO_DEFAULT_FOR_FIELD)
+ else if (thd->stmt_da->sql_errno() == ER_NO_DEFAULT_FOR_FIELD)
{
TABLE_LIST *top= top_table();
thd->clear_error();
@@ -3442,7 +3442,7 @@ int TABLE_LIST::view_check_option(THD *thd, bool ignore_failure)
TABLE_LIST *main_view= top_table();
if (ignore_failure)
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_CHECK_FAILED, ER(ER_VIEW_CHECK_FAILED),
main_view->view_db.str, main_view->view_name.str);
return(VIEW_CHECK_SKIP);
diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc
index 0764fe8be33..ed17f7968c0 100644
--- a/sql/thr_malloc.cc
+++ b/sql/thr_malloc.cc
@@ -44,9 +44,10 @@ extern "C" {
returned in the error packet.
- SHOW ERROR/SHOW WARNINGS may be empty.
*/
- thd->main_da.set_error_status(thd,
- ER_OUT_OF_RESOURCES,
- ER(ER_OUT_OF_RESOURCES));
+ thd->stmt_da->set_error_status(thd,
+ ER_OUT_OF_RESOURCES,
+ ER(ER_OUT_OF_RESOURCES),
+ NULL);
}
}
}
diff --git a/sql/time.cc b/sql/time.cc
index 962b65e454c..810d6426a01 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -748,7 +748,7 @@ void make_truncated_value_warning(THD *thd, MYSQL_ERROR::enum_warning_level leve
cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
type_str, str.c_ptr(), field_name,
- (ulong) thd->row_count);
+ (ulong) thd->warning_info->current_row_for_warning());
else
{
if (time_type > MYSQL_TIMESTAMP_ERROR)
diff --git a/sql/tztime.cc b/sql/tztime.cc
index c7a4ad049ec..6757798ad32 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1645,7 +1645,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
if (open_system_tables_for_read(thd, tz_tables, &open_tables_state_backup))
{
sql_print_warning("Can't open and lock time zone table: %s "
- "trying to live without them", thd->main_da.message());
+ "trying to live without them", thd->stmt_da->message());
/* We will try emulate that everything is ok */
return_val= time_zone_tables_exist= 0;
goto end_with_setting_default_tz;
diff --git a/sql/udf_example.c b/sql/udf_example.c
index 30d85d95034..4b39a83d4ac 100644
--- a/sql/udf_example.c
+++ b/sql/udf_example.c
@@ -139,6 +139,11 @@ typedef long long longlong;
#include <mysql.h>
#include <ctype.h>
+#ifdef _WIN32
+/* inet_aton needs winsock library */
+#pragma comment(lib, "ws2_32")
+#endif
+
static pthread_mutex_t LOCK_hostname;
#ifdef HAVE_DLOPEN
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 60674b8390b..18b0786190a 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -55,10 +55,12 @@ static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type,
struct Pack_header_error_handler: public Internal_error_handler
{
- virtual bool handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ MYSQL_ERROR ** cond_hdl);
bool is_handled;
Pack_header_error_handler() :is_handled(FALSE) {}
};
@@ -66,11 +68,14 @@ struct Pack_header_error_handler: public Internal_error_handler
bool
Pack_header_error_handler::
-handle_error(uint sql_errno,
- const char * /* message */,
- MYSQL_ERROR::enum_warning_level /* level */,
- THD * /* thd */)
+handle_condition(THD *,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level,
+ const char*,
+ MYSQL_ERROR ** cond_hdl)
{
+ *cond_hdl= NULL;
is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
return is_handled;
}
diff --git a/storage/blackhole/CMakeLists.txt b/storage/blackhole/CMakeLists.txt
index b762228d7fd..bed282ef21d 100644
--- a/storage/blackhole/CMakeLists.txt
+++ b/storage/blackhole/CMakeLists.txt
@@ -13,9 +13,6 @@
# 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("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(BLACKHOLE_SOURCES ha_blackhole.cc ha_blackhole.h)
diff --git a/storage/csv/CMakeLists.txt b/storage/csv/CMakeLists.txt
index eb21a9b048c..37760588897 100644
--- a/storage/csv/CMakeLists.txt
+++ b/storage/csv/CMakeLists.txt
@@ -13,8 +13,6 @@
# 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("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(CSV_SOURCES ha_tina.cc ha_tina.h transparent_file.cc transparent_file.h)
diff --git a/storage/example/CMakeLists.txt b/storage/example/CMakeLists.txt
index a328da107bd..f0b1343ab9c 100644
--- a/storage/example/CMakeLists.txt
+++ b/storage/example/CMakeLists.txt
@@ -13,8 +13,6 @@
# 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("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(EXAMPLE_SOURCES ha_example.cc)
MYSQL_STORAGE_ENGINE(EXAMPLE)
diff --git a/storage/heap/CMakeLists.txt b/storage/heap/CMakeLists.txt
index c2d2cd1290f..4a0fa22c8f1 100755
--- a/storage/heap/CMakeLists.txt
+++ b/storage/heap/CMakeLists.txt
@@ -13,8 +13,6 @@
# 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("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(HEAP_SOURCES _check.c _rectest.c hp_block.c hp_clear.c hp_close.c hp_create.c
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index f4d8e7b8231..31d33f06823 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -16,11 +16,7 @@
# This is the CMakeLists for InnoDB Plugin
-# TODO: remove the two FLAGS_DEBUG settings when merging into
-# 6.0-based trees, like is already the case for other engines in
-# those trees.
-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("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
# Include directories under innobase
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index f9c893ac845..524bd8ac828 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1135,7 +1135,29 @@ innobase_mysql_tmpfile(void)
will be passed to fdopen(), it will be closed by invoking
fclose(), which in turn will invoke close() instead of
my_close(). */
+
+#ifdef _WIN32
+ /* Note that on Windows, the integer returned by mysql_tmpfile
+ has no relation to C runtime file descriptor. Here, we need
+ to call my_get_osfhandle to get the HANDLE and then convert it
+ to C runtime filedescriptor. */
+ {
+ HANDLE hFile = my_get_osfhandle(fd);
+ HANDLE hDup;
+ BOOL bOK =
+ DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(),
+ &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ if(bOK) {
+ fd2 = _open_osfhandle((intptr_t)hDup,0);
+ }
+ else {
+ my_osmaperr(GetLastError());
+ fd2 = -1;
+ }
+ }
+#else
fd2 = dup(fd);
+#endif
if (fd2 < 0) {
DBUG_PRINT("error",("Got error %d on dup",fd2));
my_errno=errno;
diff --git a/storage/myisam/CMakeLists.txt b/storage/myisam/CMakeLists.txt
index c05e0046e64..829d89a798a 100755
--- a/storage/myisam/CMakeLists.txt
+++ b/storage/myisam/CMakeLists.txt
@@ -15,8 +15,6 @@
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake")
-SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
-SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
SET(MYISAM_SOURCES ft_boolean_search.c ft_nlq_search.c ft_parser.c ft_static.c ft_stem.c
ha_myisam.cc
@@ -34,16 +32,16 @@ MYSQL_STORAGE_ENGINE(MYISAM)
IF(NOT SOURCE_SUBLIBS)
ADD_EXECUTABLE(myisam_ftdump myisam_ftdump.c)
- TARGET_LINK_LIBRARIES(myisam_ftdump myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(myisam_ftdump myisam mysys dbug strings zlib)
ADD_EXECUTABLE(myisamchk myisamchk.c)
- TARGET_LINK_LIBRARIES(myisamchk myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(myisamchk myisam mysys dbug strings zlib)
ADD_EXECUTABLE(myisamlog myisamlog.c)
- TARGET_LINK_LIBRARIES(myisamlog myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(myisamlog myisam mysys dbug strings zlib)
ADD_EXECUTABLE(myisampack myisampack.c)
- TARGET_LINK_LIBRARIES(myisampack myisam mysys debug dbug strings zlib wsock32)
+ TARGET_LINK_LIBRARIES(myisampack myisam mysys dbug strings zlib)
SET_TARGET_PROPERTIES(myisamchk myisampack PROPERTIES LINK_FLAGS "setargv.obj")
diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c
index 6a4c21160f4..8a5866ae763 100644
--- a/storage/myisam/mi_locking.c
+++ b/storage/myisam/mi_locking.c
@@ -236,7 +236,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
break; /* Impossible */
}
}
-#ifdef __WIN__
+#ifdef _WIN32
else
{
/*
@@ -455,11 +455,11 @@ int _mi_writeinfo(register MI_INFO *info, uint operation)
share->state.update_count= info->last_loop= ++info->this_loop;
if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
olderror=my_errno;
-#ifdef __WIN__
+#ifdef _WIN32
if (myisam_flush)
{
- _commit(share->kfile);
- _commit(info->dfile);
+ my_sync(share->kfile,0);
+ my_sync(info->dfile,0);
}
#endif
}
diff --git a/storage/myisammrg/CMakeLists.txt b/storage/myisammrg/CMakeLists.txt
index 60cfffc67ff..c545d04a780 100755
--- a/storage/myisammrg/CMakeLists.txt
+++ b/storage/myisammrg/CMakeLists.txt
@@ -12,8 +12,6 @@
# 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("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index addec5bb58a..471e2243aac 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -153,7 +153,7 @@ extern "C" void myrg_print_wrong_table(const char *table_name)
buf[db.length]= '.';
memcpy(buf + db.length + 1, name.str, name.length);
buf[db.length + name.length + 1]= 0;
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ADMIN_WRONG_MRG_TABLE, ER(ER_ADMIN_WRONG_MRG_TABLE),
buf);
}
diff --git a/strings/CMakeLists.txt b/strings/CMakeLists.txt
index 3d9de566670..294a129fc1b 100755
--- a/strings/CMakeLists.txt
+++ b/strings/CMakeLists.txt
@@ -13,9 +13,6 @@
# 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} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
-SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
-
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
SET(STRINGS_SOURCES bchange.c bcmp.c bfill.c bmove512.c bmove_upp.c ctype-big5.c ctype-bin.c ctype-cp932.c
diff --git a/strings/conf_to_src.c b/strings/conf_to_src.c
index 7e742050aa8..9f1ed9b2441 100644
--- a/strings/conf_to_src.c
+++ b/strings/conf_to_src.c
@@ -184,11 +184,12 @@ void dispcset(FILE *f,CHARSET_INFO *cs)
{
fprintf(f,"{\n");
fprintf(f," %d,%d,%d,\n",cs->number,0,0);
- fprintf(f," MY_CS_COMPILED%s%s%s%s,\n",
+ fprintf(f," MY_CS_COMPILED%s%s%s%s%s,\n",
cs->state & MY_CS_BINSORT ? "|MY_CS_BINSORT" : "",
cs->state & MY_CS_PRIMARY ? "|MY_CS_PRIMARY" : "",
is_case_sensitive(cs) ? "|MY_CS_CSSORT" : "",
- my_charset_is_8bit_pure_ascii(cs) ? "|MY_CS_PUREASCII" : "");
+ my_charset_is_8bit_pure_ascii(cs) ? "|MY_CS_PUREASCII" : "",
+ !my_charset_is_ascii_compatible(cs) ? "|MY_CS_NONASCII": "");
if (cs->name)
{
diff --git a/strings/ctype-extra.c b/strings/ctype-extra.c
index 75244e40435..ba12f3f4267 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
@@ -6804,7 +6804,7 @@ CHARSET_INFO compiled_charsets[] = {
#ifdef HAVE_CHARSET_swe7
{
10,0,0,
- MY_CS_COMPILED|MY_CS_PRIMARY,
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_NONASCII,
"swe7", /* cset name */
"swe7_swedish_ci", /* coll name */
"", /* comment */
@@ -8454,7 +8454,7 @@ CHARSET_INFO compiled_charsets[] = {
#ifdef HAVE_CHARSET_swe7
{
82,0,0,
- MY_CS_COMPILED|MY_CS_BINSORT,
+ MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_NONASCII,
"swe7", /* cset name */
"swe7_bin", /* coll name */
"", /* comment */
@@ -8550,72 +8550,6 @@ CHARSET_INFO compiled_charsets[] = {
}
,
#endif
-#ifdef HAVE_CHARSET_geostd8
-{
- 92,0,0,
- MY_CS_COMPILED|MY_CS_PRIMARY,
- "geostd8", /* cset name */
- "geostd8_general_ci", /* coll name */
- "", /* comment */
- NULL, /* tailoring */
- ctype_geostd8_general_ci, /* ctype */
- to_lower_geostd8_general_ci, /* lower */
- to_upper_geostd8_general_ci, /* upper */
- sort_order_geostd8_general_ci, /* sort_order */
- NULL, /* contractions */
- NULL, /* sort_order_big*/
- to_uni_geostd8_general_ci, /* to_uni */
- NULL, /* from_uni */
- my_unicase_default, /* caseinfo */
- NULL, /* state map */
- NULL, /* ident map */
- 1, /* strxfrm_multiply*/
- 1, /* caseup_multiply*/
- 1, /* casedn_multiply*/
- 1, /* mbminlen */
- 1, /* mbmaxlen */
- 0, /* min_sort_char */
- 255, /* max_sort_char */
- ' ', /* pad_char */
- 0, /* escape_with_backslash_is_dangerous */
- &my_charset_8bit_handler,
- &my_collation_8bit_simple_ci_handler,
-}
-,
-#endif
-#ifdef HAVE_CHARSET_geostd8
-{
- 93,0,0,
- MY_CS_COMPILED|MY_CS_BINSORT,
- "geostd8", /* cset name */
- "geostd8_bin", /* coll name */
- "", /* comment */
- NULL, /* tailoring */
- ctype_geostd8_bin, /* ctype */
- to_lower_geostd8_bin, /* lower */
- to_upper_geostd8_bin, /* upper */
- NULL, /* sort_order */
- NULL, /* contractions */
- NULL, /* sort_order_big*/
- to_uni_geostd8_bin, /* to_uni */
- NULL, /* from_uni */
- my_unicase_default, /* caseinfo */
- NULL, /* state map */
- NULL, /* ident map */
- 1, /* strxfrm_multiply*/
- 1, /* caseup_multiply*/
- 1, /* casedn_multiply*/
- 1, /* mbminlen */
- 1, /* mbmaxlen */
- 0, /* min_sort_char */
- 255, /* max_sort_char */
- ' ', /* pad_char */
- 0, /* escape_with_backslash_is_dangerous */
- &my_charset_8bit_handler,
- &my_collation_8bit_bin_handler,
-}
-,
-#endif
#ifdef HAVE_CHARSET_latin1
{
94,0,0,
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index ac426e0d7b5..60280efe087 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -4672,7 +4672,7 @@ static MY_CHARSET_HANDLER my_charset_handler=
CHARSET_INFO my_charset_sjis_japanese_ci=
{
13,0,0, /* number */
- MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_NONASCII, /* state */
"sjis", /* cs name */
"sjis_japanese_ci", /* name */
"", /* comment */
@@ -4704,7 +4704,7 @@ CHARSET_INFO my_charset_sjis_japanese_ci=
CHARSET_INFO my_charset_sjis_bin=
{
88,0,0, /* number */
- MY_CS_COMPILED|MY_CS_BINSORT, /* state */
+ MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_NONASCII, /* state */
"sjis", /* cs name */
"sjis_bin", /* name */
"", /* comment */
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index 2ea48ddab2f..ecf92c1b7d4 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -6712,6 +6712,34 @@ static const char hungarian[]=
"&O < \\u00F6 <<< \\u00D6 << \\u0151 <<< \\u0150"
"&U < \\u00FC <<< \\u00DC << \\u0171 <<< \\u0170";
+/*
+ SCCII Part 1 : Collation Sequence (SLS1134)
+ 2006/11/24
+ Harshula Jayasuriya <harshula at gmail dot com>
+ Language Technology Research Lab, University of Colombo / ICTA
+*/
+#if 0
+static const char sinhala[]=
+ "& \\u0D96 < \\u0D82 < \\u0D83"
+ "& \\u0DA5 < \\u0DA4"
+ "& \\u0DD8 < \\u0DF2 < \\u0DDF < \\u0DF3"
+ "& \\u0DDE < \\u0DCA";
+#else
+static const char sinhala[]=
+ "& \\u0D96 < \\u0D82 < \\u0D83 < \\u0D9A < \\u0D9B < \\u0D9C < \\u0D9D"
+ "< \\u0D9E < \\u0D9F < \\u0DA0 < \\u0DA1 < \\u0DA2 < \\u0DA3"
+ "< \\u0DA5 < \\u0DA4 < \\u0DA6"
+ "< \\u0DA7 < \\u0DA8 < \\u0DA9 < \\u0DAA < \\u0DAB < \\u0DAC"
+ "< \\u0DAD < \\u0DAE < \\u0DAF < \\u0DB0 < \\u0DB1"
+ "< \\u0DB3 < \\u0DB4 < \\u0DB5 < \\u0DB6 < \\u0DB7 < \\u0DB8"
+ "< \\u0DB9 < \\u0DBA < \\u0DBB < \\u0DBD < \\u0DC0 < \\u0DC1"
+ "< \\u0DC2 < \\u0DC3 < \\u0DC4 < \\u0DC5 < \\u0DC6"
+ "< \\u0DCF"
+ "< \\u0DD0 < \\u0DD1 < \\u0DD2 < \\u0DD3 < \\u0DD4 < \\u0DD6"
+ "< \\u0DD8 < \\u0DF2 < \\u0DDF < \\u0DF3 < \\u0DD9 < \\u0DDA"
+ "< \\u0DDB < \\u0DDC < \\u0DDD < \\u0DDE < \\u0DCA";
+#endif
+
/*
Unicode Collation Algorithm:
@@ -8087,7 +8115,7 @@ MY_COLLATION_HANDLER my_collation_ucs2_uca_handler =
CHARSET_INFO my_charset_ucs2_unicode_ci=
{
128,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_unicode_ci", /* name */
"", /* comment */
@@ -8119,7 +8147,7 @@ CHARSET_INFO my_charset_ucs2_unicode_ci=
CHARSET_INFO my_charset_ucs2_icelandic_uca_ci=
{
129,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_icelandic_ci",/* name */
"", /* comment */
@@ -8151,7 +8179,7 @@ CHARSET_INFO my_charset_ucs2_icelandic_uca_ci=
CHARSET_INFO my_charset_ucs2_latvian_uca_ci=
{
130,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_latvian_ci", /* name */
"", /* comment */
@@ -8183,7 +8211,7 @@ CHARSET_INFO my_charset_ucs2_latvian_uca_ci=
CHARSET_INFO my_charset_ucs2_romanian_uca_ci=
{
131,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_romanian_ci", /* name */
"", /* comment */
@@ -8215,7 +8243,7 @@ CHARSET_INFO my_charset_ucs2_romanian_uca_ci=
CHARSET_INFO my_charset_ucs2_slovenian_uca_ci=
{
132,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_slovenian_ci",/* name */
"", /* comment */
@@ -8247,7 +8275,7 @@ CHARSET_INFO my_charset_ucs2_slovenian_uca_ci=
CHARSET_INFO my_charset_ucs2_polish_uca_ci=
{
133,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_polish_ci", /* name */
"", /* comment */
@@ -8279,7 +8307,7 @@ CHARSET_INFO my_charset_ucs2_polish_uca_ci=
CHARSET_INFO my_charset_ucs2_estonian_uca_ci=
{
134,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_estonian_ci", /* name */
"", /* comment */
@@ -8311,7 +8339,7 @@ CHARSET_INFO my_charset_ucs2_estonian_uca_ci=
CHARSET_INFO my_charset_ucs2_spanish_uca_ci=
{
135,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_spanish_ci", /* name */
"", /* comment */
@@ -8343,7 +8371,7 @@ CHARSET_INFO my_charset_ucs2_spanish_uca_ci=
CHARSET_INFO my_charset_ucs2_swedish_uca_ci=
{
136,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_swedish_ci", /* name */
"", /* comment */
@@ -8375,7 +8403,7 @@ CHARSET_INFO my_charset_ucs2_swedish_uca_ci=
CHARSET_INFO my_charset_ucs2_turkish_uca_ci=
{
137,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_turkish_ci", /* name */
"", /* comment */
@@ -8407,7 +8435,7 @@ CHARSET_INFO my_charset_ucs2_turkish_uca_ci=
CHARSET_INFO my_charset_ucs2_czech_uca_ci=
{
138,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_czech_ci", /* name */
"", /* comment */
@@ -8440,7 +8468,7 @@ CHARSET_INFO my_charset_ucs2_czech_uca_ci=
CHARSET_INFO my_charset_ucs2_danish_uca_ci=
{
139,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_danish_ci", /* name */
"", /* comment */
@@ -8472,7 +8500,7 @@ CHARSET_INFO my_charset_ucs2_danish_uca_ci=
CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci=
{
140,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_lithuanian_ci",/* name */
"", /* comment */
@@ -8504,7 +8532,7 @@ CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci=
CHARSET_INFO my_charset_ucs2_slovak_uca_ci=
{
141,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_slovak_ci", /* name */
"", /* comment */
@@ -8536,7 +8564,7 @@ CHARSET_INFO my_charset_ucs2_slovak_uca_ci=
CHARSET_INFO my_charset_ucs2_spanish2_uca_ci=
{
142,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_spanish2_ci", /* name */
"", /* comment */
@@ -8569,7 +8597,7 @@ CHARSET_INFO my_charset_ucs2_spanish2_uca_ci=
CHARSET_INFO my_charset_ucs2_roman_uca_ci=
{
143,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_roman_ci", /* name */
"", /* comment */
@@ -8602,7 +8630,7 @@ CHARSET_INFO my_charset_ucs2_roman_uca_ci=
CHARSET_INFO my_charset_ucs2_persian_uca_ci=
{
144,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_persian_ci", /* name */
"", /* comment */
@@ -8635,7 +8663,7 @@ CHARSET_INFO my_charset_ucs2_persian_uca_ci=
CHARSET_INFO my_charset_ucs2_esperanto_uca_ci=
{
145,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_esperanto_ci",/* name */
"", /* comment */
@@ -8668,7 +8696,7 @@ CHARSET_INFO my_charset_ucs2_esperanto_uca_ci=
CHARSET_INFO my_charset_ucs2_hungarian_uca_ci=
{
146,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_hungarian_ci",/* name */
"", /* comment */
@@ -8698,6 +8726,39 @@ CHARSET_INFO my_charset_ucs2_hungarian_uca_ci=
};
+CHARSET_INFO my_charset_ucs2_sinhala_uca_ci=
+{
+ 147,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "ucs2", /* csname */
+ "ucs2_sinhala_ci", /* name */
+ "", /* comment */
+ sinhala, /* tailoring */
+ NULL, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
+ 2, /* mbminlen */
+ 2, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ ' ', /* pad char */
+ 0, /* escape_with_backslash_is_dangerous */
+ &my_charset_ucs2_handler,
+ &my_collation_ucs2_uca_handler
+};
+
+
#endif
@@ -8748,7 +8809,7 @@ extern MY_CHARSET_HANDLER my_charset_utf8_handler;
CHARSET_INFO my_charset_utf8_unicode_ci=
{
192,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_unicode_ci", /* name */
"", /* comment */
@@ -8781,7 +8842,7 @@ CHARSET_INFO my_charset_utf8_unicode_ci=
CHARSET_INFO my_charset_utf8_icelandic_uca_ci=
{
193,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_icelandic_ci",/* name */
"", /* comment */
@@ -8813,7 +8874,7 @@ CHARSET_INFO my_charset_utf8_icelandic_uca_ci=
CHARSET_INFO my_charset_utf8_latvian_uca_ci=
{
194,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_latvian_ci", /* name */
"", /* comment */
@@ -8845,7 +8906,7 @@ CHARSET_INFO my_charset_utf8_latvian_uca_ci=
CHARSET_INFO my_charset_utf8_romanian_uca_ci=
{
195,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_romanian_ci", /* name */
"", /* comment */
@@ -8877,7 +8938,7 @@ CHARSET_INFO my_charset_utf8_romanian_uca_ci=
CHARSET_INFO my_charset_utf8_slovenian_uca_ci=
{
196,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_slovenian_ci",/* name */
"", /* comment */
@@ -8909,7 +8970,7 @@ CHARSET_INFO my_charset_utf8_slovenian_uca_ci=
CHARSET_INFO my_charset_utf8_polish_uca_ci=
{
197,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_polish_ci", /* name */
"", /* comment */
@@ -8941,7 +9002,7 @@ CHARSET_INFO my_charset_utf8_polish_uca_ci=
CHARSET_INFO my_charset_utf8_estonian_uca_ci=
{
198,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_estonian_ci", /* name */
"", /* comment */
@@ -8973,7 +9034,7 @@ CHARSET_INFO my_charset_utf8_estonian_uca_ci=
CHARSET_INFO my_charset_utf8_spanish_uca_ci=
{
199,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_spanish_ci", /* name */
"", /* comment */
@@ -9005,7 +9066,7 @@ CHARSET_INFO my_charset_utf8_spanish_uca_ci=
CHARSET_INFO my_charset_utf8_swedish_uca_ci=
{
200,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_swedish_ci", /* name */
"", /* comment */
@@ -9037,7 +9098,7 @@ CHARSET_INFO my_charset_utf8_swedish_uca_ci=
CHARSET_INFO my_charset_utf8_turkish_uca_ci=
{
201,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_turkish_ci", /* name */
"", /* comment */
@@ -9069,7 +9130,7 @@ CHARSET_INFO my_charset_utf8_turkish_uca_ci=
CHARSET_INFO my_charset_utf8_czech_uca_ci=
{
202,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_czech_ci", /* name */
"", /* comment */
@@ -9102,7 +9163,7 @@ CHARSET_INFO my_charset_utf8_czech_uca_ci=
CHARSET_INFO my_charset_utf8_danish_uca_ci=
{
203,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_danish_ci", /* name */
"", /* comment */
@@ -9134,7 +9195,7 @@ CHARSET_INFO my_charset_utf8_danish_uca_ci=
CHARSET_INFO my_charset_utf8_lithuanian_uca_ci=
{
204,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_lithuanian_ci",/* name */
"", /* comment */
@@ -9166,7 +9227,7 @@ CHARSET_INFO my_charset_utf8_lithuanian_uca_ci=
CHARSET_INFO my_charset_utf8_slovak_uca_ci=
{
205,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_slovak_ci", /* name */
"", /* comment */
@@ -9198,7 +9259,7 @@ CHARSET_INFO my_charset_utf8_slovak_uca_ci=
CHARSET_INFO my_charset_utf8_spanish2_uca_ci=
{
206,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_spanish2_ci", /* name */
"", /* comment */
@@ -9230,7 +9291,7 @@ CHARSET_INFO my_charset_utf8_spanish2_uca_ci=
CHARSET_INFO my_charset_utf8_roman_uca_ci=
{
207,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_roman_ci", /* name */
"", /* comment */
@@ -9262,7 +9323,7 @@ CHARSET_INFO my_charset_utf8_roman_uca_ci=
CHARSET_INFO my_charset_utf8_persian_uca_ci=
{
208,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_persian_ci", /* name */
"", /* comment */
@@ -9294,7 +9355,7 @@ CHARSET_INFO my_charset_utf8_persian_uca_ci=
CHARSET_INFO my_charset_utf8_esperanto_uca_ci=
{
209,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_esperanto_ci",/* name */
"", /* comment */
@@ -9326,7 +9387,7 @@ CHARSET_INFO my_charset_utf8_esperanto_uca_ci=
CHARSET_INFO my_charset_utf8_hungarian_uca_ci=
{
210,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"utf8", /* cs name */
"utf8_hungarian_ci",/* name */
"", /* comment */
@@ -9355,6 +9416,38 @@ CHARSET_INFO my_charset_utf8_hungarian_uca_ci=
&my_collation_any_uca_handler
};
+CHARSET_INFO my_charset_utf8_sinhala_uca_ci=
+{
+ 211,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ "utf8", /* cs name */
+ "utf8_sinhala_ci", /* name */
+ "", /* comment */
+ sinhala, /* tailoring */
+ ctype_utf8, /* ctype */
+ NULL, /* to_lower */
+ NULL, /* to_upper */
+ NULL, /* sort_order */
+ NULL, /* contractions */
+ NULL, /* sort_order_big*/
+ NULL, /* tab_to_uni */
+ NULL, /* tab_from_uni */
+ my_unicase_default, /* caseinfo */
+ NULL, /* state_map */
+ NULL, /* ident_map */
+ 8, /* strxfrm_multiply */
+ 1, /* caseup_multiply */
+ 1, /* casedn_multiply */
+ 3, /* mbminlen */
+ 3, /* mbmaxlen */
+ 9, /* min_sort_char */
+ 0xFFFF, /* max_sort_char */
+ ' ', /* pad char */
+ 0, /* escape_with_backslash_is_dangerous */
+ &my_charset_utf8_handler,
+ &my_collation_any_uca_handler
+};
+
#endif /* HAVE_CHARSET_utf8 */
#endif /* HAVE_UCA_COLLATIONS */
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index a1c691a462b..f030c08523c 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -1712,7 +1712,7 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler=
CHARSET_INFO my_charset_ucs2_general_ci=
{
35,0,0, /* number */
- MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_general_ci", /* name */
"", /* comment */
@@ -1744,7 +1744,7 @@ CHARSET_INFO my_charset_ucs2_general_ci=
CHARSET_INFO my_charset_ucs2_bin=
{
90,0,0, /* number */
- MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE,
+ MY_CS_COMPILED|MY_CS_BINSORT|MY_CS_UNICODE|MY_CS_NONASCII,
"ucs2", /* cs name */
"ucs2_bin", /* name */
"", /* comment */
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index ae942b59caa..91f633e45ce 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -4200,7 +4200,7 @@ static MY_CHARSET_HANDLER my_charset_filename_handler=
CHARSET_INFO my_charset_filename=
{
17,0,0, /* number */
- MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_HIDDEN,
+ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM|MY_CS_UNICODE|MY_CS_HIDDEN|MY_CS_NONASCII,
"filename", /* cs name */
"filename", /* name */
"", /* comment */
diff --git a/strings/ctype.c b/strings/ctype.c
index 17ad1256e74..75d76aceea3 100644
--- a/strings/ctype.c
+++ b/strings/ctype.c
@@ -405,3 +405,23 @@ my_charset_is_8bit_pure_ascii(CHARSET_INFO *cs)
}
return 1;
}
+
+
+/*
+ Shared function between conf_to_src and mysys.
+ Check if a 8bit character set is compatible with
+ ascii on the range 0x00..0x7F.
+*/
+my_bool
+my_charset_is_ascii_compatible(CHARSET_INFO *cs)
+{
+ uint i;
+ if (!cs->tab_to_uni)
+ return 1;
+ for (i= 0; i < 128; i++)
+ {
+ if (cs->tab_to_uni[i] != i)
+ return 0;
+ }
+ return 1;
+}
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index 87198fc9cf5..ccf4d8ff51d 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -53,13 +53,14 @@ datadir=
# Negative numbers mean to wait indefinitely
service_startup_timeout=900
+# Lock directory for RedHat / SuSE.
+lockdir='/var/lock/subsys'
+lock_file_path="$lockdir/mysql"
+
# The following variables are only set for letting mysql.server find things.
# Set some defaults
-pid_file=
-server_pid_file=
-use_mysqld_safe=1
-user=@MYSQLD_USER@
+mysqld_pid_file_path=
if test -z "$basedir"
then
basedir=@prefix@
@@ -101,11 +102,14 @@ else
}
fi
-PATH=/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin
+PATH="/sbin:/usr/sbin:/bin:/usr/bin:$basedir/bin"
export PATH
mode=$1 # start or stop
-shift
+
+[ $# -ge 1 ] && shift
+
+
other_args="$*" # uncommon, but needed when called from an RPM upgrade action
# Expected: "--skip-networking --skip-grant-tables"
# They are not checked here, intentionally, as it is the resposibility
@@ -131,59 +135,50 @@ parse_server_arguments() {
--datadir=*) datadir=`echo "$arg" | sed -e 's/^[^=]*=//'`
datadir_set=1
;;
- --user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
- --pid-file=*) server_pid_file=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --pid-file=*) mysqld_pid_file_path=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--service-startup-timeout=*) service_startup_timeout=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
- --use-mysqld_safe) use_mysqld_safe=1;;
- --use-manager) use_mysqld_safe=0;;
- esac
- done
-}
-
-parse_manager_arguments() {
- for arg do
- case "$arg" in
- --pid-file=*) pid_file=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
- --user=*) user=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
esac
done
}
wait_for_pid () {
- verb="$1"
- manager_pid="$2" # process ID of the program operating on the pid-file
+ verb="$1" # created | removed
+ pid="$2" # process ID of the program operating on the pid-file
+ pid_file_path="$3" # path to the PID file.
+
i=0
avoid_race_condition="by checking again"
+
while test $i -ne $service_startup_timeout ; do
case "$verb" in
'created')
# wait for a PID-file to pop into existence.
- test -s $pid_file && i='' && break
+ test -s "$pid_file_path" && i='' && break
;;
'removed')
# wait for this PID-file to disappear
- test ! -s $pid_file && i='' && break
+ test ! -s "$pid_file_path" && i='' && break
;;
*)
- echo "wait_for_pid () usage: wait_for_pid created|removed manager_pid"
+ echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"
exit 1
;;
esac
- # if manager isn't running, then pid-file will never be updated
- if test -n "$manager_pid"; then
- if kill -0 "$manager_pid" 2>/dev/null; then
- : # the manager still runs
+ # if server isn't running, then pid-file will never be updated
+ if test -n "$pid"; then
+ if kill -0 "$pid" 2>/dev/null; then
+ : # the server still runs
else
- # The manager may have exited between the last pid-file check and now.
+ # The server may have exited between the last pid-file check and now.
if test -n "$avoid_race_condition"; then
avoid_race_condition=""
continue # Check again.
fi
# there's nothing that will affect the file.
- log_failure_msg "Manager of pid-file quit without updating file."
+ log_failure_msg "The server quit without updating PID file ($pid_file_path)."
return 1 # not waiting any more.
fi
fi
@@ -191,6 +186,7 @@ wait_for_pid () {
echo $echo_n ".$echo_c"
i=`expr $i + 1`
sleep 1
+
done
if test -z "$i" ; then
@@ -259,28 +255,16 @@ fi
parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`
-# Look for the pidfile
-parse_manager_arguments `$print_defaults $extra_args manager`
-
#
# Set pid file if not given
#
-if test -z "$pid_file"
-then
- pid_file=$datadir/mysqlmanager-`@HOSTNAME@`.pid
-else
- case "$pid_file" in
- /* ) ;;
- * ) pid_file="$datadir/$pid_file" ;;
- esac
-fi
-if test -z "$server_pid_file"
+if test -z "$mysqld_pid_file_path"
then
- server_pid_file=$datadir/`@HOSTNAME@`.pid
+ mysqld_pid_file_path=$datadir/`@HOSTNAME@`.pid
else
- case "$server_pid_file" in
+ case "$mysqld_pid_file_path" in
/* ) ;;
- * ) server_pid_file="$datadir/$server_pid_file" ;;
+ * ) mysqld_pid_file_path="$datadir/$mysqld_pid_file_path" ;;
esac
fi
@@ -291,53 +275,23 @@ case "$mode" in
# Safeguard (relative paths, core dumps..)
cd $basedir
- manager=$bindir/mysqlmanager
- if test -x $libexecdir/mysqlmanager
- then
- manager=$libexecdir/mysqlmanager
- elif test -x $sbindir/mysqlmanager
- then
- manager=$sbindir/mysqlmanager
- fi
-
echo $echo_n "Starting MySQL"
- if test -x $manager -a "$use_mysqld_safe" = "0"
- then
- if test -n "$other_args"
- then
- log_failure_msg "MySQL manager does not support options '$other_args'"
- exit 1
- fi
- # Give extra arguments to mysqld with the my.cnf file. This script may
- # be overwritten at next upgrade.
- "$manager" \
- --mysqld-safe-compatible \
- --user="$user" \
- --pid-file="$pid_file" >/dev/null 2>&1 &
- wait_for_pid created $!; return_value=$?
-
- # Make lock for RedHat / SuSE
- if test -w /var/lock/subsys
- then
- touch /var/lock/subsys/mysqlmanager
- fi
- exit $return_value
- elif test -x $bindir/mysqld_safe
+ if test -x $bindir/mysqld_safe
then
# Give extra arguments to mysqld with the my.cnf file. This script
# may be overwritten at next upgrade.
- pid_file=$server_pid_file
- $bindir/mysqld_safe --datadir=$datadir --pid-file=$server_pid_file $other_args >/dev/null 2>&1 &
- wait_for_pid created $!; return_value=$?
+ $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null 2>&1 &
+ wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?
# Make lock for RedHat / SuSE
- if test -w /var/lock/subsys
+ if test -w "$lockdir"
then
- touch /var/lock/subsys/mysql
+ touch "$lock_file_path"
fi
+
exit $return_value
else
- log_failure_msg "Couldn't find MySQL manager ($manager) or server ($bindir/mysqld_safe)"
+ log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)"
fi
;;
@@ -345,39 +299,29 @@ case "$mode" in
# Stop daemon. We use a signal here to avoid having to know the
# root password.
- # The RedHat / SuSE lock directory to remove
- lock_dir=/var/lock/subsys/mysqlmanager
-
- # If the manager pid_file doesn't exist, try the server's
- if test ! -s "$pid_file"
+ if test -s "$mysqld_pid_file_path"
then
- pid_file=$server_pid_file
- lock_dir=/var/lock/subsys/mysql
- fi
+ mysqld_pid=`cat "$mysqld_pid_file_path"`
- if test -s "$pid_file"
- then
- mysqlmanager_pid=`cat $pid_file`
-
- if (kill -0 $mysqlmanager_pid 2>/dev/null)
+ if (kill -9 $mysqld_pid 2>/dev/null)
then
echo $echo_n "Shutting down MySQL"
- kill $mysqlmanager_pid
- # mysqlmanager should remove the pid_file when it exits, so wait for it.
- wait_for_pid removed "$mysqlmanager_pid"; return_value=$?
+ kill $mysqld_pid
+ # mysqld should remove the pid file when it exits, so wait for it.
+ wait_for_pid removed "$mysqld_pid" "$mysqld_pid_file_path"; return_value=$?
else
- log_failure_msg "MySQL manager or server process #$mysqlmanager_pid is not running!"
- rm $pid_file
+ log_failure_msg "MySQL server process #$mysqld_pid is not running!"
+ rm "$mysqld_pid_file_path"
fi
-
- # delete lock for RedHat / SuSE
- if test -f $lock_dir
+
+ # Delete lock for RedHat / SuSE
+ if test -f "$lock_file_path"
then
- rm -f $lock_dir
+ rm -f "$lock_file_path"
fi
exit $return_value
else
- log_failure_msg "MySQL manager or server PID file could not be found!"
+ log_failure_msg "MySQL server PID file could not be found!"
fi
;;
@@ -393,10 +337,10 @@ case "$mode" in
;;
'reload'|'force-reload')
- if test -s "$server_pid_file" ; then
- read mysqld_pid < $server_pid_file
+ if test -s "$mysqld_pid_file_path" ; then
+ read mysqld_pid < "$mysqld_pid_file_path"
kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL"
- touch $server_pid_file
+ touch "$mysqld_pid_file_path"
else
log_failure_msg "MySQL PID file could not be found!"
exit 1
@@ -404,8 +348,8 @@ case "$mode" in
;;
'status')
# First, check to see if pid file exists
- if test -s "$server_pid_file" ; then
- read mysqld_pid < $server_pid_file
+ if test -s "$mysqld_pid_file_path" ; then
+ read mysqld_pid < "$mysqld_pid_file_path"
if kill -0 $mysqld_pid 2>/dev/null ; then
log_success_msg "MySQL running ($mysqld_pid)"
exit 0
@@ -417,13 +361,8 @@ case "$mode" in
# Try to find appropriate mysqld process
mysqld_pid=`pidof $libexecdir/mysqld`
if test -z $mysqld_pid ; then
- if test "$use_mysqld_safe" = "0" ; then
- lockfile=/var/lock/subsys/mysqlmanager
- else
- lockfile=/var/lock/subsys/mysql
- fi
- if test -f $lockfile ; then
- log_failure_msg "MySQL is not running, but lock exists"
+ if test -f "$lock_file_path" ; then
+ log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists"
exit 2
fi
log_failure_msg "MySQL is not running"
@@ -436,7 +375,8 @@ case "$mode" in
;;
*)
# usage
- echo "Usage: $0 {start|stop|restart|reload|force-reload|status} [ MySQL server options ]"
+ basename=`basename "$0"`
+ echo "Usage: $basename {start|stop|restart|reload|force-reload|status} [ MySQL server options ]"
exit 1
;;
esac
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 60bf9213362..d5bb18d8483 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -465,8 +465,8 @@ rm -fr $RBR%{_datadir}/sql-bench
# will appreciate that, as all services usually offer this.
ln -s %{_sysconfdir}/init.d/mysql $RPM_BUILD_ROOT%{_sbindir}/rcmysql
-# Touch the place where the my.cnf config file might be located
-# Just to make sure it's in the file list and marked as a config file
+# Touch the place where the my.cnf config file might be located.
+# Just to make sure it's in the file list and marked as a config file.
touch $RBR%{_sysconfdir}/my.cnf
%pre server
@@ -867,6 +867,10 @@ fi
# itself - note that they must be ordered by date (important when
# merging BK trees)
%changelog
+* Fri Oct 02 2009 Alexander Nozdrin <alexander.nozdrin@sun.com>
+
+- "mysqlmanager" got removed from version 5.4, all references deleted.
+
* Fri Aug 28 2009 Joerg Bruehe <joerg.bruehe@sun.com>
- Merge up from 5.1 to 5.4: Remove handling for the InnoDB plugin.
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 2093fc0da36..0ee8769cd23 100755
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -13,15 +13,12 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-# About "mysqlclient_notls", see note in "client/CMakeLists.txt"
-
-SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
ADD_DEFINITIONS("-DMYSQL_CLIENT")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
ADD_EXECUTABLE(mysql_client_test mysql_client_test.c ../mysys/my_memmem.c)
-TARGET_LINK_LIBRARIES(mysql_client_test mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(mysql_client_test mysqlclient)
ADD_EXECUTABLE(bug25714 bug25714.c)
-TARGET_LINK_LIBRARIES(bug25714 mysqlclient_notls wsock32)
+TARGET_LINK_LIBRARIES(bug25714 mysqlclient)
diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am
index be91ef31c9d..f0ffc7a6720 100644
--- a/unittest/mysys/Makefile.am
+++ b/unittest/mysys/Makefile.am
@@ -1,4 +1,4 @@
-# Copyright (C) 2006 MySQL AB
+# 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
@@ -21,7 +21,14 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a
-noinst_PROGRAMS = bitmap-t base64-t my_atomic-t
+noinst_PROGRAMS = bitmap-t base64-t
+
+if NEED_THREAD
+# my_atomic-t is used to check thread functions, so it is safe to
+# ignore the file in non-threaded builds.
+# In fact, it will not compile without thread support.
+noinst_PROGRAMS += my_atomic-t
+endif
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt
index 164bcde7c4b..e1bd57d150f 100755
--- a/vio/CMakeLists.txt
+++ b/vio/CMakeLists.txt
@@ -13,8 +13,6 @@
# 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} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
-SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DSAFEMALLOC -DSAFE_MUTEX")
ADD_DEFINITIONS(-DUSE_SYMDIR)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/extra/yassl/include)
diff --git a/vio/viosocket.c b/vio/viosocket.c
index 2d7fd0e08cd..2a22f8c7c15 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -264,7 +264,7 @@ int vio_close(Vio * vio)
#ifdef __WIN__
if (vio->type == VIO_TYPE_NAMEDPIPE)
{
-#if defined(__NT__) && defined(MYSQL_SERVER)
+#if defined(MYSQL_SERVER)
CancelIo(vio->hPipe);
DisconnectNamedPipe(vio->hPipe);
#endif
@@ -450,7 +450,7 @@ int vio_close_pipe(Vio * vio)
{
int r;
DBUG_ENTER("vio_close_pipe");
-#if defined(__NT__) && defined(MYSQL_SERVER)
+#if defined(MYSQL_SERVER)
CancelIo(vio->hPipe);
DisconnectNamedPipe(vio->hPipe);
#endif