summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore11
-rwxr-xr-xBUILD/SETUP.sh6
-rw-r--r--BitKeeper/etc/collapsed12
-rwxr-xr-xBitKeeper/triggers/post-commit14
-rwxr-xr-xCMakeLists.txt4
-rw-r--r--Docs/Makefile.am22
-rw-r--r--Docs/MySQLEULA.txt252
-rw-r--r--Makefile.am25
-rw-r--r--README14
-rw-r--r--client/Makefile.am4
-rw-r--r--client/client_priv.h3
-rw-r--r--client/mysql.cc25
-rw-r--r--client/mysql_upgrade.c696
-rw-r--r--client/mysqlbinlog.cc2
-rw-r--r--client/mysqldump.c293
-rw-r--r--client/mysqltest.c5793
-rw-r--r--cmd-line-utils/readline/bind.c44
-rw-r--r--cmd-line-utils/readline/chardefs.h4
-rw-r--r--cmd-line-utils/readline/complete.c22
-rw-r--r--cmd-line-utils/readline/display.c17
-rw-r--r--cmd-line-utils/readline/histexpand.c6
-rw-r--r--cmd-line-utils/readline/histfile.c3
-rw-r--r--cmd-line-utils/readline/input.c2
-rw-r--r--cmd-line-utils/readline/isearch.c10
-rw-r--r--cmd-line-utils/readline/kill.c31
-rw-r--r--cmd-line-utils/readline/macro.c10
-rw-r--r--cmd-line-utils/readline/misc.c31
-rw-r--r--cmd-line-utils/readline/nls.c2
-rw-r--r--cmd-line-utils/readline/readline.c4
-rw-r--r--cmd-line-utils/readline/rltty.c7
-rw-r--r--cmd-line-utils/readline/search.c14
-rw-r--r--cmd-line-utils/readline/terminal.c10
-rw-r--r--cmd-line-utils/readline/text.c61
-rw-r--r--cmd-line-utils/readline/tilde.c2
-rw-r--r--cmd-line-utils/readline/undo.c8
-rw-r--r--cmd-line-utils/readline/util.c9
-rw-r--r--cmd-line-utils/readline/vi_mode.c83
-rw-r--r--config/ac-macros/ha_berkeley.m412
-rw-r--r--config/ac-macros/ha_innodb.m42
-rw-r--r--config/ac-macros/ha_ndbcluster.m42
-rw-r--r--configure.in19
-rw-r--r--dbug/dbug_analyze.c14
-rw-r--r--extra/replace.c6
-rw-r--r--extra/yassl/include/yassl_int.hpp7
-rw-r--r--extra/yassl/src/Makefile.am2
-rw-r--r--extra/yassl/src/ssl.cpp2
-rw-r--r--extra/yassl/taocrypt/benchmark/Makefile.am2
-rw-r--r--extra/yassl/taocrypt/benchmark/benchmark.dsp4
-rw-r--r--extra/yassl/taocrypt/include/algebra.hpp2
-rw-r--r--extra/yassl/taocrypt/include/hmac.hpp10
-rw-r--r--extra/yassl/taocrypt/src/Makefile.am2
-rw-r--r--extra/yassl/taocrypt/taocrypt.dsp4
-rwxr-xr-xextra/yassl/taocrypt/taocrypt.vcproj4
-rw-r--r--extra/yassl/taocrypt/test.dsp4
-rw-r--r--extra/yassl/taocrypt/test/Makefile.am2
-rw-r--r--extra/yassl/testsuite/Makefile.am2
-rw-r--r--extra/yassl/testsuite/test.hpp5
-rw-r--r--extra/yassl/testsuite/testsuite.cpp4
-rw-r--r--extra/yassl/testsuite/testsuite.dsp4
-rw-r--r--extra/yassl/yassl.dsp4
-rwxr-xr-xextra/yassl/yassl.vcproj4
-rw-r--r--heap/_check.c27
-rw-r--r--heap/hp_clear.c3
-rw-r--r--heap/hp_delete.c4
-rw-r--r--heap/hp_hash.c2
-rw-r--r--heap/hp_open.c5
-rw-r--r--heap/hp_rkey.c2
-rw-r--r--heap/hp_rrnd.c4
-rw-r--r--heap/hp_write.c10
-rw-r--r--include/Makefile.am36
-rw-r--r--include/abi_check0
-rw-r--r--include/abi_check.ic914
-rw-r--r--include/errmsg.h3
-rw-r--r--include/hash.h2
-rw-r--r--include/heap.h8
-rw-r--r--include/m_ctype.h12
-rw-r--r--include/my_dbug.h3
-rw-r--r--include/my_global.h4
-rw-r--r--include/my_pthread.h3
-rw-r--r--include/my_sys.h5
-rw-r--r--include/my_time.h46
-rw-r--r--include/my_tree.h5
-rw-r--r--include/mysql.h11
-rw-r--r--include/mysql_h.ic966
-rwxr-xr-xinnobase/CMakeLists.txt42
-rw-r--r--innobase/buf/buf0buf.c181
-rw-r--r--innobase/buf/buf0flu.c92
-rw-r--r--innobase/buf/buf0lru.c25
-rw-r--r--innobase/dict/dict0crea.c13
-rw-r--r--innobase/fil/fil0fil.c44
-rw-r--r--innobase/include/buf0buf.h40
-rw-r--r--innobase/include/buf0buf.ic19
-rw-r--r--innobase/include/dict0crea.h6
-rw-r--r--innobase/include/sync0arr.h13
-rw-r--r--innobase/include/sync0rw.h1
-rw-r--r--innobase/include/sync0rw.ic6
-rw-r--r--innobase/include/sync0sync.h1
-rw-r--r--innobase/os/os0file.c2
-rw-r--r--innobase/os/os0sync.c55
-rw-r--r--innobase/row/row0mysql.c8
-rw-r--r--innobase/row/row0sel.c6
-rw-r--r--innobase/srv/srv0start.c5
-rw-r--r--innobase/sync/sync0arr.c119
-rw-r--r--innobase/sync/sync0rw.c2
-rw-r--r--innobase/sync/sync0sync.c8
-rw-r--r--libmysql/Makefile.shared4
-rw-r--r--libmysql/errmsg.c3
-rw-r--r--libmysql/libmysql.c40
-rw-r--r--libmysql_r/Makefile.am10
-rw-r--r--libmysqld/Makefile.am23
-rw-r--r--libmysqld/lib_sql.cc17
-rw-r--r--libmysqld/libmysqld.c2
-rw-r--r--myisam/mi_close.c5
-rw-r--r--myisam/mi_create.c4
-rw-r--r--myisam/mi_delete.c9
-rw-r--r--myisam/mi_dynrec.c4
-rw-r--r--myisam/mi_key.c15
-rw-r--r--myisam/mi_keycache.c4
-rw-r--r--myisam/mi_open.c2
-rw-r--r--myisam/mi_page.c4
-rw-r--r--myisam/mi_statrec.c4
-rw-r--r--myisam/mi_test2.c2
-rw-r--r--myisam/mi_write.c18
-rw-r--r--myisam/myisampack.c35
-rw-r--r--myisam/sort.c259
-rw-r--r--myisammrg/myrg_extra.c2
-rw-r--r--myisammrg/myrg_rkey.c2
-rw-r--r--mysql-test/Makefile.am2
-rw-r--r--mysql-test/include/analyze_failure_sync_with_master.test15
-rw-r--r--mysql-test/include/ctype_like_escape.inc4
-rw-r--r--mysql-test/include/federated.inc2
-rw-r--r--mysql-test/include/mysqltest_while.inc137
-rw-r--r--mysql-test/include/report-features.test11
-rw-r--r--mysql-test/include/sourced.inc1
-rw-r--r--mysql-test/include/sourced1.inc1
-rw-r--r--mysql-test/include/sp-vars.inc23
-rw-r--r--mysql-test/include/strict_autoinc.inc4
-rw-r--r--mysql-test/include/wait_for_query_to_suceed.inc25
-rw-r--r--mysql-test/install_test_db.sh17
-rw-r--r--mysql-test/lib/mtr_cases.pl449
-rw-r--r--mysql-test/lib/mtr_gcov.pl18
-rw-r--r--mysql-test/lib/mtr_im.pl12
-rw-r--r--mysql-test/lib/mtr_io.pl41
-rw-r--r--mysql-test/lib/mtr_misc.pl40
-rw-r--r--mysql-test/lib/mtr_process.pl676
-rw-r--r--mysql-test/lib/mtr_report.pl114
-rw-r--r--mysql-test/lib/mtr_stress.pl12
-rw-r--r--mysql-test/lib/mtr_timer.pl29
-rw-r--r--mysql-test/lib/mtr_unique.pl156
-rwxr-xr-xmysql-test/mysql-test-run.pl3599
-rw-r--r--mysql-test/mysql-test-run.sh47
-rw-r--r--mysql-test/r/check.result2
-rw-r--r--mysql-test/r/compare.result4
-rw-r--r--mysql-test/r/create.result6
-rw-r--r--mysql-test/r/csv.result3
-rw-r--r--mysql-test/r/ctype_cp1250_ch.result1
-rw-r--r--mysql-test/r/ctype_recoding.result4
-rw-r--r--mysql-test/r/ctype_ucs.result22
-rw-r--r--mysql-test/r/ctype_utf8.result32
-rw-r--r--mysql-test/r/drop.result4
-rw-r--r--mysql-test/r/flush.result8
-rw-r--r--mysql-test/r/flush_block_commit.result6
-rw-r--r--mysql-test/r/flush_read_lock_kill.result2
-rw-r--r--mysql-test/r/fulltext.result8
-rw-r--r--mysql-test/r/func_compress.result10
-rw-r--r--mysql-test/r/func_date_add.result14
-rw-r--r--mysql-test/r/func_gconcat.result70
-rw-r--r--mysql-test/r/func_in.result9
-rw-r--r--mysql-test/r/func_misc.result2
-rw-r--r--mysql-test/r/func_sapdb.result15
-rw-r--r--mysql-test/r/func_str.result768
-rw-r--r--mysql-test/r/func_test.result75
-rw-r--r--mysql-test/r/func_time.result135
-rw-r--r--mysql-test/r/gis.result26
-rw-r--r--mysql-test/r/grant2.result8
-rw-r--r--mysql-test/r/group_min_max.result124
-rw-r--r--mysql-test/r/handler.result4
-rw-r--r--mysql-test/r/im_daemon_life_cycle.result6
-rw-r--r--mysql-test/r/im_life_cycle.result4
-rw-r--r--mysql-test/r/im_utils.result4
-rw-r--r--mysql-test/r/information_schema.result29
-rw-r--r--mysql-test/r/innodb_mysql.result31
-rw-r--r--mysql-test/r/innodb_notembedded.result2
-rw-r--r--mysql-test/r/kill.result4
-rw-r--r--mysql-test/r/lock_multi.result24
-rw-r--r--mysql-test/r/lowercase_table.result24
-rw-r--r--mysql-test/r/metadata.result34
-rw-r--r--mysql-test/r/mix_innodb_myisam_binlog.result2
-rw-r--r--mysql-test/r/multi_update.result4
-rw-r--r--mysql-test/r/mysql.result29
-rw-r--r--mysql-test/r/mysqldump-max.result19
-rw-r--r--mysql-test/r/mysqldump.result22
-rw-r--r--mysql-test/r/mysqltest.result107
-rw-r--r--mysql-test/r/ndb_charset.result8
-rw-r--r--mysql-test/r/ndb_condition_pushdown.result22
-rw-r--r--mysql-test/r/ndb_config.result3
-rw-r--r--mysql-test/r/ndb_index_unique.result12
-rw-r--r--mysql-test/r/ndb_multi.result38
-rw-r--r--mysql-test/r/ndb_update.result2
-rw-r--r--mysql-test/r/openssl_1.result4
-rw-r--r--mysql-test/r/order_by.result14
-rw-r--r--mysql-test/r/ps.result235
-rw-r--r--mysql-test/r/ps_11bugs.result33
-rw-r--r--mysql-test/r/query_cache.result51
-rw-r--r--mysql-test/r/query_cache_notembedded.result2
-rw-r--r--mysql-test/r/range.result10
-rw-r--r--mysql-test/r/rename.result4
-rw-r--r--mysql-test/r/rpl000001.result2
-rw-r--r--mysql-test/r/rpl000018.result14
-rw-r--r--mysql-test/r/rpl_chain_temp_table.result30
-rw-r--r--mysql-test/r/rpl_deadlock.result38
-rw-r--r--mysql-test/r/rpl_error_ignored_table.result2
-rw-r--r--mysql-test/r/rpl_failsafe.result34
-rw-r--r--mysql-test/r/rpl_heap.result29
-rw-r--r--mysql-test/r/rpl_ignore_table.result16
-rw-r--r--mysql-test/r/rpl_master_pos_wait.result2
-rw-r--r--mysql-test/r/rpl_packet.result17
-rw-r--r--mysql-test/r/rpl_trigger.result29
-rw-r--r--mysql-test/r/rpl_view.result4
-rw-r--r--mysql-test/r/show_check.result19
-rw-r--r--mysql-test/r/sp-error.result24
-rw-r--r--mysql-test/r/sp-threads.result4
-rw-r--r--mysql-test/r/sp-vars.result23
-rw-r--r--mysql-test/r/sp.result156
-rw-r--r--mysql-test/r/sp_notembedded.result3
-rw-r--r--mysql-test/r/ssl_des.result2159
-rw-r--r--mysql-test/r/strict_autoinc_1myisam.result1
-rw-r--r--mysql-test/r/strict_autoinc_2innodb.result1
-rw-r--r--mysql-test/r/strict_autoinc_3heap.result1
-rw-r--r--mysql-test/r/strict_autoinc_4bdb.result1
-rw-r--r--mysql-test/r/strict_autoinc_5ndb.result1
-rw-r--r--mysql-test/r/subselect.result3
-rw-r--r--mysql-test/r/synchronization.result40
-rw-r--r--mysql-test/r/timezone.result8
-rw-r--r--mysql-test/r/timezone2.result24
-rw-r--r--mysql-test/r/timezone4.result6
-rw-r--r--mysql-test/r/trigger.result101
-rw-r--r--mysql-test/r/type_bit.result8
-rw-r--r--mysql-test/r/type_newdecimal.result7
-rw-r--r--mysql-test/r/type_varchar.result36
-rw-r--r--mysql-test/r/union.result8
-rw-r--r--mysql-test/r/user_var.result9
-rw-r--r--mysql-test/r/view.result62
-rw-r--r--mysql-test/r/view_grant.result19
-rw-r--r--mysql-test/std_data/bad_gis_data.dat1
-rw-r--r--mysql-test/std_data/server-cert-des.pem16
-rw-r--r--mysql-test/std_data/server-key-des.pem18
-rw-r--r--mysql-test/t/bdb-alter-table-2-master.opt2
-rw-r--r--mysql-test/t/connect.test1
-rw-r--r--mysql-test/t/create.test28
-rw-r--r--mysql-test/t/csv.test14
-rw-r--r--mysql-test/t/ctype_collate.test39
-rw-r--r--mysql-test/t/ctype_cp1250_ch.test4
-rw-r--r--mysql-test/t/ctype_ucs.test19
-rw-r--r--mysql-test/t/ctype_utf8.test28
-rw-r--r--mysql-test/t/disabled.def1
-rw-r--r--mysql-test/t/func_compress.test14
-rw-r--r--mysql-test/t/func_date_add.test15
-rw-r--r--mysql-test/t/func_gconcat.test39
-rw-r--r--mysql-test/t/func_group.test2
-rw-r--r--mysql-test/t/func_in.test26
-rw-r--r--mysql-test/t/func_sapdb.test2
-rw-r--r--mysql-test/t/func_str.test224
-rw-r--r--mysql-test/t/func_test.test34
-rw-r--r--mysql-test/t/func_time.test93
-rw-r--r--mysql-test/t/gis.test22
-rw-r--r--mysql-test/t/grant.test2
-rw-r--r--mysql-test/t/greedy_optimizer.test62
-rw-r--r--mysql-test/t/group_min_max.test216
-rw-r--r--mysql-test/t/im_daemon_life_cycle.imtest69
-rw-r--r--mysql-test/t/im_life_cycle.imtest10
-rw-r--r--mysql-test/t/im_utils.imtest4
-rw-r--r--mysql-test/t/information_schema.test57
-rw-r--r--mysql-test/t/init_file.test2
-rw-r--r--mysql-test/t/innodb.test2
-rw-r--r--mysql-test/t/innodb_mysql.test65
-rw-r--r--mysql-test/t/join.test58
-rwxr-xr-xmysql-test/t/kill_n_check.sh82
-rw-r--r--mysql-test/t/limit.test2
-rw-r--r--mysql-test/t/lock_multi.test3
-rwxr-xr-xmysql-test/t/log.sh24
-rw-r--r--mysql-test/t/lowercase_table.test20
-rw-r--r--mysql-test/t/metadata.test19
-rw-r--r--mysql-test/t/mysql.test88
-rw-r--r--mysql-test/t/mysqldump-max.test11
-rw-r--r--mysql-test/t/mysqldump.test15
-rw-r--r--mysql-test/t/mysqltest.test476
-rw-r--r--mysql-test/t/ndb_condition_pushdown.test10
-rw-r--r--mysql-test/t/ndb_config.test5
-rw-r--r--mysql-test/t/ndb_multi.test25
-rw-r--r--mysql-test/t/not_embedded_server-master.opt2
-rw-r--r--mysql-test/t/null.test2
-rw-r--r--mysql-test/t/order_by.test9
-rw-r--r--mysql-test/t/ps-master.opt1
-rw-r--r--mysql-test/t/ps.test202
-rw-r--r--mysql-test/t/ps_11bugs.test34
-rw-r--r--mysql-test/t/ps_1general.test2
-rw-r--r--mysql-test/t/ps_grant.test2
-rw-r--r--mysql-test/t/query_cache.test31
-rw-r--r--mysql-test/t/range.test12
-rw-r--r--mysql-test/t/rename.test19
-rw-r--r--mysql-test/t/rpl000018.test29
-rw-r--r--mysql-test/t/rpl_chain_temp_table.test101
-rw-r--r--mysql-test/t/rpl_deadlock.test16
-rw-r--r--mysql-test/t/rpl_dual_pos_advance-master.opt2
-rw-r--r--mysql-test/t/rpl_empty_master_crash-master.opt1
-rw-r--r--mysql-test/t/rpl_failsafe.test24
-rw-r--r--mysql-test/t/rpl_flush_tables.test2
-rw-r--r--mysql-test/t/rpl_heap.test51
-rw-r--r--mysql-test/t/rpl_ignore_table-slave.opt2
-rw-r--r--mysql-test/t/rpl_ignore_table.test23
-rw-r--r--mysql-test/t/rpl_log-master.opt2
-rw-r--r--mysql-test/t/rpl_packet-master.opt1
-rw-r--r--mysql-test/t/rpl_packet-slave.opt1
-rw-r--r--mysql-test/t/rpl_packet.test39
-rw-r--r--mysql-test/t/rpl_slave_status.test2
-rw-r--r--mysql-test/t/rpl_trigger.test39
-rw-r--r--mysql-test/t/select.test4
-rw-r--r--mysql-test/t/show_check-master.opt1
-rw-r--r--mysql-test/t/show_check.test17
-rw-r--r--mysql-test/t/sp-error.test43
-rw-r--r--mysql-test/t/sp-prelocking.test2
-rw-r--r--mysql-test/t/sp-vars.test10
-rw-r--r--mysql-test/t/sp.test177
-rw-r--r--mysql-test/t/sp_notembedded.test12
-rw-r--r--mysql-test/t/ssl_des-master.opt1
-rw-r--r--mysql-test/t/ssl_des.test19
-rw-r--r--mysql-test/t/strict.test20
-rw-r--r--mysql-test/t/subselect.test8
-rw-r--r--mysql-test/t/system_mysql_db_fix.test6
-rw-r--r--mysql-test/t/timezone.test7
-rw-r--r--mysql-test/t/timezone2.test10
-rw-r--r--mysql-test/t/timezone4-master.opt1
-rw-r--r--mysql-test/t/timezone4.test13
-rw-r--r--mysql-test/t/trigger.test111
-rw-r--r--mysql-test/t/type_bit.test11
-rw-r--r--mysql-test/t/type_newdecimal.test14
-rw-r--r--mysql-test/t/type_varchar.test10
-rw-r--r--mysql-test/t/user_var.test10
-rw-r--r--mysql-test/t/utils.sh55
-rw-r--r--mysql-test/t/view.test98
-rw-r--r--mysql-test/t/view_grant.test41
-rwxr-xr-xmysql-test/t/wait_for_process.sh92
-rwxr-xr-xmysql-test/t/wait_for_socket.sh94
-rw-r--r--mysql-test/t/wait_timeout.test2
-rw-r--r--mysys/base64.c2
-rw-r--r--mysys/charset.c15
-rw-r--r--mysys/default.c6
-rw-r--r--mysys/hash.c13
-rw-r--r--mysys/list.c2
-rw-r--r--mysys/mf_iocache.c117
-rw-r--r--mysys/mf_keycache.c32
-rw-r--r--mysys/mf_keycaches.c4
-rw-r--r--mysys/my_alloc.c13
-rw-r--r--mysys/my_chsize.c6
-rw-r--r--mysys/my_dup.c2
-rw-r--r--mysys/my_fopen.c6
-rw-r--r--mysys/my_fstream.c8
-rw-r--r--mysys/my_getwd.c2
-rw-r--r--mysys/my_handler.c7
-rw-r--r--mysys/my_lib.c2
-rw-r--r--mysys/my_lock.c39
-rw-r--r--mysys/my_lread.c6
-rw-r--r--mysys/my_lwrite.c6
-rw-r--r--mysys/my_malloc.c4
-rw-r--r--mysys/my_pread.c20
-rw-r--r--mysys/my_quick.c26
-rw-r--r--mysys/my_read.c15
-rw-r--r--mysys/my_realloc.c4
-rw-r--r--mysys/my_seek.c37
-rw-r--r--mysys/my_thr_init.c97
-rw-r--r--mysys/my_write.c22
-rw-r--r--mysys/safemalloc.c10
-rw-r--r--mysys/thr_lock.c15
-rw-r--r--mysys/tree.c8
-rw-r--r--mysys/typelib.c2
-rw-r--r--ndb/config/type_kernel.mk.am5
-rw-r--r--ndb/config/type_ndbapi.mk.am5
-rw-r--r--ndb/config/type_ndbapitest.mk.am5
-rw-r--r--ndb/config/type_ndbapitools.mk.am5
-rw-r--r--ndb/config/type_util.mk.am2
-rw-r--r--ndb/include/kernel/GlobalSignalNumbers.h1
-rw-r--r--ndb/include/kernel/ndb_limits.h2
-rw-r--r--ndb/include/kernel/signaldata/CmRegSignalData.hpp6
-rw-r--r--ndb/include/kernel/signaldata/CopyFrag.hpp14
-rw-r--r--ndb/include/logger/LogHandler.hpp2
-rw-r--r--ndb/include/mgmapi/mgmapi.h40
-rw-r--r--ndb/include/mgmapi/ndbd_exit_codes.h2
-rw-r--r--ndb/include/mgmcommon/ConfigRetriever.hpp3
-rw-r--r--ndb/include/ndb_global.h.in6
-rw-r--r--ndb/include/ndb_version.h.in5
-rw-r--r--ndb/include/ndbapi/NdbTransaction.hpp5
-rw-r--r--ndb/include/util/File.hpp8
-rw-r--r--ndb/include/util/InputStream.hpp2
-rw-r--r--ndb/include/util/OutputStream.hpp1
-rw-r--r--ndb/include/util/SimpleProperties.hpp7
-rw-r--r--ndb/include/util/SocketClient.hpp3
-rw-r--r--ndb/include/util/UtilBuffer.hpp8
-rw-r--r--ndb/include/util/ndb_opts.h2
-rw-r--r--ndb/src/common/debugger/EventLogger.cpp7
-rw-r--r--ndb/src/common/debugger/signaldata/BackupSignalData.cpp3
-rw-r--r--ndb/src/common/debugger/signaldata/SignalNames.cpp3
-rw-r--r--ndb/src/common/logger/FileLogHandler.cpp11
-rw-r--r--ndb/src/common/logger/LogHandler.cpp4
-rw-r--r--ndb/src/common/mgmcommon/ConfigRetriever.cpp12
-rw-r--r--ndb/src/common/portlib/NdbMutex.c4
-rw-r--r--ndb/src/common/portlib/NdbThread.c4
-rw-r--r--ndb/src/common/transporter/Transporter.cpp22
-rw-r--r--ndb/src/common/util/File.cpp12
-rw-r--r--ndb/src/common/util/InputStream.cpp39
-rw-r--r--ndb/src/common/util/Parser.cpp35
-rw-r--r--ndb/src/common/util/SimpleProperties.cpp4
-rw-r--r--ndb/src/common/util/SocketClient.cpp73
-rw-r--r--ndb/src/common/util/socket_io.cpp28
-rw-r--r--ndb/src/cw/cpcd/CPCD.hpp1
-rw-r--r--ndb/src/cw/cpcd/main.cpp2
-rw-r--r--ndb/src/kernel/Makefile.am30
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt4
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp132
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.hpp6
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp8
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccInit.cpp1
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccMain.cpp2
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp9
-rw-r--r--ndb/src/kernel/blocks/dbdih/Dbdih.hpp2
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp384
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp1
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhInit.cpp4
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp62
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp30
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupGen.cpp3
-rw-r--r--ndb/src/kernel/blocks/dbtux/Dbtux.hpp241
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp38
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp17
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp25
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp13
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp335
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp59
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp31
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrMain.cpp58
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp1
-rw-r--r--ndb/src/kernel/error/ErrorReporter.hpp2
-rw-r--r--ndb/src/kernel/error/ndbd_exit_codes.c4
-rw-r--r--ndb/src/kernel/vm/Configuration.cpp16
-rw-r--r--ndb/src/kernel/vm/DLFifoList.hpp2
-rw-r--r--ndb/src/kernel/vm/TransporterCallback.cpp2
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp149
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.cpp880
-rw-r--r--ndb/src/mgmclient/main.cpp8
-rw-r--r--ndb/src/mgmclient/ndb_mgmclient.hpp4
-rw-r--r--ndb/src/mgmsrv/ConfigInfo.cpp11
-rw-r--r--ndb/src/mgmsrv/Makefile.am2
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp18
-rw-r--r--ndb/src/mgmsrv/Services.cpp30
-rw-r--r--ndb/src/mgmsrv/Services.hpp2
-rw-r--r--ndb/src/mgmsrv/main.cpp4
-rw-r--r--ndb/src/ndbapi/ClusterMgr.cpp2
-rw-r--r--ndb/src/ndbapi/DictCache.cpp3
-rw-r--r--ndb/src/ndbapi/Ndb.cpp40
-rw-r--r--ndb/src/ndbapi/NdbOperation.cpp22
-rw-r--r--ndb/src/ndbapi/NdbOperationDefine.cpp4
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp2
-rw-r--r--ndb/src/ndbapi/NdbOperationInt.cpp4
-rw-r--r--ndb/src/ndbapi/NdbOperationSearch.cpp4
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp36
-rw-r--r--ndb/src/ndbapi/NdbTransaction.cpp105
-rw-r--r--ndb/src/ndbapi/Ndbif.cpp4
-rw-r--r--ndb/src/ndbapi/Ndbinit.cpp4
-rw-r--r--ndb/src/ndbapi/Ndblist.cpp2
-rw-r--r--ndb/src/ndbapi/ndb_cluster_connection.cpp2
-rw-r--r--ndb/src/ndbapi/ndberror.c4
-rw-r--r--ndb/test/ndbapi/flexScan.cpp4
-rw-r--r--ndb/test/ndbapi/testMgm.cpp27
-rw-r--r--ndb/test/ndbapi/testOIBasic.cpp336
-rw-r--r--ndb/test/ndbapi/testTimeout.cpp50
-rw-r--r--ndb/test/run-test/daily-basic-tests.txt10
-rw-r--r--ndb/tools/delete_all.cpp5
-rw-r--r--ndb/tools/desc.cpp6
-rw-r--r--ndb/tools/drop_index.cpp9
-rw-r--r--ndb/tools/drop_tab.cpp11
-rw-r--r--ndb/tools/listTables.cpp5
-rw-r--r--ndb/tools/ndb_config.cpp68
-rw-r--r--ndb/tools/ndb_size.pl171
-rw-r--r--ndb/tools/ndb_size.tmpl20
-rw-r--r--ndb/tools/restore/consumer.hpp1
-rw-r--r--ndb/tools/restore/consumer_restore.cpp6
-rw-r--r--ndb/tools/restore/consumer_restore.hpp3
-rw-r--r--ndb/tools/restore/restore_main.cpp16
-rw-r--r--ndb/tools/select_all.cpp5
-rw-r--r--ndb/tools/select_count.cpp6
-rw-r--r--ndb/tools/waiter.cpp6
-rwxr-xr-xnetware/BUILD/compile-netware-END11
-rwxr-xr-x[-rw-r--r--]netware/BUILD/compile-netware-max2
-rwxr-xr-x[-rw-r--r--]netware/BUILD/compile-netware-max-debug2
-rwxr-xr-x[-rw-r--r--]netware/BUILD/compile-netware-src0
-rwxr-xr-xnetware/BUILD/mwenv31
-rwxr-xr-xnetware/BUILD/mwldnlm7
-rwxr-xr-xnetware/BUILD/nwbootstrap18
-rw-r--r--netware/Makefile.am5
-rw-r--r--netware/comp_err.def1
-rw-r--r--netware/isamchk.def2
-rw-r--r--netware/isamlog.def1
-rw-r--r--netware/libmysql.def2
-rw-r--r--netware/my_print_defaults.def2
-rw-r--r--netware/myisam_ftdump.def2
-rw-r--r--netware/myisamchk.def2
-rw-r--r--netware/myisamlog.def2
-rw-r--r--netware/myisampack.def2
-rw-r--r--netware/mysql.def2
-rw-r--r--netware/mysql_client_test.def10
-rw-r--r--netware/mysql_install_db.def2
-rw-r--r--netware/mysql_test_run.def2
-rw-r--r--netware/mysql_upgrade.def11
-rw-r--r--netware/mysql_waitpid.def2
-rw-r--r--netware/mysqladmin.def2
-rw-r--r--netware/mysqlbinlog.def2
-rw-r--r--netware/mysqlcheck.def2
-rw-r--r--netware/mysqld.def2
-rw-r--r--netware/mysqld_safe.def2
-rw-r--r--netware/mysqldump.def2
-rw-r--r--netware/mysqlimport.def2
-rw-r--r--netware/mysqlshow.def1
-rw-r--r--netware/mysqltest.def1
-rw-r--r--netware/pack_isam.def1
-rw-r--r--netware/perror.def2
-rw-r--r--netware/replace.def1
-rw-r--r--netware/resolve_stack_dump.def2
-rw-r--r--netware/resolveip.def1
-rw-r--r--regex/regexec.c3
-rw-r--r--scripts/make_binary_distribution.sh8
-rwxr-xr-xscripts/make_win_bin_dist15
-rw-r--r--scripts/mysql_install_db.sh36
-rw-r--r--server-tools/instance-manager/guardian.cc74
-rw-r--r--server-tools/instance-manager/guardian.h4
-rw-r--r--server-tools/instance-manager/instance.cc23
-rw-r--r--server-tools/instance-manager/instance_map.cc4
-rw-r--r--server-tools/instance-manager/listener.cc4
-rw-r--r--server-tools/instance-manager/manager.cc21
-rw-r--r--server-tools/instance-manager/mysql_connection.cc20
-rw-r--r--server-tools/instance-manager/options.cc4
-rw-r--r--server-tools/instance-manager/options.h2
-rw-r--r--server-tools/instance-manager/portability.h1
-rw-r--r--sql-common/client.c90
-rw-r--r--sql-common/my_time.c231
-rw-r--r--sql/Makefile.am7
-rw-r--r--sql/examples/ha_example.cc4
-rw-r--r--sql/examples/ha_example.h2
-rw-r--r--sql/examples/ha_tina.cc4
-rw-r--r--sql/examples/ha_tina.h2
-rw-r--r--sql/field.cc481
-rw-r--r--sql/field.h124
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/gen_lex_hash.cc5
-rw-r--r--sql/ha_archive.cc29
-rw-r--r--sql/ha_archive.h2
-rw-r--r--sql/ha_berkeley.cc4
-rw-r--r--sql/ha_berkeley.h2
-rw-r--r--sql/ha_blackhole.cc4
-rw-r--r--sql/ha_blackhole.h2
-rw-r--r--sql/ha_federated.cc24
-rw-r--r--sql/ha_federated.h5
-rw-r--r--sql/ha_heap.cc5
-rw-r--r--sql/ha_heap.h2
-rw-r--r--sql/ha_innodb.cc20
-rw-r--r--sql/ha_innodb.h2
-rw-r--r--sql/ha_myisam.cc6
-rw-r--r--sql/ha_myisam.h2
-rw-r--r--sql/ha_myisammrg.cc5
-rw-r--r--sql/ha_myisammrg.h2
-rw-r--r--sql/ha_ndbcluster.cc186
-rw-r--r--sql/ha_ndbcluster.h83
-rw-r--r--sql/handler.cc27
-rw-r--r--sql/handler.h2
-rw-r--r--sql/item.cc34
-rw-r--r--sql/item.h18
-rw-r--r--sql/item_cmpfunc.cc5
-rw-r--r--sql/item_func.cc63
-rw-r--r--sql/item_func.h5
-rw-r--r--sql/item_strfunc.cc226
-rw-r--r--sql/item_strfunc.h6
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_subselect.h2
-rw-r--r--sql/item_sum.cc56
-rw-r--r--sql/item_sum.h53
-rw-r--r--sql/item_timefunc.cc249
-rw-r--r--sql/item_timefunc.h19
-rw-r--r--sql/log.cc8
-rw-r--r--sql/log_event.cc16
-rw-r--r--sql/log_event.h22
-rw-r--r--sql/mysql_priv.h21
-rw-r--r--sql/mysqld.cc81
-rw-r--r--sql/net_serv.cc2
-rw-r--r--sql/opt_range.cc32
-rw-r--r--sql/opt_range.h2
-rw-r--r--sql/opt_sum.cc7
-rw-r--r--sql/parse_file.h16
-rw-r--r--sql/password.c4
-rw-r--r--sql/protocol.cc16
-rw-r--r--sql/protocol.h1
-rw-r--r--sql/set_var.cc24
-rw-r--r--sql/slave.cc89
-rw-r--r--sql/sp.cc42
-rw-r--r--sql/sp_cache.cc1
-rw-r--r--sql/sp_head.cc12
-rw-r--r--sql/sql_acl.cc71
-rw-r--r--sql/sql_base.cc19
-rw-r--r--sql/sql_cache.cc118
-rw-r--r--sql/sql_class.cc12
-rw-r--r--sql/sql_class.h28
-rw-r--r--sql/sql_db.cc7
-rw-r--r--sql/sql_delete.cc13
-rw-r--r--sql/sql_handler.cc1
-rw-r--r--sql/sql_lex.cc12
-rw-r--r--sql/sql_lex.h29
-rw-r--r--sql/sql_load.cc14
-rw-r--r--sql/sql_parse.cc212
-rw-r--r--sql/sql_prepare.cc63
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_repl.cc10
-rw-r--r--sql/sql_select.cc61
-rw-r--r--sql/sql_show.cc12
-rw-r--r--sql/sql_string.cc156
-rw-r--r--sql/sql_string.h14
-rw-r--r--sql/sql_table.cc217
-rw-r--r--sql/sql_trigger.cc129
-rw-r--r--sql/sql_union.cc22
-rw-r--r--sql/sql_update.cc6
-rw-r--r--sql/sql_view.cc110
-rw-r--r--sql/sql_view.h2
-rw-r--r--sql/sql_yacc.yy164
-rw-r--r--sql/stacktrace.c2
-rw-r--r--sql/strfunc.cc2
-rw-r--r--sql/table.cc18
-rw-r--r--sql/time.cc15
-rw-r--r--sql/tztime.cc86
-rw-r--r--sql/uniques.cc46
-rw-r--r--sql/unireg.cc8
-rw-r--r--strings/ctype-bin.c3
-rw-r--r--strings/ctype-mb.c24
-rw-r--r--strings/ctype-simple.c22
-rw-r--r--strings/ctype-ucs2.c8
-rw-r--r--strings/ctype-utf8.c135
-rw-r--r--strings/decimal.c4
-rw-r--r--support-files/mysql.spec.sh23
-rw-r--r--tests/mysql_client_test.c199
-rw-r--r--vio/viosocket.c16
-rw-r--r--vio/viossl.c35
-rw-r--r--vio/viosslfactories.c21
648 files changed, 25172 insertions, 9388 deletions
diff --git a/.bzrignore b/.bzrignore
index ecaa4b60c51..8455c05b220 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -403,8 +403,10 @@ heap/hp_test2
help
help.c
help.h
+include/check_abi
include/my_config.h
include/my_global.h
+include/mysql_h.ic
include/mysql_version.h
include/mysqld_ername.h
include/mysqld_error.h
@@ -704,6 +706,7 @@ mysql-test/r/bdb-deadlock.err
mysql-test/r/bdb.err
mysql-test/r/bdb.log
mysql-test/r/bdb_cache.err
+mysql-test/r/blackhole.log
mysql-test/r/client_test.err
mysql-test/r/csv.err
mysql-test/r/ctype_ucs.err
@@ -1319,3 +1322,11 @@ win/vs71cache.txt
win/vs8cache.txt
zlib/*.ds?
zlib/*.vcproj
+mysql-test/r/*.warnings
+bdb/dist/db.h
+bdb/dist/db_config.h
+bdb/dist/db_cxx.h
+bdb/dist/db_int.h
+bdb/dist/include.tcl
+*.gcda
+*.gcno
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index 8055f337821..6f3c4222ed2 100755
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -56,9 +56,9 @@ global_warnings="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wch
#debug_extra_warnings="-Wuninitialized"
c_warnings="$global_warnings -Wunused"
cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor"
-base_max_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine $SSL_LIBRARY"
-base_max_no_ndb_configs="--with-innodb --with-berkeley-db --without-ndbcluster --with-archive-storage-engine --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine $SSL_LIBRARY"
-max_leave_isam_configs="--with-innodb --with-berkeley-db --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-blackhole-storage-engine --with-csv-storage-engine $SSL_LIBRARY --with-embedded-server --with-big-tables"
+base_max_configs="--with-innodb --with-ndbcluster --with-archive-storage-engine --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine $SSL_LIBRARY"
+base_max_no_ndb_configs="--with-innodb --without-ndbcluster --with-archive-storage-engine --with-big-tables --with-blackhole-storage-engine --with-federated-storage-engine --with-csv-storage-engine $SSL_LIBRARY"
+max_leave_isam_configs="--with-innodb --with-ndbcluster --with-archive-storage-engine --with-federated-storage-engine --with-blackhole-storage-engine --with-csv-storage-engine $SSL_LIBRARY --with-embedded-server --with-big-tables"
max_configs="$base_max_configs --with-embedded-server"
max_no_ndb_configs="$base_max_no_ndb_configs --with-embedded-server"
diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed
index 79836bb030e..10bc7a2182a 100644
--- a/BitKeeper/etc/collapsed
+++ b/BitKeeper/etc/collapsed
@@ -5,5 +5,17 @@
45001f7c3b2hhCXDKfUvzkX9TNe6VA
45002051rHJfMEXAIMiAZV0clxvKSA
4513d8e4Af4dQWuk13sArwofRgFDQw
+45143312u0Tz4r0wPXCbUKwdHa2jWA
+45143b90ewOQuTW8-jrB3ZSAQvMRJw
+45184588w9U72A6KX1hUFeAC4shSHA
+45185df8mZbxfp85FbA0VxUXkmDewA
4519a6c5BVUxEHTf5iJnjZkixMBs8g
451ab499rgdjXyOnUDqHu-wBDoS-OQ
+451b110a3ZV6MITl93ehXk2wxrbW7g
+45214442pBGT9KuZEGixBH71jTzbOA
+45214a07hVsIGwvwa-WrO-jpeaSwVw
+452a92d0-31-8wSzSfZi165fcGcXPA
+452c6c6dAjuNghfc1ObZ_UQ5SCl85g
+4538a7b0EbDHHkWPbIwxO6ZIDdg6Dg
+454a7ef8gdvE_ddMlJyghvOAkKPNOQ
+454f8960jsVT_kMKJtZ9OCgXoba0xQ
diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit
index 981b55c66ec..8051cf98b7a 100755
--- a/BitKeeper/triggers/post-commit
+++ b/BitKeeper/triggers/post-commit
@@ -35,9 +35,17 @@ fi
CHANGESET=`bk -R prs -r+ -h -d':P:::I:' ChangeSet`
CSETKEY=`bk -R prs -r+ -h -d':KEY:' ChangeSet`
-BUG=`bk -R prs -r+ -h -d':C:' ChangeSet | sed -ne 's/^.*[Bb][Uu][Gg] *# *\([0-9][0-9]*\).*$/\1/p'`
-WL=`bk -R prs -r+ -h -d':C:' ChangeSet | sed -ne 's/^.*[Ww][Ll] *# *\([0-9][0-9]*\).*$/ WL#\1/p'`
-
+#
+# composing subject lines of commit mails.
+# if a fix targets to a WL and there is a bug referred
+# then X-Bug mail header will contain the first found bug's number
+#
+BUG=`bk -R prs -r+ -h -d':C:' ChangeSet | \
+ sed -ne 's/[Bb][Uu][Gg] *# *\([0-9][0-9]*\).*$/BUG#\1/
+ s/.*BUG#\([0-9][0-9]*\)/\1/p'`
+WL=`bk -R prs -r+ -h -d':C:' ChangeSet | \
+ sed -ne 's/[Ww][Ll] *# *\([0-9][0-9]*\).*$/WL#\1/
+ s/.*\(WL#[0-9][0-9]*\)/ \1/p'`
if [ "$BUG" = "" ]
then
TO=dev-public@mysql.com
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8058f615f7c..1c858eebb92 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -122,10 +122,10 @@ ADD_SUBDIRECTORY(myisam)
ADD_SUBDIRECTORY(myisammrg)
ADD_SUBDIRECTORY(client)
IF(WITH_BERKELEY_STORAGE_ENGINE)
-ADD_SUBDIRECTORY(bdb)
+ ADD_SUBDIRECTORY(bdb)
ENDIF(WITH_BERKELEY_STORAGE_ENGINE)
IF(WITH_INNOBASE_STORAGE_ENGINE)
-ADD_SUBDIRECTORY(innobase)
+ ADD_SUBDIRECTORY(innobase)
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
ADD_SUBDIRECTORY(sql)
ADD_SUBDIRECTORY(sql/examples)
diff --git a/Docs/Makefile.am b/Docs/Makefile.am
index 4722f61f5b9..ad78a30118e 100644
--- a/Docs/Makefile.am
+++ b/Docs/Makefile.am
@@ -26,7 +26,7 @@ all-local: $(TXT_FILES)
# make sure that "make install" installs the info page, too
# automake only seems to take care of this automatically,
# if we're building the info page from texi directly.
-install-data-hook: mysql.info
+install-data-hook: $(srcdir)/mysql.info
$(mkinstalldirs) $(DESTDIR)$(infodir)
$(INSTALL_DATA) $(srcdir)/mysql.info $(DESTDIR)$(infodir)
@@ -44,23 +44,23 @@ CLEAN_FILES: $(TXT_FILES)
GT = $(srcdir)/Support/generate-text-files.pl
-../INSTALL-SOURCE: mysql.info $(GT)
- perl -w $(GT) mysql.info "installing-source" "windows-source-build" > $@
+../INSTALL-SOURCE: $(srcdir)/mysql.info $(GT)
+ perl -w $(GT) $(srcdir)/mysql.info "installing-source" "windows-source-build" > $@
-../INSTALL-WIN-SOURCE: mysql.info $(GT)
- perl -w $(GT) mysql.info "windows-source-build" "post-installation" > $@
+../INSTALL-WIN-SOURCE: $(srcdir)/mysql.info $(GT)
+ perl -w $(GT) $(srcdir)/mysql.info "windows-source-build" "post-installation" > $@
# We put the description for the binary installation here so that
# people who download source wont have to see it. It is moved up to
# the toplevel by the script that makes the binary tar files.
-INSTALL-BINARY: mysql.info $(GT)
- perl -w $(GT) mysql.info "installing-binary" "installing-source" > $@
+INSTALL-BINARY: $(srcdir)/mysql.info $(GT)
+ perl -w $(GT) $(srcdir)/mysql.info "installing-binary" "installing-source" > $@
-../EXCEPTIONS-CLIENT: mysql.info $(GT)
- perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@
+../EXCEPTIONS-CLIENT: $(srcdir)/mysql.info $(GT)
+ perl -w $(GT) $(srcdir)/mysql.info "mysql-floss-license-exception" "function-index" > $@
-../support-files/MacOSX/ReadMe.txt: mysql.info $(GT)
- perl -w $(GT) mysql.info "mac-os-x-installation" "netware-installation" > $@
+../support-files/MacOSX/ReadMe.txt: $(srcdir)/mysql.info $(GT)
+ perl -w $(GT) $(srcdir)/mysql.info "mac-os-x-installation" "netware-installation" > $@
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/Docs/MySQLEULA.txt b/Docs/MySQLEULA.txt
deleted file mode 100644
index f50c50298b1..00000000000
--- a/Docs/MySQLEULA.txt
+++ /dev/null
@@ -1,252 +0,0 @@
- License Agreement for Commercial Use of MySQL[tm] Software
-
-This Agreement ("License") is between MySQL AB, a Swedish company
-("Licensor"), and the customer ("Licensee") identified on the electronic order
-form submitted on behalf of Licensee (the "Order Form"). In consideration of
-the mutual promises, covenants and conditions contained herein, the
-sufficiency of which is hereby acknowledged, the parties agree as follows.
-
-1. License Grant.
-"Licensed Software" means a complete and unchanged copy of the object code
-version of the MySQL relational database management software identified in the
-Order Form and posted on a special download page of the MySQL AB web site (the
-"Download Page") made available to Licensee immediately after payment as
-provided in Section 4. Subject to payment and the other terms and conditions
-hereof, Licensor grants to Licensee a limited, non-exclusive and
-non-transferable right to: (a) make one copy of the Licensed Software for each
-license purchased (each, a "Licensed Copy"); (b) compile and/or link each
-Licensed Copy to one copy of the Licensee software identified in the Order
-Form (the "Licensee Application") without modifying the Licensed Software
-(each, an "Integrated Product"); and (c) load and use the Licensed Copy
-portion of an Integrated Product on one machine or instrument in the operating
-system environment(s), and on the hardware platform(s) specified in the Order
-Form, and solely for running and extracting data from, the Licensee
-Application. "Use" means operation by one person for internal business
-purposes in accordance with the terms and conditions hereof. Licensed Copies
-shall be deemed accepted by Licensee immediately upon download. Licensee may
-make one additional copy of each Licensed Copy for backup and archival
-purposes only.
-
-2. Transfer.
-Only after Licensee has linked or compiled a Licensed Copy as permitted in
-Section 1, Licensee may transfer to a third party (the "Transferee") the right
-to use such copy as described in Section 1. As a condition to any such
-transfer: (a) Licensee must deliver the Licensed Copy and any backup copy to
-the Transferee along with a copy of this License (including the Sales Order);
-and (b) the Transferee must accept the terms and conditions of this License.
-Any and all of Licensee's rights to a Licensed Copy shall terminate upon
-transfer of the right to use such copy. A Transferee's rights are limited to
-the use rights described in Section 1(c), and do not include the linking,
-compilation or copying rights (except for backup and archival copies)
-described in Section 1. If you did not purchase this License directly from
-MySQL AB, then you are a Transferee. Licensee and any Transferee must comply
-with all applicable export laws and regulations.
-
-3. Restrictions.
-Licensee may use the Licensed Software only as expressly provided in Section
-1. Without limiting the foregoing, Licensee shall not: (a) lease, license,
-use, make available, distribute or modify all or any part of the Licensed
-Software to any third party, except as otherwise expressly permitted herein;
-(b) use the Licensed Software to operate in or as a time-sharing, outsourcing,
-service bureau, application service provider or managed service provider
-environment; (c) lease, license, use, make available or distribute the
-Licensed Software as a general SQL server, as a stand alone application or
-with applications other than the Licensee Application under this License; (d)
-copy the Licensed Software onto any public or distributed network; (e)
-distribute Integrated Products pursuant to a public or open source license;
-(f) port the Licensed Software to any operating system other than as described
-in the Order Form; or (g) change any proprietary rights notices which appear
-in the Licensed Software. Except as otherwise provided in Section 2, the
-rights granted to Licensee herein are rights that may be exercised solely by
-Licensee.
-
-4. Price and payment.
-No later than thirty (30) days after submission of the Order Form, Licensee
-shall remit one non-refundable license fee per Licensed Copy as posted on
-http://shop.mysql.com on the date Licensee submitted the Order Form (the
-"License Fee"). All payments shall be made in Euros or U.S. dollars. Licensee
-shall be responsible for paying all local, state, federal and international
-sales, value added, excise and other taxes and duties payable in connection
-with this License, other than taxes based upon Licensor's net income. Licensee
-shall not be permitted to access the Download Page until Licensor has received
-payment in full.
-
-5. Termination.
-Licensor may terminate this License immediately if the Licensee shall breach
-any of the provisions of this License and such breach remains uncured 30 days
-after receipt of notice. In the event that Licensee becomes liquidated,
-dissolved, bankrupt or insolvent, whether voluntarily or involuntarily, or
-shall take any action to be so declared, Licensor shall have the right to
-terminate this License immediately. Upon expiration, cancellation or other
-termination of this License, Licensee shall immediately: (a) discontinue
-distribution of Integrated Products that include Licensed Software; and (b)
-destroy all copies of the Licensed Software, including (without limitation) as
-linked or compiled in any Integrated Product. Sections 4 through 10 shall
-survive the termination of this License for any reason.
-
-6. Proprietary Rights.
-Licensee agrees that the copyright, patent, trade secrets and all other
-intellectual proprietary rights of whatever nature in the Licensed Software
-and related documentation, including derivative works, are and shall remain
-the exclusive property of Licensor and any third party suppliers. Nothing in
-this License should be construed as transferring any aspects of such rights to
-Licensee or any third party. Licensor reserves any and all rights not
-expressly granted herein. MySQL is a trademark of MySQL AB, and shall not be
-used by Licensee without Licensor's express written authorization. Licensee
-shall include in the Integrated Products a conspicuous notice that the
-Integrated Products include software whose copyright is owned by MySQL AB.
-
-7. Disclaimer of Warranties.
-THE LICENSED SOFTWARE IS LICENSED "AS IS," WITHOUT ANY WARRANTIES WHATSOEVER.
-LICENSOR EXPRESSLY DISCLAIMS, AND LICENSEE EXPRESSLY WAIVES, ALL WARRANTIES,
-WHETHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTIBILITY, FITNESS
-FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, SYSTEM INTEGRATION,
-NON-INTERFERENCE AND ACCURACY OF INFORMATIONAL CONTENT. LICENSOR DOES NOT
-WARRANT THAT THE LICENSED SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR THAT
-THE OPERATION OF THE LICENSED SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR
-THAT ERRORS WILL BE CORRECTED. THE ENTIRE RISK OF THE LICENSED SOFTWARE'S
-QUALITY AND PERFORMANCE IS WITH LICENSEE. Without limiting the generality of
-the foregoing disclaimer, Licensee acknowledges that the Licensed Software is
-not specifically designed, manufactured or intended for use in the planning,
-construction, maintenance, control or direct operation of nuclear facilities,
-aircraft navigation, control or communication systems, weapons systems or
-direct life support systems.
-
-8. Indemnification.
-Licensee hereby indemnifies and agrees to defend Licensor against any and all
-damages, judgments and costs (including reasonable attorneys' fees) related to
-any claim based upon: (a) an allegation that the Licensee Application
-infringes the intellectual property of a third party; (b) use of the Licensed
-Software in a manner prohibited under this License or in a manner for which
-the Licensed Software was not designed; (c) integration or use of the Licensed
-Software with the Licensee Application (where use of the Licensed Software
-alone would not infringe); (d) changes made by Licensee to the Licensed
-Software (where use of unmodified Licensed Software would not infringe); (e)
-changes made, or actions taken, by Licensor upon Licensee's direct
-instructions; or (f) bodily injury, property damage or any other damage or
-injury due to the use or inability to use an Integrated Product.
-
-9. Limitation of Liability.
-LICENSOR SHALL HAVE NO LIABILITY WITH RESPECT TO ITS OBLIGATIONS UNDER THIS
-AGREEMENT OR OTHERWISE FOR CONSEQUENTIAL, EXEMPLARY, SPECIAL, INDIRECT,
-INCIDENTAL OR PUNITIVE DAMAGES, INCLUDING (WITHOUT LIMITATION) ANY LOST
-PROFITS OR LOST SAVINGS (WHETHER RESULTING FROM IMPAIRED OR LOST DATA,
-SOFTWARE OR COMPUTER FAILURE OR ANY OTHER CAUSE), EVEN IF IT HAS BEEN ADVISED
-OF THE POSSIBILITY OF SUCH DAMAGES. NOTWITHSTANDING ANY OTHER PROVISION IN
-THIS AGREEMENT, THE LIABILITY OF LICENSOR FOR ANY REASON AND UPON ANY CAUSE OF
-ACTION SHALL BE LIMITED TO THE AMOUNT PAID TO LICENSOR BY LICENSEE UNDER THIS
-AGREEMENT. THIS LIMITATION APPLIES TO ALL CAUSES OF ACTION IN THE AGGREGATE,
-INCLUDING (WITHOUT LIMITATION) BREACH OF CONTRACT, BREACH OF WARRANTY,
-NEGLIGENCE, MISREPRESENTATIONS AND OTHER TORTS. THE PARTIES AGREE THAT THE
-REMEDIES AND LIMITATIONS HEREIN ALLOCATE THE RISKS BETWEEN THE PARTIES AS
-AUTHORIZED BY APPLICABLE LAWS. THE LICENSE FEES ARE SET IN RELIANCE UPON THIS
-ALLOCATION OF RISK AND THE EXCLUSION OF CERTAIN DAMAGES AS SET FORTH IN THIS
-AGREEMENT.
-
-10. Miscellaneous.
-
-10.1 Interpretation.
-Failure by Licensor to exercise any right or remedy does not signify
-acceptance of the event giving rise to such right or remedy. No action arising
-out of this License may be brought by Licensee more than one year after the
-cause of action has accrued. If any part of this License is held by a court of
-competent jurisdiction to be illegal or unenforceable, the validity or
-enforceability of the remainder of this License shall not be affected and such
-provision shall be deemed modified to the minimum extent necessary to make
-such provision consistent with applicable law and, in its modified form, such
-provision shall be enforceable and enforced. Licensor reserves the right not
-to accept any Order Form. Any invoice issued by Licensor in connection with
-this License shall be deemed a part of this Agreement. To the extent of any
-inconsistency between an Order Form and an invoice issued by Licensor, the
-terms and conditions of the invoice shall prevail; Licensee shall be deemed to
-have accepted an invoice upon payment of such invoice. In the event that
-Licensee placed an order by telephone or through an authorized sales
-representative, the invoice issued by Licensor shall constitute the Order
-Form. The terms and conditions of this Agreement shall replace and serve as a
-novation of the terms and conditions of any commercial (i.e., non-GPL) license
-purchased online by Licensee prior to August 2002.
-
-10.2 Binding.
-This Agreement will be binding upon and inure to the benefit of the parties,
-their respective successors and permitted assigns. Except as otherwise
-provided in Section 2, without the prior written consent of Licensor, Licensee
-may not assign this License or its rights or obligations under this License to
-any person or party, whether by operation of law or otherwise; any attempt by
-Licensee to assign this License without Licensor's prior written consent shall
-be null and void. There are no intended third party beneficiaries of this
-License. The parties are, and shall remain, independent contractors; nothing
-in this License is designed to create, nor shall create between them, a
-partnership, joint venture, agency, or employment relationship.
-
-10.3 Governing Law; Dispute Forum.
-If Licensee's residence, principal place of business or place of organization
-is in the United States of America ("USA"), then this License shall be deemed
-to have been executed in the USA and shall be governed by the laws of the
-State of Delaware, without regard to the conflict of laws provisions thereof.
-If Licensee's residence, principal place of business or place of organization
-is in any country other than the USA, then this License shall be deemed to
-have been executed in Sweden and shall be governed by the laws of Sweden,
-without regard to the conflict of laws provisions thereof. In no event shall
-the United Nations Convention on Contracts for the International Sale of Goods
-apply to, or govern, this License. The parties consent to the exclusive
-jurisdiction of the courts of Sweden and the USA, as provided in this Section.
-In the event that Licensor initiates an action in connection with this License
-or any other dispute between the parties, the exclusive jurisdiction of such
-action shall be in: (a) Newark, Delaware, if Licensee's residence, principal
-place of business or place of organization is in the USA; or (b) Uppsala,
-Sweden, if Licensee's residence, principal place of business or place of
-organization is in any country other than the USA. In the event that Licensee
-initiates an action in connection with this License or any other dispute
-between the parties, the exclusive jurisdiction of such action shall be in
-Stockholm, Sweden. Notwithstanding the foregoing, either party may bring a
-counterclaim in an action in the same jurisdiction in which the originating
-claim was filed, and either party may enforce any judgment rendered by such
-court in any court of competent jurisdiction. Licensee shall comply at its own
-expense with all relevant and applicable laws related to use and distribution
-of the Licensed Software as permitted in this License. Notwithstanding the
-foregoing, Licensor may seek injunctive or other equitable relief in any
-jurisdiction in order to protect its intellectual property rights. The parties
-have agreed to execute this License in the English language, and the English
-language version of the Agreement will control for all purposes. Any action
-brought under this License shall be conducted in the English language.
-Licensee shall be responsible for Licensor's attorneys fees and other expenses
-associated with the enforcement of this License or the collection of any
-amounts due under this License.
-
-10.4 Notice.
-Unless otherwise agreed, any notice under this License shall be delivered and
-addressed to Licensee at the address set forth on the Order Form, and to
-Licensor at Bangardsgatan 8, 753 20, Uppsala, Sweden. Notice shall be deemed
-received by any party: (a) on the day given, if personally delivered or if
-sent by confirmed facsimile transmission, receipt verified; (b) on the third
-day after deposit, if mailed by certified, first class, postage prepaid,
-return receipt requested mail, or by reputable, expedited overnight courier;
-or (c) on the fifth day after deposit, if sent by reputable, expedited
-international courier. Either party may change its address for notice
-purposes upon notice in accordance with this Section. Licensor may identify
-Licensee as a commercial licensee, including on the MySQL web site.
-
-10.5 GPL.
-The GPL License shall continue to apply to any and all uses and distributions
-of the Licensed Software undertaken by Licensee either prior to the Effective
-Date, after termination, or otherwise outside the scope of this License. This
-Agreement shall not be deemed to replace or otherwise amend any Licensee
-rights or obligations pursuant to the GPL License with respect to any uses of
-the Licensed Software described in the preceding sentence.
-
-10.6 Entire Agreement.
-This Agreement (including the Order Form and the invoice) comprises the entire
-agreement, and supercedes and merges all prior proposals, understandings and
-agreements, oral and written, between the parties relating to the subject
-matter of this License. This Agreement may be amended or modified only in a
-writing executed by both parties. To the extent of any conflict or
-inconsistency between this License and any invoice or other document submitted
-by Licensee to Licensor, this License will control. Licensor's acceptance of
-any document shall not be construed as an acceptance of provisions which are
-in any way in conflict or inconsistent with, or in addition to, this License,
-unless such terms are separately and specifically accepted in writing by an
-authorized officer of Licensor.
-
-10.7 Print this License.
-For record keeping purposes, we encourage Licensee to print this License and
-the Order Form on the date that the Order Form is submitted.
diff --git a/Makefile.am b/Makefile.am
index e27f8d098c5..6038825c928 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,6 +49,14 @@ BUILT_SOURCES = linked_client_sources linked_server_sources \
CLEANFILES = $(BUILT_SOURCES) bdb/build_unix/db.h
DISTCLEANFILES = ac_available_languages_fragment
+# Our current filtering of "sql_yacc.cc" in "sql/Makefile.am" creates
+# a problem, if a VPATH build and "sql_yacc.cc" was part of the source
+# distribution we end up with one "sql_yacc.cc" in the source tree,
+# and one in the build tree. This breaks "distcleancheck", until this
+# is sorted out we redefine the find that scans for files not removed
+
+distcleancheck_listfiles = find . -name sql_yacc.cc -o -type f -print
+
linked_include_sources:
cd include; $(MAKE) link_sources
echo timestamp > linked_include_sources
@@ -92,15 +100,12 @@ bin-dist: all
# Create initial database files for Windows installations.
dist-hook:
rm -rf `find $(distdir) -type d -name SCCS -print`
- if echo "$(distdir)" | grep -q '^/' ; then \
- scripts/mysql_install_db --no-defaults --windows \
- --basedir=$(top_srcdir) \
- --datadir="$(distdir)/win/data"; \
- else \
- scripts/mysql_install_db --no-defaults --windows \
- --basedir=$(top_srcdir) \
- --datadir="$$(pwd)/$(distdir)/win/data"; \
- fi
+ rm -f `find $(distdir) -type l -print`
+ mkdir -p $(distdir)/win
+ scripts/mysql_install_db --no-defaults --windows \
+ --basedir=$(top_builddir) \
+ --datadir=$(distdir)/win/data \
+ --srcdir=$(top_srcdir)
tags:
support-files/build-tags
@@ -136,7 +141,7 @@ test-force-pl:
./mysql-test-run.pl --ps-protocol --force
#used by autopush.pl to run memory based tests
-test-force-mem:
+test-force-pl-mem:
cd mysql-test; \
./mysql-test-run.pl --force --mem && \
./mysql-test-run.pl --ps-protocol --force --mem
diff --git a/README b/README
index d37b37cd918..56bd912d3d6 100644
--- a/README
+++ b/README
@@ -2,8 +2,9 @@ This is a release of MySQL, a dual-license SQL database server.
MySQL is brought to you by the MySQL team at MySQL AB.
License information can be found in these files:
-- For GPL (free) distributions, see the COPYING file.
-- For commercial distributions, see the MySQLEULA.txt file.
+- For GPL (free) distributions, see the COPYING file and
+ the EXCEPTIONS-CLIENT file.
+- For commercial distributions, see the LICENSE.mysql file.
For further information about MySQL or additional documentation, see:
@@ -15,11 +16,10 @@ Some manual sections of special interest:
- If you are migrating from an older version of MySQL, please read the
"Upgrading from..." section first!
- To see what MySQL can do, take a look at the features section.
-- For installation instructions, see the Installation chapter.
-- For future plans, see the TODO appendix.
-- For the new features/bugfix history, see the News appendix.
-- For the currently known bugs/misfeatures (known errors) see the problems
- appendix.
+- For installation instructions, see the Installing and Upgrading chapter.
+- For the new features/bugfix history, see the Change History appendix.
+- For the currently known bugs/misfeatures (known errors) see the Problems
+ and Common Errors appendix.
- For a list of developers and other contributors, see the Credits
appendix.
diff --git a/client/Makefile.am b/client/Makefile.am
index d3c320db56c..29624f2017f 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -38,7 +38,9 @@ noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
mysql_SOURCES = mysql.cc readline.cc sql_string.cc completion_hash.cc
mysqladmin_SOURCES = mysqladmin.cc
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
-mysqltest_SOURCES= mysqltest.c $(top_srcdir)/mysys/my_getsystime.c \
+mysqltest_SOURCES= mysqltest.c \
+ $(top_srcdir)/mysys/my_getsystime.c \
+ $(top_srcdir)/mysys/my_copy.c \
$(yassl_dummy_link_fix)
mysqltest_LDADD = $(top_builddir)/regex/libregex.a $(LDADD)
mysqlbinlog_SOURCES = mysqlbinlog.cc $(top_srcdir)/mysys/mf_tempdir.c $(top_srcdir)/mysys/my_new.cc
diff --git a/client/client_priv.h b/client/client_priv.h
index 9e011144836..7ebbade4ef6 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -51,5 +51,6 @@ enum options_client
#endif
OPT_TRIGGERS,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
- OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT
+ OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT,
+ OPT_DEBUG_INFO
};
diff --git a/client/mysql.cc b/client/mysql.cc
index 1d7abbbc38a..cd24e1d5ce2 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -388,6 +388,21 @@ int main(int argc,char *argv[])
else
status.add_to_history=1;
status.exit_status=1;
+
+ {
+ /*
+ The file descriptor-layer may be out-of-sync with the file-number layer,
+ so we make sure that "stdout" is really open. If its file is closed then
+ explicitly close the FD layer.
+ */
+ int stdout_fileno_copy;
+ stdout_fileno_copy= dup(fileno(stdout)); /* Okay if fileno fails. */
+ if (stdout_fileno_copy == -1)
+ fclose(stdout);
+ else
+ close(stdout_fileno_copy); /* Clean up dup(). */
+ }
+
load_defaults("my",load_default_groups,&argc,&argv);
defaults_argv=argv;
if (get_options(argc, (char **) argv))
@@ -2109,6 +2124,8 @@ com_go(String *buffer,char *line __attribute__((unused)))
(long) mysql_num_rows(result),
(long) mysql_num_rows(result) == 1 ? "row" : "rows");
end_pager();
+ if (mysql_errno(&mysql))
+ error= put_error(&mysql);
}
}
else if (mysql_affected_rows(&mysql) == ~(ulonglong) 0)
@@ -2380,7 +2397,6 @@ print_table_data(MYSQL_RES *result)
const char *buffer;
uint data_length;
uint field_max_length;
- bool right_justified;
uint visible_length;
uint extra_padding;
@@ -2919,7 +2935,11 @@ com_connect(String *buffer, char *line)
bzero(buff, sizeof(buff));
if (buffer)
{
- strmake(buff, line, sizeof(buff) - 1);
+ /*
+ Two null bytes are needed in the end of buff to allow
+ get_arg to find end of string the second time it's called.
+ */
+ strmake(buff, line, sizeof(buff)-2);
tmp= get_arg(buff, 0);
if (tmp && *tmp)
{
@@ -3425,7 +3445,6 @@ server_version_string(MYSQL *mysql)
{
char *bufp = buf;
MYSQL_RES *result;
- MYSQL_ROW cur;
bufp = strnmov(buf, mysql_get_server_info(mysql), sizeof buf);
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 6ec361392c8..520d87b5ed7 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -16,21 +16,42 @@
#include "client_priv.h"
#include <my_dir.h>
+#include <my_list.h>
+#include <sslopt-vars.h>
+
+#define UPGRADE_DEFAULTS_NAME "mysql_upgrade_defaults"
+#define MYSQL_UPGRADE_INFO_NAME "mysql_upgrade_info"
+#define MYSQL_FIX_PRIV_TABLES_NAME "mysql_fix_privilege_tables.sql"
+
+#define MY_PARENT (1 << 0)
+#define MY_ISDIR (1 << 1)
+#define MY_SEARCH_SELF (1 << 2)
#ifdef __WIN__
const char *mysqlcheck_name= "mysqlcheck.exe";
const char *mysql_name= "mysql.exe";
+const char *mysqld_name= "mysqld.exe";
#else
const char *mysqlcheck_name= "mysqlcheck";
const char *mysql_name= "mysql";
+const char *mysqld_name= "mysqld";
#endif /*__WIN__*/
-static my_bool opt_force= 0, opt_verbose= 0, tty_password= 0;
+extern TYPELIB sql_protocol_typelib;
+
+static my_bool opt_force= 0, opt_verbose= 0, opt_compress= 0;
static char *user= (char*) "root", *basedir= 0, *datadir= 0, *opt_password= 0;
-static my_bool upgrade_defaults_created= 0;
-static my_string opt_mysql_port, opt_mysql_unix_port= 0;
-static char *default_dbug_option= (char*) "d:t:O,/tmp/comp_err.trace";
-static my_bool info_flag= 0;
+static char *current_host= 0;
+static char *opt_default_charset= 0, *opt_charsets_dir= 0;
+#ifdef HAVE_SMEM
+static char *shared_memory_base_name= 0;
+#endif
+static char *opt_protocol= 0;
+static my_string opt_mysql_port= 0, opt_mysql_unix_port= 0;
+#ifndef DBUG_OFF
+static char *default_dbug_option= (char*) "d:t:O,/tmp/mysql_upgrade.trace";
+#endif
+static my_bool info_flag= 0, tty_password= 0;
static struct my_option my_long_options[]=
{
@@ -50,27 +71,51 @@ static struct my_option my_long_options[]=
#endif
{"debug-info", 'T', "Print some debug info at exit.", (gptr *) & info_flag,
(gptr *) & info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"force", 'f', "Continue even if we get an sql-error.",
+ {"default-character-set", OPT_DEFAULT_CHARSET,
+ "Set the default character set.", (gptr*) &opt_default_charset,
+ (gptr*) &opt_default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade "
+ "has already been executed for the current version of MySQL.",
(gptr*) &opt_force, (gptr*) &opt_force, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
+ {"character-sets-dir", OPT_CHARSETS_DIR,
+ "Directory where character sets are.", (gptr*) &opt_charsets_dir,
+ (gptr*) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"compress", OPT_COMPRESS, "Use compression in server/client protocol.",
+ (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ 0, 0, 0},
+ {"host",'h', "Connect to host.", (gptr*) &current_host,
+ (gptr*) &current_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p',
- "Password to use when connecting to server. If password is not given it's solicited on the tty.",
- 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ "Password to use when connecting to server. If password is not given"
+ " it's solicited on the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef __WIN__
+ {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
- (gptr*) &opt_mysql_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
- 0},
+ (gptr*) &opt_mysql_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"protocol", OPT_MYSQL_PROTOCOL,
"The protocol of connection (tcp,socket,pipe,memory).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef HAVE_SMEM
+ {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory.", (gptr*) &shared_memory_base_name,
+ (gptr*) &shared_memory_base_name, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"socket", 'S', "Socket file to use for connection.",
- (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"user", 'u', "User for login if not current user.", (gptr*) &user,
(gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"verbose", 'v', "Display more output about the process", (gptr*) &opt_verbose,
- (gptr *) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+#include <sslopt-longopts.h>
+ {"verbose", 'v', "Display more output about the process",
+ (gptr*) &opt_verbose, (gptr*) &opt_verbose, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
+
static const char *load_default_groups[]=
{
"mysql_upgrade", 0
@@ -78,6 +123,81 @@ static const char *load_default_groups[]=
#include <help_end.h>
+static LIST *extra_defaults= NULL;
+
+typedef struct _extra_default
+{
+ int id;
+ const char *name;
+ int n_len;
+ const char *value;
+ int v_len;
+} extra_default_t;
+
+static inline
+void set_extra_default(int id, const struct my_option *opt)
+{
+ switch (id) {
+ case 'b': case 'd': /* these are ours */
+ case 'f': /* --force is ours */
+ case 'u': /* --user passed on cmdline */
+ case 'T': /* --debug-info is not accepted by mysqlcheck */
+ /* so, do nothing */
+ break;
+ default:
+ {
+ LIST *l;
+ extra_default_t *d;
+
+ /*
+ Remove any earlier duplicates: they can
+ refer to invalid memory addresses (stale pointers)
+ */
+ l= extra_defaults;
+ while (l)
+ {
+ LIST *n= l->next;
+
+ d= l->data;
+ if (d->id == id)
+ {
+ extra_defaults= list_delete(extra_defaults, l);
+ my_free((gptr)l, MYF(0));
+ my_free((gptr)d, MYF(0));
+ }
+ l= n;
+ }
+
+ d= (extra_default_t *)my_malloc(sizeof(extra_default_t),
+ MYF(MY_FAE|MY_ZEROFILL));
+ d->id= id;
+ d->name= opt->name;
+ d->n_len= strlen(opt->name);
+ if (opt->arg_type != NO_ARG)
+ switch (opt->var_type & GET_TYPE_MASK) {
+ case GET_BOOL:
+ if (*((int *)opt->value))
+ {
+ d->value= "true";
+ d->v_len= 4;
+ }
+ break;
+ case GET_STR:
+ case GET_STR_ALLOC:
+ d->value= *opt->value;
+ d->v_len= strlen(d->value);
+ break;
+ default:
+ my_printf_error(0, "Error: internal error at %s:%d", MYF(0),
+ __FILE__, __LINE__);
+ exit(1);
+ }
+ list_push(extra_defaults, d);
+ }
+ }
+}
+
+
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)),
char *argument)
@@ -85,16 +205,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)),
switch (optid) {
case '?':
puts
- ("MySQL utility script to upgrade database to the current server version");
+ ("MySQL utility to upgrade database to the current server version");
puts("");
my_print_help(my_long_options);
exit(0);
case '#':
DBUG_PUSH(argument ? argument : default_dbug_option);
break;
- case 'f':
- opt_force= TRUE;
- break;
case 'p':
tty_password= 1;
if (argument)
@@ -109,315 +226,412 @@ get_one_option(int optid, const struct my_option *opt __attribute__ ((unused)),
tty_password= 0;
}
break;
+#ifdef __WIN__
+ case 'W':
+ my_free(opt_protocol, MYF(MY_ALLOW_ZERO_PTR));
+ opt_protocol= my_strdup("pipe", MYF(MY_FAE));
+ break;
+#endif
+ case OPT_MYSQL_PROTOCOL:
+ if (find_type(argument, &sql_protocol_typelib, 0) > 0)
+ {
+ my_free(opt_protocol, MYF(MY_ALLOW_ZERO_PTR));
+ opt_protocol= my_strdup(argument, MYF(MY_FAE));
+ }
+ else
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
+ }
+ break;
+#include <sslopt-case.h>
default:;
- };
+ }
+ set_extra_default(opt->id, opt);
return 0;
}
-/* buffer should be not smaller than FN_REFLEN */
-static my_bool test_file_exists_res(const char *dir, const char *fname,
- char *buffer, char **buf_end)
-{
- MY_STAT stat_info;
-
- *buf_end= strxnmov(buffer, FN_REFLEN-1, dir, "/", fname, NullS);
- unpack_filename(buffer, buffer);
- return my_stat(buffer, &stat_info, MYF(0)) != 0;
-}
-
-
-static my_bool test_file_exists(const char *dir, const char *fname)
-{
- char path[FN_REFLEN];
- char *path_end;
- return test_file_exists_res(dir, fname, path, &path_end);
-}
-
-
static int create_check_file(const char *path)
{
- File check_file= my_open(path, O_CREAT | O_WRONLY, MYF(MY_FAE | MY_WME));
- int error;
-
- if (check_file < 0)
- return 1;
-
- error= my_write(check_file,
- MYSQL_SERVER_VERSION, strlen(MYSQL_SERVER_VERSION),
+ int ret;
+ File fd;
+
+ fd= my_open(path, O_CREAT | O_WRONLY, MYF(MY_FAE | MY_WME));
+ if (fd < 0) {
+ ret= 1;
+ goto error;
+ }
+ ret= my_write(fd, MYSQL_SERVER_VERSION,
+ sizeof(MYSQL_SERVER_VERSION) - 1,
MYF(MY_WME | MY_FNABP));
- error= my_close(check_file, MYF(MY_FAE | MY_WME)) || error;
- return error;
+ ret|= my_close(fd, MYF(MY_FAE | MY_WME));
+error:
+ return ret;
}
-static int create_defaults_file(const char *path, const char *our_defaults_path)
+static int create_defaults_file(const char *path, const char *forced_path)
{
- uint b_read;
- File our_defaults_file, defaults_file;
- char buffer[512];
- char *buffer_end;
- int failed_to_open_count= 0;
- int error;
-
- /* check if the defaults file is needed at all */
- if (!opt_password)
- return 0;
-
-retry_open:
+ int ret;
+ uint cnt;
+ File forced_file, defaults_file;
+
+ DYNAMIC_STRING buf;
+ extra_default_t *d;
+
+ my_delete(path, MYF(0));
+
defaults_file= my_open(path, O_BINARY | O_CREAT | O_WRONLY | O_EXCL,
MYF(MY_FAE | MY_WME));
-
if (defaults_file < 0)
{
- if (failed_to_open_count == 0)
- {
- remove(path);
- failed_to_open_count+= 1;
- goto retry_open;
- }
- else
- return 1;
+ ret= 1;
+ goto out;
+ }
+
+ if (init_dynamic_string(&buf, NULL, my_getpagesize(), FN_REFLEN))
+ {
+ ret= 1;
+ goto error;
}
- upgrade_defaults_created= 1;
- if (our_defaults_path)
+ if (forced_path)
{
- our_defaults_file= my_open(our_defaults_path, O_RDONLY,
- MYF(MY_FAE | MY_WME));
- if (our_defaults_file < 0)
- return 1;
+ forced_file= my_open(forced_path, O_RDONLY, MYF(MY_FAE | MY_WME));
+ if (forced_file < 0)
+ {
+ ret= 1;
+ goto error;
+ }
do
{
- if (((b_read= my_read(our_defaults_file, buffer,
- sizeof(buffer), MYF(MY_WME))) == MY_FILE_ERROR) ||
- my_write(defaults_file, buffer, b_read, MYF(MY_FNABP | MY_WME)))
+ cnt= my_read(forced_file, buf.str, buf.max_length, MYF(MY_WME));
+ if ((cnt == MY_FILE_ERROR)
+ || my_write(defaults_file, buf.str, cnt, MYF(MY_FNABP | MY_WME)))
{
- error= 1;
- goto close_return;
+ ret= 1;
+ my_close(forced_file, MYF(0));
+ goto error;
}
- } while (b_read == sizeof(buffer));
+ } while (cnt == buf.max_length);
+ my_close(forced_file, MYF(0));
}
- buffer_end= strnmov(buffer, "\n[client]", sizeof(buffer));
- if (opt_password)
- buffer_end= strxnmov(buffer_end, sizeof(buffer),
- "\npassword=", opt_password, NullS);
- error= my_write(defaults_file, buffer, (int) (buffer_end - buffer),
- MYF(MY_WME | MY_FNABP));
-close_return:
- return my_close(defaults_file, MYF(MY_WME)) || error;
+
+ dynstr_set(&buf, "\n[client]");
+ while (extra_defaults)
+ {
+ int len;
+
+ d= extra_defaults->data;
+ len= d->n_len + d->v_len + 1;
+ if (buf.length + len >= buf.max_length) /* to avoid realloc() */
+ {
+ if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME)))
+ {
+ ret= 1;
+ goto error;
+ }
+ dynstr_set(&buf, NULL);
+ }
+ if (dynstr_append_mem(&buf, "\n", 1)
+ || dynstr_append_mem(&buf, d->name, d->n_len)
+ || (d->v_len && (dynstr_append_mem(&buf, "=", 1)
+ || dynstr_append_mem(&buf, d->value, d->v_len))))
+ {
+ ret= 1;
+ goto error;
+ }
+ my_delete((gptr)d, MYF(0));
+ list_pop(extra_defaults); /* pop off the head */
+ }
+ if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME)))
+ {
+ ret= 1;
+ goto error;
+ }
+ /* everything's all right */
+ ret= 0;
+error:
+ dynstr_free(&buf);
+
+ if (defaults_file >= 0)
+ ret|= my_close(defaults_file, MYF(MY_WME));
+
+ if (ret)
+ my_delete(path, MYF(0));
+
+out:
+ return ret;
+}
+
+
+/* Compare filenames */
+static int comp_names(struct fileinfo *a, struct fileinfo *b)
+{
+ return (strcmp(a->name,b->name));
+}
+
+
+static int find_file(const char *name, const char *root,
+ uint flags, char *result, size_t len, ...)
+{
+ int ret= 1;
+ va_list va;
+ const char *subdir;
+ char *cp;
+ FILEINFO key;
+
+ /* Init key with name of the file to look for */
+ key.name= (char*)name;
+
+ DBUG_ASSERT(root != NULL);
+
+ cp= strmake(result, root, len);
+ if (cp[-1] != FN_LIBCHAR)
+ *cp++= FN_LIBCHAR;
+
+ va_start(va, len);
+ subdir= (!(flags & MY_SEARCH_SELF)) ? va_arg(va, char *) : "";
+ while (subdir)
+ {
+ MY_DIR *dir;
+ FILEINFO *match;
+ char *cp1;
+
+ cp1= strnmov(cp, subdir, len - (cp - result) - 1);
+
+ dir= my_dir(result, (flags & MY_ISDIR) ? MY_WANT_STAT : MYF(0));
+ if (dir)
+ {
+ match= bsearch(&key, dir->dir_entry, dir->number_off_files,
+ sizeof(FILEINFO), (qsort_cmp)comp_names);
+ if (match)
+ {
+ ret= (flags & MY_ISDIR) ? !MY_S_ISDIR(match->mystat->st_mode) : 0;
+ if (!ret)
+ {
+ if (cp1[-1] != FN_LIBCHAR)
+ *cp1++= FN_LIBCHAR;
+
+ if (!(flags & MY_PARENT))
+ strnmov(cp1, name, len - (cp1 - result));
+ else
+ *cp1= '\0';
+
+ my_dirend(dir);
+ break;
+ }
+ }
+ my_dirend(dir);
+ }
+ subdir= va_arg(va, char *);
+ }
+ va_end(va);
+ return ret;
}
int main(int argc, char **argv)
{
- char bindir[FN_REFLEN];
- char *bindir_end, *buf_end;
- char datadir_buf[FN_REFLEN];
- char mysqlcheck_line[FN_REFLEN], *mysqlcheck_end;
- char check_file_name[FN_REFLEN];
- int check_file;
- char fix_priv_tables_cmd[FN_REFLEN], *fix_cmd_end;
- char script_line[FN_REFLEN];
- int error;
+ int ret;
+
char *forced_defaults_file;
char *forced_extra_defaults;
char *defaults_group_suffix;
- char upgrade_defaults_path[FN_REFLEN], *defaults_to_use= 0;
- char port_socket[100], *port_socket_end;
+ const char *script_line;
+ char *upgrade_defaults_path;
+ char *defaults_to_use= NULL;
+ int upgrade_defaults_created= 0;
+
+ char path[FN_REFLEN];
+ DYNAMIC_STRING cmdline;
MY_INIT(argv[0]);
#ifdef __NETWARE__
setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
#endif
+ /* Check if we are forced to use specific defaults */
+ get_defaults_options(argc, argv,
+ &forced_defaults_file, &forced_extra_defaults,
+ &defaults_group_suffix);
+
load_defaults("my", load_default_groups, &argc, &argv);
- if ((error= handle_options(&argc, &argv, my_long_options, get_one_option)))
- exit(error);
-
+ if (handle_options(&argc, &argv, my_long_options, get_one_option))
+ {
+ ret= 1;
+ goto error;
+ }
if (tty_password)
opt_password= get_tty_password(NullS);
- /* Check if we want to force the use a specific default file */
- get_defaults_options(argc, argv,
- &forced_defaults_file, &forced_extra_defaults,
- &defaults_group_suffix);
-
- port_socket_end= port_socket;
- if (opt_mysql_port)
- port_socket_end= strxnmov(port_socket, sizeof(port_socket) - 1, " --port=",
- opt_mysql_port, NullS);
- if (opt_mysql_unix_port)
- port_socket_end= strxnmov(port_socket_end,
- sizeof(port_socket) -
- (int)(port_socket_end - port_socket) - 1,
- " --socket=", opt_mysql_unix_port, NullS);
- *port_socket_end= 0;
-
- if (basedir)
+ if (init_dynamic_string(&cmdline, NULL, 2 * FN_REFLEN + 128, FN_REFLEN))
{
- bindir_end= strmake(bindir, basedir, sizeof(bindir)-1);
+ ret= 1;
+ goto error;
}
- else
+ if (!basedir)
{
- if (test_file_exists("./share/mysql/english", "errmsg.sys")
- && (test_file_exists("./bin", "mysqld") ||
- test_file_exists("./libexec", "mysqld")))
- {
- my_getwd(bindir, sizeof(bindir), MYF(0));
- bindir_end= bindir + strlen(bindir);
- }
- else
+ my_getwd(path, sizeof(path), MYF(0));
+ basedir= my_strdup(path, MYF(0));
+ if (find_file("errmsg.sys", basedir, MYF(0), path, sizeof(path),
+ "share/mysql/english", NullS)
+ || find_file(mysqld_name, basedir, MYF(0), path, sizeof(path),
+ "bin", "libexec", NullS))
{
- bindir_end= strmake(bindir, DEFAULT_MYSQL_HOME, sizeof(bindir)-1);
+ my_free((gptr)basedir, MYF(0));
+ basedir= (char *)DEFAULT_MYSQL_HOME;
}
}
if (!datadir)
{
- datadir= datadir_buf;
- if (test_file_exists(bindir, "data/mysql"))
- {
- *strxnmov(datadir_buf, sizeof(datadir_buf)-1, bindir, "/data", NullS)= 0;
- }
- else if (test_file_exists(bindir, "var/mysql"))
- {
- *strxnmov(datadir_buf, sizeof(datadir_buf)-1, bindir, "/var", NullS)= 0;
- }
+ if (!find_file("mysql", basedir, MYF(MY_ISDIR|MY_PARENT),
+ path, sizeof(path),
+ "data", "var", NullS))
+ datadir= my_strdup(path, MYF(0));
else
- datadir= (char*) DATADIR;
+ datadir= (char *)DATADIR;
}
-
- strmake(bindir_end, "/bin", sizeof(bindir) - (int) (bindir_end - bindir)-1);
-
- if (!test_file_exists_res
- (bindir, mysqlcheck_name, mysqlcheck_line, &mysqlcheck_end))
+ if (find_file("user.frm", datadir, MYF(0), path, sizeof(path),
+ "mysql", NullS))
{
- printf("Can't find program '%s'\n", mysqlcheck_line);
- puts("Please restart with --basedir=mysql-install-directory");
- exit(1);
+ ret= 1;
+ puts("Can't find data directory. Please restart with"
+ " --datadir=path-to-writable-data-dir");
+ goto error;
}
- if (!test_file_exists(datadir, "mysql/user.frm"))
+ /*
+ Create the modified defaults file to be used by mysqlcheck
+ and mysql tools
+ */
+ fn_format(path, UPGRADE_DEFAULTS_NAME, datadir, "", MYF(0));
+ upgrade_defaults_path= my_strdup(path, MYF(0));
+
+ if (extra_defaults)
{
- puts
- ("Can't find data directory. Please restart with --datadir=path-to-data-dir");
- exit(1);
- }
-
- /* create the modified defaults file to be used by mysqlcheck */
- /* and mysql tools */
- *strxnmov(upgrade_defaults_path, sizeof(upgrade_defaults_path)-1,
- datadir, "/upgrade_defaults", NullS)= 0;
- unpack_filename(upgrade_defaults_path, upgrade_defaults_path);
- if ((error=
- create_defaults_file(upgrade_defaults_path, forced_extra_defaults)))
- goto err_exit;
-
- defaults_to_use= upgrade_defaults_created ?
- upgrade_defaults_path : forced_extra_defaults;
+ ret= create_defaults_file(upgrade_defaults_path, forced_extra_defaults);
+ if (ret)
+ goto error;
+
+ defaults_to_use= upgrade_defaults_path;
+ upgrade_defaults_created= 1;
+ }
+ else
+ defaults_to_use= forced_extra_defaults;
- if (test_file_exists_res(datadir, "mysql_upgrade_info", check_file_name,
- &buf_end) && !opt_force)
+ if (!find_file(MYSQL_UPGRADE_INFO_NAME, datadir, MY_SEARCH_SELF,
+ path, sizeof(path), NULL, NullS)
+ && !opt_force)
{
- char chf_buffer[50];
- int b_read;
- check_file= my_open(check_file_name, O_RDONLY, MYF(0));
- b_read= my_read(check_file, chf_buffer, sizeof(chf_buffer)-1, MYF(0));
- chf_buffer[b_read]= 0;
- my_close(check_file, MYF(0));
- if (!strcmp(chf_buffer, MYSQL_SERVER_VERSION))
+ char buf[sizeof(MYSQL_SERVER_VERSION)];
+ int fd, cnt;
+
+ fd= my_open(path, O_RDONLY, MYF(0));
+ cnt= my_read(fd, buf, sizeof(buf) - 1, MYF(0));
+ my_close(fd, MYF(0));
+ buf[cnt]= 0;
+ if (!strcmp(buf, MYSQL_SERVER_VERSION))
{
if (opt_verbose)
- puts("mysql_upgrade already done for this version");
+ puts("mysql_upgrade has already been done for this version");
goto fix_priv_tables;
}
}
+
+ if (find_file(mysqlcheck_name, basedir, MYF(0), path, sizeof(path),
+ "bin", NullS))
+ {
+ ret= 1;
+ printf("Can't find program '%s'\n", mysqlcheck_name);
+ puts("Please restart with --basedir=mysql-install-directory");
+ goto error;
+ }
+ else
+ dynstr_set(&cmdline, path);
if (defaults_to_use)
{
- mysqlcheck_end= strxnmov(mysqlcheck_end,
- sizeof(mysqlcheck_line) - (int) (mysqlcheck_end -
- mysqlcheck_line),
- " --defaults-extra-file=", defaults_to_use,NullS);
+ dynstr_append(&cmdline, " --defaults-extra-file=");
+ dynstr_append(&cmdline, defaults_to_use);
}
-
- mysqlcheck_end= strxnmov(mysqlcheck_end,
- sizeof(mysqlcheck_line) -
- (int) (mysqlcheck_end - mysqlcheck_line - 1),
- " --check-upgrade --all-databases --auto-repair --user=",
- user, port_socket, NullS);
- *mysqlcheck_end= 0;
+
+ dynstr_append(&cmdline, " --check-upgrade --all-databases"
+ " --auto-repair --user=");
+ dynstr_append(&cmdline, user);
if (opt_verbose)
- printf("Running %s\n", mysqlcheck_line);
- if ((error= system(mysqlcheck_line)))
+ printf("Running %s\n", cmdline.str);
+
+ ret= system(cmdline.str);
+ if (ret)
{
- printf("Error executing '%s'\n", mysqlcheck_line);
- goto err_exit;
+ printf("Error executing '%s'\n", cmdline.str);
+ goto error;
}
- if ((error= create_check_file(check_file_name)))
- goto err_exit;
+ fn_format(path, MYSQL_UPGRADE_INFO_NAME, datadir, "", MYF(0));
+ ret= create_check_file(path);
+ if (ret)
+ goto error;
fix_priv_tables:
- if (!test_file_exists_res(bindir, mysql_name,
- fix_priv_tables_cmd, &fix_cmd_end))
+ if (find_file(mysql_name, basedir, MYF(0), path, sizeof(path),
+ "bin", NullS))
{
- puts("Could not find MySQL command-line client (mysql).");
- puts
- ("Please use --basedir to specify the directory where MySQL is installed.");
- error= 1;
- goto err_exit;
+ ret= 1;
+ puts("Could not find MySQL command-line client (mysql).\n"
+ "Please use --basedir to specify the directory"
+ " where MySQL is installed.");
+ goto error;
}
-
- if (!test_file_exists_res(basedir,
- "support_files/mysql_fix_privilege_tables.sql",
- script_line, &buf_end)
- && !test_file_exists_res(basedir, "share/mysql_fix_privilege_tables.sql",
- script_line, &buf_end)
- && !test_file_exists_res(basedir,
- "share/mysql/mysql_fix_privilege_tables.sql",
- script_line, &buf_end)
- && !test_file_exists_res(basedir,
- "scripts/mysql_fix_privilege_tables.sql",
- script_line, &buf_end)
- && !test_file_exists_res("/usr/local/mysql/share/mysql",
- "mysql_fix_privilege_tables.sql", script_line,
- &buf_end))
+ else
+ dynstr_set(&cmdline, path);
+
+ if (find_file(MYSQL_FIX_PRIV_TABLES_NAME, basedir, MYF(0),
+ path, sizeof(path),
+ "support_files", "share/mysql", "scripts",
+ NullS)
+ && find_file(MYSQL_FIX_PRIV_TABLES_NAME, "/usr/local/mysql", MYF(0),
+ path, sizeof(path),
+ "share/mysql", NullS))
{
- puts("Could not find file mysql_fix_privilege_tables.sql");
- puts
- ("Please use --basedir to specify the directory where MySQL is installed");
- error= 1;
- goto err_exit;
+ ret= 1;
+ puts("Could not find file " MYSQL_FIX_PRIV_TABLES_NAME "\n"
+ "Please use --basedir to specify the directory"
+ " where MySQL is installed");
+ goto error;
}
+ else
+ script_line= my_strdup(path, MYF(0));
if (defaults_to_use)
{
- fix_cmd_end= strxnmov(fix_cmd_end,
- sizeof(fix_priv_tables_cmd) -
- (int) (fix_cmd_end - fix_priv_tables_cmd - 1),
- " --defaults-extra-file=", defaults_to_use, NullS);
+ dynstr_append(&cmdline, " --defaults-extra-file=");
+ dynstr_append(&cmdline, defaults_to_use);
}
- fix_cmd_end= strxnmov(fix_cmd_end,
- sizeof(fix_priv_tables_cmd) - (int) (fix_cmd_end -
- fix_priv_tables_cmd),
- " --user=", user, port_socket, " mysql < ", script_line, NullS);
- *fix_cmd_end= 0;
+ dynstr_append(&cmdline, " --force --no-auto-rehash --batch --user=");
+ dynstr_append(&cmdline, user);
+ dynstr_append(&cmdline, " mysql < ");
+ dynstr_append(&cmdline, script_line);
- if ((error= system(fix_priv_tables_cmd)))
- {
- /* Problem is that the 'Duplicate column' error */
- /* which is not a bug for the script makes 'mysql' return */
- /* an error */
- /* printf("Error executing '%s'\n", fix_priv_tables_cmd); */
- }
+ if (opt_verbose)
+ printf("Running %s\n", cmdline.str);
+
+ ret= system(cmdline.str);
+ if (ret)
+ printf("Error executing '%s'\n", cmdline.str);
+
+error:
+ dynstr_free(&cmdline);
-err_exit:
if (upgrade_defaults_created)
my_delete(upgrade_defaults_path, MYF(0));
+
my_end(info_flag ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
- return error;
-} /* main */
+ return ret;
+}
+
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index c04c2ecabd6..ff4e0b5a5cf 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1088,7 +1088,7 @@ could be out of memory");
}
if (len < 8 && net->read_pos[0] == 254)
break; // end of data
- DBUG_PRINT("info",( "len= %u, net->read_pos[5] = %d\n",
+ DBUG_PRINT("info",( "len: %lu, net->read_pos[5]: %d\n",
len, net->read_pos[5]));
if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
len - 1, &error_msg,
diff --git a/client/mysqldump.c b/client/mysqldump.c
index b3a209c6086..05765ef2a02 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -30,14 +30,14 @@
** master/autocommit code by Brian Aker <brian@tangent.org>
** SSL by
** Andrei Errapart <andreie@no.spam.ee>
-** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee>
+** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee>
** XML by Gary Huntress <ghuntress@mediaone.net> 10/10/01, cleaned up
** and adapted to mysqldump 05/11/01 by Jani Tolonen
** Added --single-transaction option 06/06/2002 by Peter Zaitsev
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
*/
-#define DUMP_VERSION "10.10"
+#define DUMP_VERSION "10.11"
#include <my_global.h>
#include <my_sys.h>
@@ -45,6 +45,7 @@
#include <m_string.h>
#include <m_ctype.h>
#include <hash.h>
+#include <stdarg.h>
#include "client_priv.h"
#include "mysql.h"
@@ -98,7 +99,7 @@ static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
opt_dump_triggers= 0, opt_routines=0, opt_tz_utc=1;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*mysql=0;
-static my_bool insert_pat_inited=0;
+static my_bool insert_pat_inited= 0, info_flag;
static DYNAMIC_STRING insert_pat;
static char *opt_password=0,*current_user=0,
*current_host=0,*path=0,*fields_terminated=0,
@@ -106,6 +107,7 @@ static char *opt_password=0,*current_user=0,
*where=0, *order_by=0,
*opt_compatible_mode_str= 0,
*err_ptr= 0;
+static char **defaults_argv= 0;
static char compatible_mode_normal_str[255];
static ulong opt_compatible_mode= 0;
#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
@@ -115,7 +117,7 @@ static my_string opt_mysql_unix_port=0;
static int first_error=0;
static DYNAMIC_STRING extended_row;
#include <sslopt-vars.h>
-FILE *md_result_file;
+FILE *md_result_file= 0;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
#endif
@@ -214,6 +216,8 @@ static struct my_option my_long_options[] =
{"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
(gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", (gptr*) &info_flag,
+ (gptr*) &info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", (gptr*) &default_charset,
(gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -523,6 +527,8 @@ static void write_header(FILE *sql_file, char *db_name)
if (opt_xml)
{
fputs("<?xml version=\"1.0\"?>\n", sql_file);
+ /* Schema reference. Allows use of xsi:nil for NULL values and
+ xsi:type to define an element's data type. */
fputs("<mysqldump ", sql_file);
fputs("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
sql_file);
@@ -625,14 +631,6 @@ byte* get_table_key(const char *entry, uint *length,
}
-void init_table_rule_hash(HASH* h)
-{
- if (hash_init(h, charset_info, 16, 0, 0,
- (hash_get_key) get_table_key,
- (hash_free_key) free_table_ent, 0))
- exit(EX_EOM);
-}
-
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
@@ -675,6 +673,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
break;
case '#':
DBUG_PUSH(argument ? argument : default_dbug_option);
+ info_flag= 1;
break;
#include <sslopt-case.h>
case 'V': print_version(); exit(0);
@@ -715,9 +714,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
fprintf(stderr, "Illegal use of option --ignore-table=<database>.<table>\n");
exit(1);
}
- if (!hash_inited(&ignore_table))
- init_table_rule_hash(&ignore_table);
-
if (my_hash_insert(&ignore_table, (byte*)my_strdup(argument, MYF(0))))
exit(EX_EOM);
break;
@@ -793,9 +789,21 @@ static int get_options(int *argc, char ***argv)
md_result_file= stdout;
load_defaults("my",load_default_groups,argc,argv);
+ defaults_argv= *argv;
+
+ if (hash_init(&ignore_table, charset_info, 16, 0, 0,
+ (hash_get_key) get_table_key,
+ (hash_free_key) free_table_ent, 0))
+ return(EX_EOM);
+ /* Don't copy cluster internal log tables */
+ if (my_hash_insert(&ignore_table,
+ (byte*) my_strdup("mysql.apply_status", MYF(MY_WME))) ||
+ my_hash_insert(&ignore_table,
+ (byte*) my_strdup("mysql.schema", MYF(MY_WME))))
+ return(EX_EOM);
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
- exit(ho_error);
+ if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
+ return(ho_error);
*mysql_params->p_max_allowed_packet= opt_max_allowed_packet;
*mysql_params->p_net_buffer_length= opt_net_buffer_length;
@@ -807,7 +815,7 @@ static int get_options(int *argc, char ***argv)
{
fprintf(stderr,
"%s: You must use option --tab with --fields-...\n", my_progname);
- return(1);
+ return(EX_USAGE);
}
/* Ensure consistency of the set of binlog & locking options */
@@ -817,7 +825,7 @@ static int get_options(int *argc, char ***argv)
{
fprintf(stderr, "%s: You can't use --single-transaction and "
"--lock-all-tables at the same time.\n", my_progname);
- return(1);
+ return(EX_USAGE);
}
if (opt_master_data)
opt_lock_all_tables= !opt_single_transaction;
@@ -826,14 +834,14 @@ static int get_options(int *argc, char ***argv)
if (enclosed && opt_enclosed)
{
fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
- return(1);
+ return(EX_USAGE);
}
if ((opt_databases || opt_alldbs) && path)
{
fprintf(stderr,
"%s: --databases or --all-databases can't be used with --tab.\n",
my_progname);
- return(1);
+ return(EX_USAGE);
}
if (strcmp(default_charset, charset_info->csname) &&
!(charset_info= get_charset_by_csname(default_charset,
@@ -842,7 +850,7 @@ static int get_options(int *argc, char ***argv)
if ((*argc < 1 && !opt_alldbs) || (*argc > 0 && opt_alldbs))
{
short_usage();
- return 1;
+ return EX_USAGE;
}
if (tty_password)
opt_password=get_tty_password(NullS);
@@ -917,6 +925,23 @@ static FILE* open_sql_file_for_table(const char* table)
}
+static void free_resources()
+{
+ if (md_result_file && md_result_file != stdout)
+ my_fclose(md_result_file, MYF(0));
+ my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
+ if (hash_inited(&ignore_table))
+ hash_free(&ignore_table);
+ if (extended_insert)
+ dynstr_free(&extended_row);
+ if (insert_pat_inited)
+ dynstr_free(&insert_pat);
+ if (defaults_argv)
+ free_defaults(defaults_argv);
+ my_end(info_flag ? MY_CHECK_ERROR : 0);
+}
+
+
static void safe_exit(int error)
{
if (!first_error)
@@ -925,18 +950,19 @@ static void safe_exit(int error)
return;
if (mysql)
mysql_close(mysql);
+ free_resources();
exit(error);
}
-/* safe_exit */
/*
-** dbConnect -- connects to the host and selects DB.
+ db_connect -- connects to the host and selects DB.
*/
-static int dbConnect(char *host, char *user,char *passwd)
+
+static int connect_to_db(char *host, char *user,char *passwd)
{
char buff[20+FN_REFLEN];
- DBUG_ENTER("dbConnect");
+ DBUG_ENTER("connect_to_db");
verbose_msg("-- Connecting to %s...\n", host ? host : "localhost");
mysql_init(&mysql_connection);
@@ -957,11 +983,11 @@ static int dbConnect(char *host, char *user,char *passwd)
#endif
mysql_options(&mysql_connection, MYSQL_SET_CHARSET_NAME, default_charset);
if (!(mysql= mysql_real_connect(&mysql_connection,host,user,passwd,
- NULL,opt_mysql_port,opt_mysql_unix_port,
- 0)))
+ NULL,opt_mysql_port,opt_mysql_unix_port,
+ 0)))
{
DB_error(&mysql_connection, "when trying to connect");
- return 1;
+ DBUG_RETURN(1);
}
/*
Don't dump SET NAMES with a pre-4.1 server (bug#7997).
@@ -978,7 +1004,7 @@ static int dbConnect(char *host, char *user,char *passwd)
if (mysql_query_with_error_report(mysql, 0, buff))
{
safe_exit(EX_MYSQLERR);
- return 1;
+ DBUG_RETURN(1);
}
/*
set time_zone to UTC to allow dumping date types between servers with
@@ -990,11 +1016,11 @@ static int dbConnect(char *host, char *user,char *passwd)
if (mysql_query_with_error_report(mysql, 0, buff))
{
safe_exit(EX_MYSQLERR);
- return 1;
+ DBUG_RETURN(1);
}
}
- return 0;
-} /* dbConnect */
+ DBUG_RETURN(0);
+} /* connect_to_db */
/*
@@ -1123,7 +1149,7 @@ static char *quote_for_like(const char *name, char *buff)
SYNOPSIS
print_quoted_xml()
- output - output file
+ xml_file - output file
str - string to print
len - its length
@@ -1160,34 +1186,63 @@ static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
/*
- Print xml tag with one attribute.
+ Print xml tag. Optionally add attribute(s).
SYNOPSIS
- print_xml_tag1()
- xml_file - output file
- sbeg - line beginning
- stag_atr - tag and attribute
- sval - value of attribute
- send - line ending
+ print_xml_tag(xml_file, sbeg, send, tag_name, first_attribute_name,
+ ..., attribute_name_n, attribute_value_n, NullS)
+ xml_file - output file
+ sbeg - line beginning
+ send - line ending
+ tag_name - XML tag name.
+ first_attribute_name - tag and first attribute
+ first_attribute_value - (Implied) value of first attribute
+ attribute_name_n - attribute n
+ attribute_value_n - value of attribute n
DESCRIPTION
- Print tag with one attribute to the xml_file. Format is:
- sbeg<stag_atr="sval">send
+ Print XML tag with any number of attribute="value" pairs to the xml_file.
+
+ Format is:
+ sbeg<tag_name first_attribute_name="first_attribute_value" ...
+ attribute_name_n="attribute_value_n">send
NOTE
- sval MUST be a NULL terminated string.
- sval string will be qouted before output.
+ Additional arguments must be present in attribute/value pairs.
+ The last argument should be the null character pointer.
+ All attribute_value arguments MUST be NULL terminated strings.
+ All attribute_value arguments will be quoted before output.
*/
-static void print_xml_tag1(FILE * xml_file, const char* sbeg,
- const char* stag_atr, const char* sval,
- const char* send)
+static void print_xml_tag(FILE * xml_file, const char* sbeg, const char* send,
+ const char* tag_name,
+ const char* first_attribute_name, ...)
{
+ va_list arg_list;
+ const char *attribute_name, *attribute_value;
+
fputs(sbeg, xml_file);
- fputs("<", xml_file);
- fputs(stag_atr, xml_file);
- fputs("\"", xml_file);
- print_quoted_xml(xml_file, sval, strlen(sval));
- fputs("\">", xml_file);
+ fputc('<', xml_file);
+ fputs(tag_name, xml_file);
+
+ va_start(arg_list, first_attribute_name);
+ attribute_name= first_attribute_name;
+ while (attribute_name != NullS)
+ {
+ attribute_value= va_arg(arg_list, char *);
+ DBUG_ASSERT(attribute_value != NullS);
+
+ fputc(' ', xml_file);
+ fputs(attribute_name, xml_file);
+ fputc('\"', xml_file);
+
+ print_quoted_xml(xml_file, attribute_value, strlen(attribute_value));
+ fputc('\"', xml_file);
+
+ attribute_name= va_arg(arg_list, char *);
+ }
+ va_end(arg_list);
+
+ fputc('>', xml_file);
fputs(send, xml_file);
check_io(xml_file);
}
@@ -1271,6 +1326,28 @@ static void print_xml_row(FILE *xml_file, const char *row_name,
}
/*
+ Print hex value for blob data.
+
+ SYNOPSIS
+ print_blob_as_hex()
+ output_file - output file
+ str - string to print
+ len - its length
+
+ DESCRIPTION
+ Print hex value for blob data.
+*/
+
+static void print_blob_as_hex(FILE *output_file, const char *str, ulong len)
+{
+ /* sakaik got the idea to to provide blob's in hex notation. */
+ const char *ptr= str, *end= ptr + len;
+ for (; ptr < end ; ptr++)
+ fprintf(output_file, "%02X", *((uchar *)ptr));
+ check_io(output_file);
+}
+
+/*
dump_routines_for_db
-- retrievs list of routines for a given db, and prints out
the CREATE PROCEDURE definition into the output (the dump).
@@ -1342,7 +1419,7 @@ static uint dump_routines_for_db(char *db)
routine body of other routines that are not the creator of!
*/
DBUG_PRINT("info",("length of body for %s row[2] '%s' is %d",
- routine_name, row[2], strlen(row[2])));
+ routine_name, row[2], (int) strlen(row[2])));
if (strlen(row[2]))
{
char *query_str= NULL;
@@ -1465,7 +1542,11 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
complete_insert= opt_complete_insert;
if (!insert_pat_inited)
- insert_pat_inited= init_dynamic_string(&insert_pat, "", 1024, 1024);
+ {
+ insert_pat_inited= 1;
+ if (init_dynamic_string(&insert_pat, "", 1024, 1024))
+ safe_exit(EX_MYSQLERR);
+ }
else
dynstr_set(&insert_pat, "");
}
@@ -1714,7 +1795,8 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (!opt_xml)
fprintf(sql_file, "CREATE TABLE %s (\n", result_table);
else
- print_xml_tag1(sql_file, "\t", "table_structure name=", table, "\n");
+ print_xml_tag(sql_file, "\t", "\n", "table_structure", "name=", table,
+ NullS);
check_io(sql_file);
}
@@ -1919,7 +2001,7 @@ continue_xml:
write_footer(sql_file);
my_fclose(sql_file, MYF(MY_WME));
}
- DBUG_RETURN(num_fields);
+ DBUG_RETURN((uint) num_fields);
} /* get_table_structure */
@@ -1933,7 +2015,7 @@ continue_xml:
*/
-static void dump_triggers_for_table (char *table, char *db)
+static void dump_triggers_for_table(char *table, char *db)
{
char *result_table;
char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3];
@@ -2121,7 +2203,7 @@ static void dump_table(char *table, char *db)
The "table" could be a view. If so, we don't do anything here.
*/
if (strcmp (table_type, "VIEW") == 0)
- return;
+ DBUG_VOID_RETURN;
/* Check --no-data flag */
if (opt_no_data)
@@ -2283,8 +2365,8 @@ static void dump_table(char *table, char *db)
rownr=0;
init_length=(uint) insert_pat.length+4;
if (opt_xml)
- print_xml_tag1(md_result_file, "\t", "table_data name=", table, "\n");
-
+ print_xml_tag(md_result_file, "\t", "\n", "table_data", "name=", table,
+ NullS);
if (opt_autocommit)
{
fprintf(md_result_file, "set autocommit=0;\n");
@@ -2338,7 +2420,7 @@ static void dump_table(char *table, char *db)
field->type == MYSQL_TYPE_LONG_BLOB ||
field->type == MYSQL_TYPE_MEDIUM_BLOB ||
field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0;
- if (extended_insert)
+ if (extended_insert && !opt_xml)
{
if (i == 0)
dynstr_set(&extended_row,"(");
@@ -2427,18 +2509,25 @@ static void dump_table(char *table, char *db)
{
if (opt_xml)
{
- print_xml_tag1(md_result_file, "\t\t", "field name=",
- field->name, "");
- print_quoted_xml(md_result_file, row[i], length);
+ if (opt_hex_blob && is_blob && length)
+ {
+ /* Define xsi:type="xs:hexBinary" for hex encoded data */
+ print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
+ field->name, "xsi:type=", "xs:hexBinary", NullS);
+ print_blob_as_hex(md_result_file, row[i], length);
+ }
+ else
+ {
+ print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
+ field->name, NullS);
+ print_quoted_xml(md_result_file, row[i], length);
+ }
fputs("</field>\n", md_result_file);
}
else if (opt_hex_blob && is_blob && length)
{
- /* sakaik got the idea to to provide blob's in hex notation. */
- char *ptr= row[i], *end= ptr + length;
fputs("0x", md_result_file);
- for (; ptr < end ; ptr++)
- fprintf(md_result_file, "%02X", *((uchar *)ptr));
+ print_blob_as_hex(md_result_file, row[i], length);
}
else
unescape(md_result_file, row[i], length);
@@ -2449,8 +2538,8 @@ static void dump_table(char *table, char *db)
char *ptr= row[i];
if (opt_xml)
{
- print_xml_tag1(md_result_file, "\t\t", "field name=",
- field->name, "");
+ print_xml_tag(md_result_file, "\t\t", "", "field", "name=",
+ field->name, NullS);
fputs(!my_isalpha(charset_info, *ptr) ? ptr: "NULL",
md_result_file);
fputs("</field>\n", md_result_file);
@@ -2631,6 +2720,8 @@ static int dump_databases(char **db_names)
{
int result=0;
char **db;
+ DBUG_ENTER("dump_databases");
+
for (db= db_names ; *db ; db++)
{
if (dump_all_tables_in_db(*db))
@@ -2644,7 +2735,7 @@ static int dump_databases(char **db_names)
result=1;
}
}
- return result;
+ DBUG_RETURN(result);
} /* dump_databases */
@@ -2659,7 +2750,7 @@ RETURN VALUES
0 Success.
1 Failure.
*/
-int init_dumping_views(char *qdatabase)
+int init_dumping_views(char *qdatabase __attribute__((unused)))
{
return 0;
} /* init_dumping_views */
@@ -2756,12 +2847,11 @@ static int init_dumping(char *database, int init_func(char*))
} /* init_dumping */
+/* Return 1 if we should copy the table */
+
my_bool include_table(byte* hash_key, uint len)
{
- if (hash_search(&ignore_table, (byte*) hash_key, len))
- return FALSE;
-
- return TRUE;
+ return !hash_search(&ignore_table, (byte*) hash_key, len);
}
@@ -2770,18 +2860,18 @@ static int dump_all_tables_in_db(char *database)
char *table;
uint numrows;
char table_buff[NAME_LEN*2+3];
-
char hash_key[2*NAME_LEN+2]; /* "db.tablename" */
char *afterdot;
int using_mysql_db= my_strcasecmp(&my_charset_latin1, database, "mysql");
+ DBUG_ENTER("dump_all_tables_in_db");
afterdot= strmov(hash_key, database);
*afterdot++= '.';
if (init_dumping(database, init_dumping_tables))
- return 1;
+ DBUG_RETURN(1);
if (opt_xml)
- print_xml_tag1(md_result_file, "", "database name=", database, "\n");
+ print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
if (lock_tables)
{
DYNAMIC_STRING query;
@@ -2833,7 +2923,7 @@ static int dump_all_tables_in_db(char *database)
fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n");
fprintf(md_result_file,"\n/*! FLUSH PRIVILEGES */;\n");
}
- return 0;
+ DBUG_RETURN(0);
} /* dump_all_tables_in_db */
@@ -2858,7 +2948,7 @@ static my_bool dump_all_views_in_db(char *database)
if (init_dumping(database, init_dumping_views))
return 1;
if (opt_xml)
- print_xml_tag1(md_result_file, "", "database name=", database, "\n");
+ print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
if (lock_tables)
{
DYNAMIC_STRING query;
@@ -2997,7 +3087,7 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
/* We shall countinue here, if --force was given */
}
if (opt_xml)
- print_xml_tag1(md_result_file, "", "database name=", db, "\n");
+ print_xml_tag(md_result_file, "", "\n", "database", "name=", db, NullS);
/* Dump each selected table */
for (pos= dump_tables; pos < end; pos++)
@@ -3104,7 +3194,7 @@ static int do_reset_master(MYSQL *mysql_con)
}
-static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now)
+static int start_transaction(MYSQL *mysql_con)
{
/*
We use BEGIN for old servers. --single-transaction --master-data will fail
@@ -3119,10 +3209,8 @@ static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now)
"SET SESSION TRANSACTION ISOLATION "
"LEVEL REPEATABLE READ") ||
mysql_query_with_error_report(mysql_con, 0,
- consistent_read_now ?
"START TRANSACTION "
- "WITH CONSISTENT SNAPSHOT" :
- "BEGIN"));
+ "/*!40100 WITH CONSISTENT SNAPSHOT */"));
}
@@ -3197,7 +3285,6 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
/*
-
SYNOPSIS
Check if we the table is one of the table types that should be ignored:
@@ -3237,8 +3324,8 @@ char check_if_ignore_table(const char *table_name, char *table_type)
{
if (mysql_errno(mysql) != ER_PARSE_ERROR)
{ /* If old MySQL version */
- verbose_msg("-- Warning: Couldn't get status information for " \
- "table %s (%s)\n", table_name,mysql_error(mysql));
+ verbose_msg("-- Warning: Couldn't get status information for "
+ "table %s (%s)\n", table_name, mysql_error(mysql));
DBUG_RETURN(result); /* assume table is ok */
}
}
@@ -3593,26 +3680,31 @@ static my_bool get_view_structure(char *table, char* db)
int main(int argc, char **argv)
{
+ int exit_code;
MY_INIT("mysqldump");
compatible_mode_normal_str[0]= 0;
default_charset= (char *)mysql_universal_client_charset;
bzero((char*) &ignore_table, sizeof(ignore_table));
- if (get_options(&argc, &argv))
+ exit_code= get_options(&argc, &argv);
+ if (exit_code)
{
- my_end(0);
- exit(EX_USAGE);
+ free_resources(0);
+ exit(exit_code);
}
- if (dbConnect(current_host, current_user, opt_password))
+ if (connect_to_db(current_host, current_user, opt_password))
+ {
+ free_resources(0);
exit(EX_MYSQLERR);
+ }
if (!path)
write_header(md_result_file, *argv);
if ((opt_lock_all_tables || opt_master_data) &&
do_flush_tables_read_lock(mysql))
goto err;
- if (opt_single_transaction && start_transaction(mysql, test(opt_master_data)))
+ if (opt_single_transaction && start_transaction(mysql))
goto err;
if (opt_delete_master_logs && do_reset_master(mysql))
goto err;
@@ -3652,15 +3744,6 @@ err:
dbDisconnect(current_host);
if (!path)
write_footer(md_result_file);
- if (md_result_file != stdout)
- my_fclose(md_result_file, MYF(0));
- my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR));
- if (hash_inited(&ignore_table))
- hash_free(&ignore_table);
- if (extended_insert)
- dynstr_free(&extended_row);
- if (insert_pat_inited)
- dynstr_free(&insert_pat);
- my_end(0);
+ free_resources();
return(first_error);
} /* main */
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 261a2ae2870..77d7ddd345e 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -14,36 +14,25 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* mysqltest test tool
- * See the manual for more information
- * TODO: document better how mysqltest works
- *
- * Written by:
- * Sasha Pachev <sasha@mysql.com>
- * Matt Wagner <matt@mysql.com>
- * Monty
- * Jani
- * Holyfoot
- **/
-
-/**********************************************************************
- TODO:
+/*
+ mysqltest
-- Do comparison line by line, instead of doing a full comparison of
- the text file. This will save space as we don't need to keep many
- results in memory. It will also make it possible to do simple
- 'comparison' fixes like accepting the result even if a float differed
- in the last decimals.
+ Tool used for executing a .test file
-- Don't buffer lines from the test that you don't expect to need
- again.
+ See the "MySQL Test framework manual" for more information
+ http://dev.mysql.com/doc/mysqltest/en/index.html
-- Change 'read_line' to be faster by using the readline.cc code;
- We can do better than calling feof() for each character!
+ Please keep the test framework tools identical in all versions!
-**********************************************************************/
+ Written by:
+ Sasha Pachev <sasha@mysql.com>
+ Matt Wagner <matt@mysql.com>
+ Monty
+ Jani
+ Holyfoot
+*/
-#define MTEST_VERSION "2.6"
+#define MTEST_VERSION "3.0"
#include <my_global.h>
#include <mysql_embed.h>
@@ -52,18 +41,18 @@
#include <mysql.h>
#include <mysql_version.h>
#include <mysqld_error.h>
+#include <errmsg.h>
#include <m_ctype.h>
#include <my_dir.h>
-#include <errmsg.h> /* Error codes */
#include <hash.h>
#include <my_getopt.h>
#include <stdarg.h>
-#include <sys/stat.h>
#include <violite.h>
-#include "my_regex.h" /* Our own version of lib */
+#include "my_regex.h" /* Our own version of regex */
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
+
#ifndef WEXITSTATUS
# ifdef __WIN__
# define WEXITSTATUS(stat_val) (stat_val)
@@ -71,145 +60,115 @@
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
# endif
#endif
-/* MAX_QUERY is 256K -- there is a test in sp-big that is >128K */
-#define MAX_QUERY (256*1024)
-#define MAX_VAR_NAME 256
-#define MAX_COLUMNS 256
-#define MAX_CONS 128
-#define MAX_INCLUDE_DEPTH 16
-#define INIT_Q_LINES 1024
-#define MIN_VAR_ALLOC 32
-#define BLOCK_STACK_DEPTH 32
-#define MAX_EXPECTED_ERRORS 10
-#define QUERY_SEND 1
-#define QUERY_REAP 2
-#ifndef MYSQL_MANAGER_PORT
-#define MYSQL_MANAGER_PORT 23546
-#endif
-#define MAX_SERVER_ARGS 64
-
-
-#define SLAVE_POLL_INTERVAL 300000 /* 0.3 of a sec */
-#define DEFAULT_DELIMITER ";"
-#define MAX_DELIMITER 16
-
-#define RESULT_OK 0
-#define RESULT_CONTENT_MISMATCH 1
-#define RESULT_LENGTH_MISMATCH 2
-
-enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
- OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC,
- OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
- OPT_SSL_CIPHER,OPT_PS_PROTOCOL,OPT_SP_PROTOCOL,OPT_CURSOR_PROTOCOL,
- OPT_VIEW_PROTOCOL, OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES};
-/* ************************************************************************ */
-/*
- The list of error codes to --error are stored in an internal array of
- structs. This struct can hold numeric SQL error codes or SQLSTATE codes
- as strings. The element next to the last active element in the list is
- set to type ERR_EMPTY. When an SQL statement returns an error, we use
- this list to check if this is an expected error.
-*/
-
-enum match_err_type
-{
- ERR_EMPTY= 0,
- ERR_ERRNO,
- ERR_SQLSTATE
+#define MAX_VAR_NAME_LENGTH 256
+#define MAX_COLUMNS 256
+#define MAX_EMBEDDED_SERVER_ARGS 64
+#define MAX_DELIMITER_LENGTH 16
+
+/* Flags controlling send and reap */
+#define QUERY_SEND_FLAG 1
+#define QUERY_REAP_FLAG 2
+
+ enum {
+ RESULT_OK= 0,
+ RESULT_CONTENT_MISMATCH= 1,
+ RESULT_LENGTH_MISMATCH= 2
+ };
+
+enum {
+ OPT_SKIP_SAFEMALLOC=256, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT,
+ OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER, OPT_PS_PROTOCOL,
+ OPT_SP_PROTOCOL, OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL,
+ OPT_SSL_VERIFY_SERVER_CERT, OPT_MAX_CONNECT_RETRIES,
+ OPT_MARK_PROGRESS, OPT_CHARSETS_DIR
};
-typedef struct
-{
- enum match_err_type type;
- union
- {
- uint errnum;
- char sqlstate[SQLSTATE_LENGTH+1]; /* \0 terminated string */
- } code;
-} match_err;
-
-typedef struct
-{
- const char *name;
- long code;
-} st_error;
-
-static st_error global_error[] =
-{
-#include <mysqld_ername.h>
- { 0, 0 }
-};
-
-static match_err global_expected_errno[MAX_EXPECTED_ERRORS];
-static uint global_expected_errors;
-
-/* ************************************************************************ */
-
static int record= 0, opt_sleep= -1;
-static char *db = 0, *pass=0;
-const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./";
-static int port = 0;
+static char *db= 0, *pass= 0;
+const char *user= 0, *host= 0, *unix_sock= 0, *opt_basedir= "./";
+const char *opt_include= 0, *opt_charsets_dir;
+static int port= 0;
static int opt_max_connect_retries;
-static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0;
+static my_bool opt_compress= 0, silent= 0, verbose= 0;
static my_bool tty_password= 0;
+static my_bool opt_mark_progress= 0;
static my_bool ps_protocol= 0, ps_protocol_enabled= 0;
static my_bool sp_protocol= 0, sp_protocol_enabled= 0;
static my_bool view_protocol= 0, view_protocol_enabled= 0;
static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0;
-static int parsing_disabled= 0;
-const char *manager_user="root",*manager_host=0;
-char *manager_pass=0;
-int manager_port=MYSQL_MANAGER_PORT;
-int manager_wait_timeout=3;
-MYSQL_MANAGER* manager=0;
+static my_bool parsing_disabled= 0;
+static my_bool display_result_vertically= FALSE, display_metadata= FALSE;
+static my_bool disable_query_log= 0, disable_result_log= 0;
+static my_bool disable_warnings= 0, disable_ps_warnings= 0;
+static my_bool disable_info= 1;
+static my_bool abort_on_error= 1;
static char **default_argv;
-static const char *load_default_groups[]= { "mysqltest","client",0 };
-static char line_buffer[MAX_DELIMITER], *line_buffer_pos= line_buffer;
+static const char *load_default_groups[]= { "mysqltest", "client", 0 };
+static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
-typedef struct
-{
- FILE* file;
- const char *file_name;
- uint lineno; /* Current line in file */
-} test_file;
+static uint start_lineno= 0; /* Start line of current command */
-static test_file file_stack[MAX_INCLUDE_DEPTH];
-static test_file* cur_file;
-static test_file* file_stack_end;
-uint start_lineno= 0; /* Start line of query */
+static char delimiter[MAX_DELIMITER_LENGTH]= ";";
+static uint delimiter_length= 1;
static char TMPDIR[FN_REFLEN];
-static char delimiter[MAX_DELIMITER]= DEFAULT_DELIMITER;
-static uint delimiter_length= 1;
/* Block stack */
-enum block_cmd { cmd_none, cmd_if, cmd_while };
-typedef struct
+enum block_cmd {
+ cmd_none,
+ cmd_if,
+ cmd_while
+};
+
+struct st_block
{
int line; /* Start line of block */
my_bool ok; /* Should block be executed */
enum block_cmd cmd; /* Command owning the block */
-} BLOCK;
-static BLOCK block_stack[BLOCK_STACK_DEPTH];
-static BLOCK *cur_block, *block_stack_end;
+};
+
+static struct st_block block_stack[32];
+static struct st_block *cur_block, *block_stack_end;
+
+/* Open file stack */
+struct st_test_file
+{
+ FILE* file;
+ const char *file_name;
+ uint lineno; /* Current line in file */
+};
+
+static struct st_test_file file_stack[16];
+static struct st_test_file* cur_file;
+static struct st_test_file* file_stack_end;
+
static CHARSET_INFO *charset_info= &my_charset_latin1; /* Default charset */
-static const char *charset_name= "latin1"; /* Default character set name */
-static int embedded_server_arg_count=0;
-static char *embedded_server_args[MAX_SERVER_ARGS];
+static const char *embedded_server_groups[]=
+{
+ "server",
+ "embedded",
+ "mysqltest_SERVER",
+ NullS
+};
-static my_bool display_result_vertically= FALSE, display_metadata= FALSE;
+static int embedded_server_arg_count=0;
+static char *embedded_server_args[MAX_EMBEDDED_SERVER_ARGS];
-/* See the timer_output() definition for details */
+/*
+ Timer related variables
+ See the timer_output() definition for details
+*/
static char *timer_file = NULL;
static ulonglong timer_start;
-static int got_end_timer= FALSE;
static void timer_output(void);
static ulonglong timer_now(void);
+static ulonglong progress_start= 0;
+
/* Precompiled re's */
static my_regex_t ps_re; /* the query can be run using PS protocol */
static my_regex_t sp_re; /* the query can be run as a SP */
@@ -219,50 +178,25 @@ static void init_re(void);
static int match_re(my_regex_t *, char *);
static void free_re(void);
-static const char *embedded_server_groups[]=
-{
- "server",
- "embedded",
- "mysqltest_SERVER",
- NullS
-};
-
DYNAMIC_ARRAY q_lines;
#include "sslopt-vars.h"
-typedef struct
-{
- char file[FN_REFLEN];
- ulong pos;
-} MASTER_POS ;
-
-struct connection
+struct
{
- MYSQL mysql;
- /* Used when creating views and sp, to avoid implicit commit */
- MYSQL* util_mysql;
- char *name;
- MYSQL_STMT* stmt;
-
- const char *cur_query;
- int cur_query_len;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- int query_done;
-};
+ int read_lines,current_line;
+} parser;
-typedef struct
+struct
{
- int read_lines,current_line;
-} PARSER;
+ char file[FN_REFLEN];
+ ulong pos;
+} master_pos;
-PARSER parser;
-MASTER_POS master_pos;
/* if set, all results are concated and compared against this file */
-const char *result_file = 0;
+const char *result_file_name= 0;
-typedef struct
+typedef struct st_var
{
char *name;
int name_len;
@@ -272,73 +206,79 @@ typedef struct
int alloced_len;
int int_dirty; /* do not update string if int is updated until first read */
int alloced;
+ char *env_s;
} VAR;
-VAR var_reg[10];
/*Perl/shell-like variable registers */
+VAR var_reg[10];
+
HASH var_hash;
-my_bool disable_query_log=0, disable_result_log=0, disable_warnings=0;
-my_bool disable_ps_warnings= 0;
-my_bool disable_info= 1; /* By default off */
-my_bool abort_on_error= 1;
-struct connection cons[MAX_CONS];
-struct connection* cur_con, *next_con, *cons_end;
+struct st_connection
+{
+ MYSQL mysql;
+ /* Used when creating views and sp, to avoid implicit commit */
+ MYSQL* util_mysql;
+ char *name;
+ MYSQL_STMT* stmt;
- /* Add new commands before Q_UNKNOWN !*/
+#ifdef EMBEDDED_LIBRARY
+ const char *cur_query;
+ int cur_query_len;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int query_done;
+#endif /*EMBEDDED_LIBRARY*/
+};
+struct st_connection connections[128];
+struct st_connection* cur_con, *next_con, *connections_end;
+/*
+ List of commands in mysqltest
+ Must match the "command_names" array
+ Add new commands before Q_UNKNOWN!
+*/
enum enum_commands {
-Q_CONNECTION=1, Q_QUERY,
-Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
-Q_INC, Q_DEC,
-Q_SOURCE, Q_DISCONNECT,
-Q_LET, Q_ECHO,
-Q_WHILE, Q_END_BLOCK,
-Q_SYSTEM, Q_RESULT,
-Q_REQUIRE, Q_SAVE_MASTER_POS,
-Q_SYNC_WITH_MASTER,
-Q_SYNC_SLAVE_WITH_MASTER,
-Q_ERROR,
-Q_SEND, Q_REAP,
-Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
-Q_PING, Q_EVAL,
-Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
-Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
-Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
-Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
-Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
-Q_WAIT_FOR_SLAVE_TO_STOP,
-Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
-Q_ENABLE_PS_WARNINGS, Q_DISABLE_PS_WARNINGS,
-Q_ENABLE_INFO, Q_DISABLE_INFO,
-Q_ENABLE_METADATA, Q_DISABLE_METADATA,
-Q_EXEC, Q_DELIMITER,
-Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
-Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
-Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
-Q_START_TIMER, Q_END_TIMER,
-Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
-Q_EXIT,
-Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
-Q_IF,
-Q_DISABLE_PARSING, Q_ENABLE_PARSING,
-
-Q_UNKNOWN, /* Unknown command. */
-Q_COMMENT, /* Comments, ignored. */
-Q_COMMENT_WITH_COMMAND
+ Q_CONNECTION=1, Q_QUERY,
+ Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP,
+ Q_INC, Q_DEC,
+ Q_SOURCE, Q_DISCONNECT,
+ Q_LET, Q_ECHO,
+ Q_WHILE, Q_END_BLOCK,
+ Q_SYSTEM, Q_RESULT,
+ Q_REQUIRE, Q_SAVE_MASTER_POS,
+ Q_SYNC_WITH_MASTER,
+ Q_SYNC_SLAVE_WITH_MASTER,
+ Q_ERROR,
+ Q_SEND, Q_REAP,
+ Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN,
+ Q_PING, Q_EVAL,
+ Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
+ Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
+ Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
+ Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
+ Q_WAIT_FOR_SLAVE_TO_STOP,
+ Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
+ Q_ENABLE_PS_WARNINGS, Q_DISABLE_PS_WARNINGS,
+ Q_ENABLE_INFO, Q_DISABLE_INFO,
+ Q_ENABLE_METADATA, Q_DISABLE_METADATA,
+ Q_EXEC, Q_DELIMITER,
+ Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
+ Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
+ Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
+ Q_START_TIMER, Q_END_TIMER,
+ Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
+ Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
+ Q_IF,
+ Q_DISABLE_PARSING, Q_ENABLE_PARSING,
+ Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST,
+ Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT,
+
+ Q_UNKNOWN, /* Unknown command. */
+ Q_COMMENT, /* Comments, ignored. */
+ Q_COMMENT_WITH_COMMAND
};
-/* this should really be called command */
-struct st_query
-{
- char *query, *query_buf,*first_argument,*last_argument,*end;
- int first_word_len;
- my_bool abort_on_error, require_file;
- match_err expected_errno[MAX_EXPECTED_ERRORS];
- uint expected_errors;
- char record_file[FN_REFLEN];
- enum enum_commands type;
-};
const char *command_names[]=
{
@@ -379,9 +319,6 @@ const char *command_names[]=
/* Enable/disable that the _result_ from a query is logged to result file */
"enable_result_log",
"disable_result_log",
- "server_start",
- "server_stop",
- "require_manager",
"wait_for_slave_to_stop",
"enable_warnings",
"disable_warnings",
@@ -404,73 +341,124 @@ const char *command_names[]=
"character_set",
"disable_ps_protocol",
"enable_ps_protocol",
- "exit",
"disable_reconnect",
"enable_reconnect",
"if",
"disable_parsing",
"enable_parsing",
+ "replace_regex",
+ "remove_file",
+ "file_exists",
+ "write_file",
+ "copy_file",
+ "perl",
+ "die",
+ /* Don't execute any more commands, compare result */
+ "exit",
0
};
-TYPELIB command_typelib= {array_elements(command_names),"",
- command_names, 0};
-DYNAMIC_STRING ds_res;
-static void die(const char *fmt, ...);
-static void init_var_hash();
-static VAR* var_from_env(const char *, const char *);
-static byte* get_var_key(const byte* rec, uint* len, my_bool t);
-static VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
- int val_len);
-
-static void var_free(void* v);
+/*
+ The list of error codes to --error are stored in an internal array of
+ structs. This struct can hold numeric SQL error codes, error names or
+ SQLSTATE codes as strings. The element next to the last active element
+ in the list is set to type ERR_EMPTY. When an SQL statement returns an
+ error, we use this list to check if this is an expected error.
+*/
+enum match_err_type
+{
+ ERR_EMPTY= 0,
+ ERR_ERRNO,
+ ERR_SQLSTATE
+};
-void dump_result_to_reject_file(const char *record_file, char *buf, int size);
-void dump_result_to_log_file(const char *record_file, char *buf, int size);
+struct st_match_err
+{
+ enum match_err_type type;
+ union
+ {
+ uint errnum;
+ char sqlstate[SQLSTATE_LENGTH+1]; /* \0 terminated string */
+ } code;
+};
-int close_connection(struct st_query*);
-static void set_charset(struct st_query*);
-VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
- my_bool ignore_not_existing);
-int eval_expr(VAR* v, const char *p, const char** p_end);
-static int read_server_arguments(const char *name);
+struct st_expected_errors
+{
+ struct st_match_err err[10];
+ uint count;
+};
+static struct st_expected_errors saved_expected_errors;
-/* Definitions for replace result */
+struct st_command
+{
+ char *query, *query_buf,*first_argument,*last_argument,*end;
+ int first_word_len, query_len;
+ my_bool abort_on_error;
+ struct st_expected_errors expected_errors;
+ char require_file[FN_REFLEN];
+ enum enum_commands type;
+};
-typedef struct st_pointer_array { /* when using array-strings */
- TYPELIB typelib; /* Pointer to strings */
- byte *str; /* Strings is here */
- int7 *flag; /* Flag about each var. */
- uint array_allocs,max_count,length,max_length;
-} POINTER_ARRAY;
+TYPELIB command_typelib= {array_elements(command_names),"",
+ command_names, 0};
-struct st_replace;
-struct st_replace *init_replace(my_string *from, my_string *to, uint count,
- my_string word_end_chars);
-void free_replace();
-static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
-static void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
- const char *from, int len);
-void free_pointer_array(POINTER_ARRAY *pa);
-static void do_eval(DYNAMIC_STRING *query_eval, const char *query,
- my_bool pass_through_escape_chars);
-static void str_to_file(const char *fname, char *str, int size);
+DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
+
+void die(const char *fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 1, 2);
+void abort_not_supported_test(const char *fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 1, 2);
+void verbose_msg(const char *fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 1, 2);
+void warning_msg(const char *fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 1, 2);
+
+VAR* var_from_env(const char *, const char *);
+VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
+ int val_len);
+void var_free(void* v);
+VAR* var_get(const char *var_name, const char** var_name_end,
+ my_bool raw, my_bool ignore_not_existing);
+void eval_expr(VAR* v, const char *p, const char** p_end);
+my_bool match_delimiter(int c, const char *delim, uint length);
+void dump_result_to_reject_file(char *buf, int size);
+void dump_result_to_log_file(char *buf, int size);
+void dump_warning_messages();
+void dump_progress();
+
+void do_eval(DYNAMIC_STRING *query_eval, const char *query,
+ const char *query_end, my_bool pass_through_escape_chars);
+void str_to_file(const char *fname, char *str, int size);
#ifdef __WIN__
-static void free_tmp_sh_file();
-static void free_win_path_patterns();
+void free_tmp_sh_file();
+void free_win_path_patterns();
#endif
-struct st_replace *glob_replace;
static int eval_result = 0;
-/* For column replace */
-char *replace_column[MAX_COLUMNS];
-uint max_replace_column= 0;
+/* For replace_column */
+static char *replace_column[MAX_COLUMNS];
+static uint max_replace_column= 0;
+void do_get_replace_column(struct st_command*);
+void free_replace_column();
+
+/* For replace */
+void do_get_replace(struct st_command *command);
+void free_replace();
+
+/* For replace_regex */
+void do_get_replace_regex(struct st_command *command);
+void free_replace_regex();
+
+
+void free_all_replace(){
+ free_replace();
+ free_replace_regex();
+ free_replace_column();
+}
-static void get_replace_column(struct st_query *q);
-static void free_replace_column();
/* Disable functions that only exist in MySQL 4.0 */
#if MYSQL_VERSION_ID < 40000
@@ -479,14 +467,15 @@ void mysql_disable_rpl_parse(MYSQL* mysql __attribute__((unused))) {}
int mysql_rpl_parse_enabled(MYSQL* mysql __attribute__((unused))) { return 1; }
my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
-static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
- int len);
-static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
-static void handle_error(const char *query, struct st_query *q,
- unsigned int err_errno, const char *err_error,
- const char *err_sqlstate, DYNAMIC_STRING *ds);
-static void handle_no_error(struct st_query *q);
+void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
+ int len);
+void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
+void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val);
+void handle_error(struct st_command*,
+ unsigned int err_errno, const char *err_error,
+ const char *err_sqlstate, DYNAMIC_STRING *ds);
+void handle_no_error(struct st_command*);
#ifdef EMBEDDED_LIBRARY
/*
@@ -498,7 +487,7 @@ static void handle_no_error(struct st_query *q);
*/
pthread_handler_t send_one_query(void *arg)
{
- struct connection *cn= (struct connection*)arg;
+ struct st_connection *cn= (struct st_connection*)arg;
mysql_thread_init();
VOID(mysql_send_query(&cn->mysql, cn->cur_query, cn->cur_query_len));
@@ -512,12 +501,12 @@ pthread_handler_t send_one_query(void *arg)
return 0;
}
-static int do_send_query(struct connection *cn, const char *q, int q_len,
+static int do_send_query(struct st_connection *cn, const char *q, int q_len,
int flags)
{
pthread_t tid;
- if (flags & QUERY_REAP)
+ if (flags & QUERY_REAP_FLAG)
return mysql_send_query(&cn->mysql, q, q_len);
if (pthread_mutex_init(&cn->mutex, NULL) ||
@@ -539,27 +528,27 @@ static int do_send_query(struct connection *cn, const char *q, int q_len,
#endif /*EMBEDDED_LIBRARY*/
-static void do_eval(DYNAMIC_STRING* query_eval, const char *query,
- my_bool pass_through_escape_chars)
+void do_eval(DYNAMIC_STRING *query_eval, const char *query,
+ const char *query_end, my_bool pass_through_escape_chars)
{
const char *p;
register char c, next_c;
register int escaped = 0;
- VAR* v;
+ VAR *v;
DBUG_ENTER("do_eval");
- for (p= query; (c = *p); ++p)
+ for (p= query; (c= *p) && p < query_end; ++p)
{
switch(c) {
case '$':
if (escaped)
{
- escaped = 0;
+ escaped= 0;
dynstr_append_mem(query_eval, p, 1);
}
else
{
- if (!(v = var_get(p, &p, 0, 0)))
+ if (!(v= var_get(p, &p, 0, 0)))
die("Bad variable in eval");
dynstr_append_mem(query_eval, v->str_val, v->str_val_len);
}
@@ -568,13 +557,13 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char *query,
next_c= *(p+1);
if (escaped)
{
- escaped = 0;
+ escaped= 0;
dynstr_append_mem(query_eval, p, 1);
}
- else if (next_c == '\\' || next_c == '$')
+ else if (next_c == '\\' || next_c == '$' || next_c == '"')
{
- /* Set escaped only if next char is \ or $ */
- escaped = 1;
+ /* Set escaped only if next char is \, " or $ */
+ escaped= 1;
if (pass_through_escape_chars)
{
@@ -594,10 +583,131 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char *query,
}
-static void close_cons()
+enum arg_type
{
- DBUG_ENTER("close_cons");
- for (--next_con; next_con >= cons; --next_con)
+ ARG_STRING,
+ ARG_REST
+};
+
+struct command_arg {
+ const char *argname; /* Name of argument */
+ enum arg_type type; /* Type of argument */
+ my_bool required; /* Argument required */
+ DYNAMIC_STRING *ds; /* Storage for argument */
+ const char *description; /* Description of the argument */
+};
+
+
+void check_command_args(struct st_command *command,
+ const char *arguments,
+ const struct command_arg *args,
+ int num_args, const char delimiter_arg)
+{
+ int i;
+ const char *ptr= arguments;
+ const char *start;
+
+ DBUG_ENTER("check_command_args");
+ DBUG_PRINT("enter", ("num_args: %d", num_args));
+ for (i= 0; i < num_args; i++)
+ {
+ const struct command_arg *arg= &args[i];
+
+ switch (arg->type)
+ {
+ /* A string */
+ case ARG_STRING:
+ /* Skip leading spaces */
+ while (*ptr && *ptr == ' ')
+ ptr++;
+ start= ptr;
+ /* Find end of arg, terminated by "delimiter_arg" */
+ while (*ptr && *ptr != delimiter_arg)
+ ptr++;
+ if (ptr > start)
+ {
+ init_dynamic_string(arg->ds, 0, ptr-start, 32);
+ do_eval(arg->ds, start, ptr, FALSE);
+ }
+ else
+ {
+ /* Empty string */
+ init_dynamic_string(arg->ds, "", 0, 0);
+ }
+ command->last_argument= (char*)ptr;
+
+ /* Step past the delimiter */
+ if (*ptr && *ptr == delimiter_arg)
+ ptr++;
+ DBUG_PRINT("info", ("val: %s", arg->ds->str));
+ break;
+
+ /* Rest of line */
+ case ARG_REST:
+ start= ptr;
+ init_dynamic_string(arg->ds, 0, command->query_len, 256);
+ do_eval(arg->ds, start, command->end, FALSE);
+ command->last_argument= command->end;
+ DBUG_PRINT("info", ("val: %s", arg->ds->str));
+ break;
+
+ default:
+ DBUG_ASSERT("Unknown argument type");
+ break;
+ }
+
+ /* Check required arg */
+ if (arg->ds->length == 0 && arg->required)
+ die("Missing required argument '%s' to command '%.*s'", arg->argname,
+ command->first_word_len, command->query);
+
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void handle_command_error(struct st_command *command, uint error)
+{
+ DBUG_ENTER("handle_command_error");
+ DBUG_PRINT("enter", ("error: %d", error));
+ if (error != 0)
+ {
+ uint i;
+
+ if (command->abort_on_error)
+ die("command \"%.*s\" failed with error %d",
+ command->first_word_len, command->query, error);
+ for (i= 0; i < command->expected_errors.count; i++)
+ {
+ DBUG_PRINT("info", ("expected error: %d",
+ command->expected_errors.err[i].code.errnum));
+ if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
+ (command->expected_errors.err[i].code.errnum == error))
+ {
+ DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d",
+ command->first_word_len, command->query, error));
+ DBUG_VOID_RETURN;
+ }
+ }
+ die("command \"%.*s\" failed with wrong error: %d",
+ command->first_word_len, command->query, error);
+ }
+ else if (command->expected_errors.err[0].type == ERR_ERRNO &&
+ command->expected_errors.err[0].code.errnum != 0)
+ {
+ /* Error code we wanted was != 0, i.e. not an expected success */
+ die("command \"%.*s\" succeeded - should have failed with errno %d...",
+ command->first_word_len, command->query,
+ command->expected_errors.err[0].code.errnum);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void close_connections()
+{
+ DBUG_ENTER("close_connections");
+ for (--next_con; next_con >= connections; --next_con)
{
if (next_con->stmt)
mysql_stmt_close(next_con->stmt);
@@ -611,14 +721,16 @@ static void close_cons()
}
-static void close_files()
+void close_files()
{
DBUG_ENTER("close_files");
for (; cur_file >= file_stack; cur_file--)
{
- DBUG_PRINT("info", ("file_name: %s", cur_file->file_name));
if (cur_file->file && cur_file->file != stdin)
+ {
+ DBUG_PRINT("info", ("closing file: %s", cur_file->file_name));
my_fclose(cur_file->file, MYF(0));
+ }
my_free((gptr)cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR));
cur_file->file_name= 0;
}
@@ -626,25 +738,22 @@ static void close_files()
}
-static void free_used_memory()
+void free_used_memory()
{
uint i;
DBUG_ENTER("free_used_memory");
-#ifndef EMBEDDED_LIBRARY
- if (manager)
- mysql_manager_close(manager);
-#endif
- close_cons();
+
+ close_connections();
close_files();
hash_free(&var_hash);
- for (i=0 ; i < q_lines.elements ; i++)
+ for (i= 0 ; i < q_lines.elements ; i++)
{
- struct st_query **q= dynamic_element(&q_lines, i, struct st_query**);
+ struct st_command **q= dynamic_element(&q_lines, i, struct st_command**);
my_free((gptr) (*q)->query_buf,MYF(MY_ALLOW_ZERO_PTR));
my_free((gptr) (*q),MYF(0));
}
- for (i=0; i < 10; i++)
+ for (i= 0; i < 10; i++)
{
if (var_reg[i].alloced_len)
my_free(var_reg[i].str_val, MYF(MY_WME));
@@ -653,8 +762,9 @@ static void free_used_memory()
my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
delete_dynamic(&q_lines);
dynstr_free(&ds_res);
- free_replace();
- free_replace_column();
+ dynstr_free(&ds_progress);
+ dynstr_free(&ds_warning_messages);
+ free_all_replace();
my_free(pass,MYF(MY_ALLOW_ZERO_PTR));
free_defaults(default_argv);
mysql_server_end();
@@ -666,10 +776,12 @@ static void free_used_memory()
DBUG_VOID_RETURN;
}
-static void die(const char *fmt, ...)
+
+void die(const char *fmt, ...)
{
va_list args;
DBUG_ENTER("die");
+ DBUG_PRINT("enter", ("start_lineno: %d", start_lineno));
/* Print the error message */
va_start(args, fmt);
@@ -688,8 +800,12 @@ static void die(const char *fmt, ...)
va_end(args);
/* Dump the result that has been accumulated so far to .log file */
- if (result_file && ds_res.length)
- dump_result_to_log_file(result_file, ds_res.str, ds_res.length);
+ if (result_file_name && ds_res.length)
+ dump_result_to_log_file(ds_res.str, ds_res.length);
+
+ /* Dump warning messages */
+ if (result_file_name && ds_warning_messages.length)
+ dump_warning_messages();
/* Clean up and exit */
free_used_memory();
@@ -701,20 +817,54 @@ static void die(const char *fmt, ...)
exit(1);
}
-/* Note that we will get some memory leaks when calling this! */
-static void abort_not_supported_test()
+void abort_not_supported_test(const char *fmt, ...)
{
+ va_list args;
+ struct st_test_file* err_file= cur_file;
DBUG_ENTER("abort_not_supported_test");
- fprintf(stderr, "This test is not supported by this installation\n");
- if (!silent)
- printf("skipped\n");
+
+ /* Print include filestack */
+ fprintf(stderr, "The test '%s' is not supported by this installation\n",
+ file_stack->file_name);
+ fprintf(stderr, "Detected in file %s at line %d\n",
+ err_file->file_name, err_file->lineno);
+ while (err_file != file_stack)
+ {
+ err_file--;
+ fprintf(stderr, "included from %s at line %d\n",
+ err_file->file_name, err_file->lineno);
+ }
+
+ /* Print error message */
+ va_start(args, fmt);
+ if (fmt)
+ {
+ fprintf(stderr, "reason: ");
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ va_end(args);
+
+ /* Clean up and exit */
free_used_memory();
my_end(MY_CHECK_ERROR);
+
+ if (!silent)
+ printf("skipped\n");
+
exit(62);
}
-static void verbose_msg(const char *fmt, ...)
+
+void abort_not_in_this_version()
+{
+ die("Not available in this version of mysqltest");
+}
+
+
+void verbose_msg(const char *fmt, ...)
{
va_list args;
DBUG_ENTER("verbose_msg");
@@ -722,25 +872,60 @@ static void verbose_msg(const char *fmt, ...)
DBUG_VOID_RETURN;
va_start(args, fmt);
-
fprintf(stderr, "mysqltest: ");
+ if (cur_file && cur_file != file_stack)
+ fprintf(stderr, "In included file \"%s\": ",
+ cur_file->file_name);
if (start_lineno != 0)
fprintf(stderr, "At line %u: ", start_lineno);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
+
DBUG_VOID_RETURN;
}
-void init_parser()
+void warning_msg(const char *fmt, ...)
{
- parser.current_line= parser.read_lines= 0;
- memset(&var_reg, 0, sizeof(var_reg));
+ va_list args;
+ char buff[512];
+ size_t len;
+ DBUG_ENTER("warning_msg");
+
+ va_start(args, fmt);
+ dynstr_append(&ds_warning_messages, "mysqltest: ");
+ if (start_lineno != 0)
+ {
+ dynstr_append(&ds_warning_messages, "Warning detected ");
+ if (cur_file && cur_file != file_stack)
+ {
+ len= my_snprintf(buff, sizeof(buff), "in included file %s ",
+ cur_file->file_name);
+ dynstr_append_mem(&ds_warning_messages,
+ buff, len);
+ }
+ len= my_snprintf(buff, sizeof(buff), "at line %d: ",
+ start_lineno);
+ dynstr_append_mem(&ds_warning_messages,
+ buff, len);
+ }
+#ifndef __WIN__
+ len= vsnprintf(buff, sizeof(buff), fmt, args);
+ dynstr_append_mem(&ds_warning_messages, buff, len);
+#endif
+ dynstr_append(&ds_warning_messages, "\n");
+ va_end(args);
+
+ DBUG_VOID_RETURN;
}
-static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
+/*
+ Compare content of the string ds to content of file fname
+*/
+
+int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
{
MY_STAT stat_info;
char *tmp, *res_ptr;
@@ -754,34 +939,35 @@ static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
if (!test_if_hard_path(fname))
{
strxmov(eval_file, opt_basedir, fname, NullS);
- fn_format(eval_file, eval_file,"","",4);
+ fn_format(eval_file, eval_file, "", "", MY_UNPACK_FILENAME);
}
else
- fn_format(eval_file, fname,"","",4);
+ fn_format(eval_file, fname, "", "", MY_UNPACK_FILENAME);
if (!my_stat(eval_file, &stat_info, MYF(MY_WME)))
die(NullS);
if (!eval_result && (uint) stat_info.st_size != ds->length)
{
- DBUG_PRINT("info",("Size differs: result size: %u file size: %u",
- ds->length, stat_info.st_size));
+ DBUG_PRINT("info",("Size differs: result size: %u file size: %lu",
+ ds->length, (ulong) stat_info.st_size));
DBUG_PRINT("info",("result: '%s'", ds->str));
DBUG_RETURN(RESULT_LENGTH_MISMATCH);
}
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
- die(NullS);
+ die("Out of memory");
if ((fd = my_open(eval_file, O_RDONLY, MYF(MY_WME))) < 0)
- die(NullS);
+ die("Failed to open file %s", eval_file);
if (my_read(fd, (byte*)tmp, stat_info.st_size, MYF(MY_WME|MY_NABP)))
- die(NullS);
+ die("Failed to read from file %s, errno: %d", eval_file, errno);
tmp[stat_info.st_size] = 0;
- init_dynamic_string(&res_ds, "", 0, 65536);
+ init_dynamic_string(&res_ds, "", stat_info.st_size+256, 256);
if (eval_result)
{
- do_eval(&res_ds, tmp, FALSE);
- res_ptr = res_ds.str;
- if ((res_len = res_ds.length) != ds->length)
+ do_eval(&res_ds, tmp, tmp + stat_info.st_size, FALSE);
+ res_ptr= res_ds.str;
+ res_len= res_ds.length;
+ if (res_len != ds->length)
{
res= RESULT_LENGTH_MISMATCH;
goto err;
@@ -798,47 +984,45 @@ static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
err:
if (res && eval_result)
- str_to_file(fn_format(eval_file, fname, "", ".eval",2), res_ptr,
- res_len);
+ str_to_file(fn_format(eval_file, fname, "", ".eval",
+ MY_REPLACE_EXT),
+ res_ptr, res_len);
+ dynstr_free(&res_ds);
my_free((gptr) tmp, MYF(0));
my_close(fd, MYF(MY_WME));
- dynstr_free(&res_ds);
DBUG_RETURN(res);
}
+
/*
- Check the content of ds against content of file fname
+ Check the content of ds against result file
SYNOPSIS
check_result
ds - content to be checked
- fname - name of file to check against
- require_option - if set and check fails, the test will be aborted
- with the special exit code "not supported test"
RETURN VALUES
- error - the function will not return
+ error - the function will not return
*/
-static void check_result(DYNAMIC_STRING* ds, const char *fname,
- my_bool require_option)
+
+void check_result(DYNAMIC_STRING* ds)
{
- int res= dyn_string_cmp(ds, fname);
DBUG_ENTER("check_result");
+ DBUG_ASSERT(result_file_name);
- if (res && require_option)
- abort_not_supported_test();
- switch (res) {
+ switch (dyn_string_cmp(ds, result_file_name))
+ {
case RESULT_OK:
break; /* ok */
case RESULT_LENGTH_MISMATCH:
- dump_result_to_reject_file(fname, ds->str, ds->length);
+ dump_result_to_reject_file(ds->str, ds->length);
die("Result length mismatch");
break;
case RESULT_CONTENT_MISMATCH:
- dump_result_to_reject_file(fname, ds->str, ds->length);
+ dump_result_to_reject_file(ds->str, ds->length);
die("Result content mismatch");
break;
default: /* impossible */
@@ -849,13 +1033,109 @@ static void check_result(DYNAMIC_STRING* ds, const char *fname,
}
-VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
+/*
+ Check the content of ds against a require file
+ If match fails, abort the test with special error code
+ indicating that test is not supported
+
+ SYNOPSIS
+ check_result
+ ds - content to be checked
+ fname - name of file to check against
+
+ RETURN VALUES
+ error - the function will not return
+
+*/
+
+void check_require(DYNAMIC_STRING* ds, const char *fname)
+{
+ DBUG_ENTER("check_require");
+
+ if (dyn_string_cmp(ds, fname))
+ {
+ char reason[FN_REFLEN];
+ fn_format(reason, fname, "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
+ abort_not_supported_test("Test requires: '%s'", reason);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static byte *get_var_key(const byte* var, uint* len,
+ my_bool __attribute__((unused)) t)
+{
+ register char* key;
+ key = ((VAR*)var)->name;
+ *len = ((VAR*)var)->name_len;
+ return (byte*)key;
+}
+
+
+VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
+ int val_len)
+{
+ int val_alloc_len;
+ VAR *tmp_var;
+ if (!name_len && name)
+ name_len = strlen(name);
+ if (!val_len && val)
+ val_len = strlen(val) ;
+ val_alloc_len = val_len + 16; /* room to grow */
+ if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
+ + name_len+1, MYF(MY_WME))))
+ die("Out of memory");
+
+ tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
+ tmp_var->alloced = (v == 0);
+
+ if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME))))
+ die("Out of memory");
+
+ memcpy(tmp_var->name, name, name_len);
+ if (val)
+ {
+ memcpy(tmp_var->str_val, val, val_len);
+ tmp_var->str_val[val_len]= 0;
+ }
+ tmp_var->name_len = name_len;
+ tmp_var->str_val_len = val_len;
+ tmp_var->alloced_len = val_alloc_len;
+ tmp_var->int_val = (val) ? atoi(val) : 0;
+ tmp_var->int_dirty = 0;
+ tmp_var->env_s = 0;
+ return tmp_var;
+}
+
+
+void var_free(void *v)
+{
+ my_free(((VAR*) v)->str_val, MYF(MY_WME));
+ if (((VAR*)v)->alloced)
+ my_free((char*) v, MYF(MY_WME));
+}
+
+
+VAR* var_from_env(const char *name, const char *def_val)
+{
+ const char *tmp;
+ VAR *v;
+ if (!(tmp = getenv(name)))
+ tmp = def_val;
+
+ v = var_init(0, name, strlen(name), tmp, strlen(tmp));
+ my_hash_insert(&var_hash, (byte*)v);
+ return v;
+}
+
+
+VAR* var_get(const char *var_name, const char **var_name_end, my_bool raw,
my_bool ignore_not_existing)
{
int digit;
- VAR* v;
+ VAR *v;
DBUG_ENTER("var_get");
- DBUG_PRINT("enter",("var_name: %s",var_name));
+ DBUG_PRINT("enter", ("var_name: %s",var_name));
if (*var_name != '$')
goto err;
@@ -874,16 +1154,16 @@ VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw,
die("Empty variable");
}
length= (uint) (var_name - save_var_name);
- if (length >= MAX_VAR_NAME)
+ if (length >= MAX_VAR_NAME_LENGTH)
die("Too long variable name: %s", save_var_name);
if (!(v = (VAR*) hash_search(&var_hash, save_var_name, length)))
{
- char buff[MAX_VAR_NAME+1];
+ char buff[MAX_VAR_NAME_LENGTH+1];
strmake(buff, save_var_name, length);
v= var_from_env(buff, "");
}
- var_name--; /* Point at last character */
+ var_name--; /* Point at last character */
}
else
v = var_reg + digit;
@@ -904,7 +1184,8 @@ err:
DBUG_RETURN(0);
}
-static VAR *var_obtain(const char *name, int len)
+
+VAR *var_obtain(const char *name, int len)
{
VAR* v;
if ((v = (VAR*)hash_search(&var_hash, name, len)))
@@ -914,208 +1195,308 @@ static VAR *var_obtain(const char *name, int len)
return v;
}
-int var_set(const char *var_name, const char *var_name_end,
- const char *var_val, const char *var_val_end)
+
+/*
+ - if variable starts with a $ it is regarded as a local test varable
+ - if not it is treated as a environment variable, and the corresponding
+ environment variable will be updated
+*/
+
+void var_set(const char *var_name, const char *var_name_end,
+ const char *var_val, const char *var_val_end)
{
- int digit;
- VAR* v;
+ int digit, env_var= 0;
+ VAR *v;
DBUG_ENTER("var_set");
DBUG_PRINT("enter", ("var_name: '%.*s' = '%.*s' (length: %d)",
(int) (var_name_end - var_name), var_name,
(int) (var_val_end - var_val), var_val,
(int) (var_val_end - var_val)));
- if (*var_name++ != '$')
- {
- var_name--;
- die("Variable name in %s does not start with '$'", var_name);
- }
- digit = *var_name - '0';
+ if (*var_name != '$')
+ env_var= 1;
+ else
+ var_name++;
+
+ digit= *var_name - '0';
if (!(digit < 10 && digit >= 0))
{
- v = var_obtain(var_name, (uint) (var_name_end - var_name));
+ v= var_obtain(var_name, (uint) (var_name_end - var_name));
}
else
- v = var_reg + digit;
- DBUG_RETURN(eval_expr(v, var_val, (const char**)&var_val_end));
-}
+ v= var_reg + digit;
+ eval_expr(v, var_val, (const char**) &var_val_end);
-int open_file(const char *name)
-{
- char buff[FN_REFLEN];
- DBUG_ENTER("open_file");
- DBUG_PRINT("enter", ("name: %s", name));
- if (!test_if_hard_path(name))
+ if (env_var)
{
- strxmov(buff, opt_basedir, name, NullS);
- name=buff;
+ char buf[1024], *old_env_s= v->env_s;
+ if (v->int_dirty)
+ {
+ sprintf(v->str_val, "%d", v->int_val);
+ v->int_dirty= 0;
+ v->str_val_len= strlen(v->str_val);
+ }
+ strxmov(buf, v->name, "=", v->str_val, NullS);
+ if (!(v->env_s= my_strdup(buf, MYF(MY_WME))))
+ die("Out of memory");
+ putenv(v->env_s);
+ my_free((gptr)old_env_s, MYF(MY_ALLOW_ZERO_PTR));
}
- fn_format(buff,name,"","",4);
+ DBUG_VOID_RETURN;
+}
- if (cur_file == file_stack_end)
- die("Source directives are nesting too deep");
- cur_file++;
- if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
- {
- cur_file--;
- die("Could not open file %s", buff);
- }
- cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
- cur_file->lineno=1;
- DBUG_RETURN(0);
+/*
+ Store an integer (typically the returncode of the last SQL)
+ statement in the mysqltest builtin variable $mysql_errno, by
+ simulating of a user statement "let $mysql_errno= <integer>"
+*/
+
+void var_set_errno(int sql_errno)
+{
+ /* TODO MASV make easier */
+ const char *var_name= "$mysql_errno";
+ char var_val[21];
+ uint length= my_sprintf(var_val, (var_val, "%d", sql_errno));
+ var_set(var_name, var_name + 12, var_val, var_val + length);
+ return;
}
/*
- Check for unexpected "junk" after the end of query
- This is normally caused by missing delimiters
+ Set variable from the result of a query
+
+ SYNOPSIS
+ var_query_set()
+ var variable to set from query
+ query start of query string to execute
+ query_end end of the query string to execute
+
+
+ DESCRIPTION
+ let @<var_name> = `<query>`
+
+ Execute the query and assign the first row of result to var as
+ a tab separated strings
+
+ Also assign each column of the result set to
+ variable "$<var_name>_<column_name>"
+ Thus the tab separated output can be read from $<var_name> and
+ and each individual column can be read as $<var_name>_<col_name>
+
*/
-int check_eol_junk(const char *eol)
+void var_query_set(VAR *var, const char *query, const char** query_end)
{
- const char *p= eol;
- DBUG_ENTER("check_eol_junk");
- DBUG_PRINT("enter", ("eol: %s", eol));
- /* Remove all spacing chars except new line */
- while (*p && my_isspace(charset_info, *p) && (*p != '\n'))
- p++;
+ char* end = (char*)((query_end && *query_end) ?
+ *query_end : query + strlen(query));
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ MYSQL* mysql = &cur_con->mysql;
+ DBUG_ENTER("var_query_set");
+ LINT_INIT(res);
- /* Check for extra delimiter */
- if (*p && !strncmp(p, delimiter, delimiter_length))
- die("Extra delimiter \"%s\" found", delimiter);
+ while (end > query && *end != '`')
+ --end;
+ if (query == end)
+ die("Syntax error in query, missing '`'");
+ ++query;
- /* Allow trailing # comment */
- if (*p && *p != '#')
+ if (mysql_real_query(mysql, query, (int)(end - query)) ||
+ !(res = mysql_store_result(mysql)))
{
- if (*p == '\n')
- die("Missing delimiter");
- die("End of line junk detected: \"%s\"", p);
+ *end = 0;
+ die("Error running query '%s': %d %s", query,
+ mysql_errno(mysql), mysql_error(mysql));
}
- DBUG_RETURN(0);
-}
-
-/* ugly long name, but we are following the convention */
-int do_wait_for_slave_to_stop(struct st_query *q __attribute__((unused)))
-{
- MYSQL* mysql = &cur_con->mysql;
- for (;;)
+ if ((row = mysql_fetch_row(res)) && row[0])
{
- MYSQL_RES *res;
- MYSQL_ROW row;
- int done;
- LINT_INIT(res);
+ /*
+ Concatenate all row results with tab in between to allow us to work
+ with results from many columns (for example from SHOW VARIABLES)
+ */
+ DYNAMIC_STRING result;
+ uint i;
+ ulong *lengths;
+ char *end;
+#ifdef NOT_YET
+ MYSQL_FIELD *fields= mysql_fetch_fields(res);
+#endif
- if (mysql_query(mysql,"show status like 'Slave_running'") ||
- !(res=mysql_store_result(mysql)))
- die("Query failed while probing slave for stop: %s",
- mysql_error(mysql));
- if (!(row=mysql_fetch_row(res)) || !row[1])
+ init_dynamic_string(&result, "", 2048, 2048);
+ lengths= mysql_fetch_lengths(res);
+ for (i=0; i < mysql_num_fields(res); i++)
{
- mysql_free_result(res);
- die("Strange result from query while probing slave for stop");
+ if (row[0])
+ {
+#ifdef NOT_YET
+ /* Add to <var_name>_<col_name> */
+ uint j;
+ char var_col_name[MAX_VAR_NAME_LENGTH];
+ uint length= snprintf(var_col_name, MAX_VAR_NAME_LENGTH,
+ "$%s_%s", var->name, fields[i].name);
+ /* Convert characters not allowed in variable names to '_' */
+ for (j= 1; j < length; j++)
+ {
+ if (!my_isvar(charset_info,var_col_name[j]))
+ var_col_name[j]= '_';
+ }
+ var_set(var_col_name, var_col_name + length,
+ row[i], row[i] + lengths[i]);
+#endif
+ /* Add column to tab separated string */
+ dynstr_append_mem(&result, row[i], lengths[i]);
+ }
+ dynstr_append_mem(&result, "\t", 1);
}
- done = !strcmp(row[1],"OFF");
- mysql_free_result(res);
- if (done)
- break;
- my_sleep(SLAVE_POLL_INTERVAL);
+ end= result.str + result.length-1;
+ eval_expr(var, result.str, (const char**) &end);
+ dynstr_free(&result);
}
- return 0;
+ else
+ eval_expr(var, "", 0);
+
+ mysql_free_result(res);
+ DBUG_VOID_RETURN;
}
-int do_require_manager(struct st_query *query __attribute__((unused)) )
+
+void var_copy(VAR *dest, VAR *src)
{
- if (!manager)
- abort_not_supported_test();
- return 0;
+ dest->int_val= src->int_val;
+ dest->int_dirty= src->int_dirty;
+
+ /* Alloc/realloc data for str_val in dest */
+ if (dest->alloced_len < src->alloced_len &&
+ !(dest->str_val= dest->str_val
+ ? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
+ : my_malloc(src->alloced_len, MYF(MY_WME))))
+ die("Out of memory");
+ else
+ dest->alloced_len= src->alloced_len;
+
+ /* Copy str_val data to dest */
+ dest->str_val_len= src->str_val_len;
+ if (src->str_val_len)
+ memcpy(dest->str_val, src->str_val, src->str_val_len);
}
-#ifndef EMBEDDED_LIBRARY
-static int do_server_op(struct st_query *q, const char *op)
+
+void eval_expr(VAR *v, const char *p, const char **p_end)
{
- char *p= q->first_argument;
- char com_buf[256], *com_p;
- if (!manager)
+ static int MIN_VAR_ALLOC= 32; /* MASV why 32? */
+ VAR *vp;
+ if (*p == '$')
{
- die("Manager is not initialized, manager commands are not possible");
+ if ((vp= var_get(p, p_end, 0, 0)))
+ {
+ var_copy(v, vp);
+ return;
+ }
}
- com_p= strmov(com_buf,op);
- com_p= strmov(com_p,"_exec ");
- if (!*p)
- die("Missing server name in server_%s", op);
- while (*p && !my_isspace(charset_info, *p))
- *com_p++= *p++;
- *com_p++= ' ';
- com_p= int10_to_str(manager_wait_timeout, com_p, 10);
- *com_p++= '\n';
- *com_p= 0;
- if (mysql_manager_command(manager, com_buf, (int)(com_p-com_buf)))
- die("Error in command: %s(%d)", manager->last_error, manager->last_errno);
- while (!manager->eof)
- {
- if (mysql_manager_fetch_line(manager, com_buf, sizeof(com_buf)))
- die("Error fetching result line: %s(%d)", manager->last_error,
- manager->last_errno);
- }
-
- q->last_argument= p;
- return 0;
+ else if (*p == '`')
+ {
+ var_query_set(v, p, p_end);
+ }
+ else
+ {
+ int new_val_len = (p_end && *p_end) ?
+ (int) (*p_end - p) : (int) strlen(p);
+ if (new_val_len + 1 >= v->alloced_len)
+ {
+ v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
+ MIN_VAR_ALLOC : new_val_len + 1;
+ if (!(v->str_val =
+ v->str_val ? my_realloc(v->str_val, v->alloced_len+1,
+ MYF(MY_WME)) :
+ my_malloc(v->alloced_len+1, MYF(MY_WME))))
+ die("Out of memory");
+ }
+ v->str_val_len = new_val_len;
+ memcpy(v->str_val, p, new_val_len);
+ v->str_val[new_val_len] = 0;
+ v->int_val=atoi(p);
+ v->int_dirty=0;
+ }
+ return;
}
-int do_server_start(struct st_query *q)
-{
- return do_server_op(q, "start");
-}
-int do_server_stop(struct st_query *q)
+int open_file(const char *name)
{
- return do_server_op(q, "stop");
-}
+ char buff[FN_REFLEN];
+ DBUG_ENTER("open_file");
+ DBUG_PRINT("enter", ("name: %s", name));
+ if (!test_if_hard_path(name))
+ {
+ strxmov(buff, opt_basedir, name, NullS);
+ name=buff;
+ }
+ fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
-#endif
+ if (cur_file == file_stack_end)
+ die("Source directives are nesting too deep");
+ cur_file++;
+ if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
+ {
+ cur_file--;
+ die("Could not open file %s", buff);
+ }
+ cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
+ cur_file->lineno=1;
+ DBUG_RETURN(0);
+}
/*
Source and execute the given file
SYNOPSIS
- do_source()
- query called command
+ do_source()
+ query called command
DESCRIPTION
- source <file_name>
+ source <file_name>
- Open the file <file_name> and execute it
+ Open the file <file_name> and execute it
*/
-int do_source(struct st_query *query)
+void do_source(struct st_command *command)
{
- char *p= query->first_argument, *name;
- if (!*p)
- die("Missing file name in source");
- name= p;
- while (*p && !my_isspace(charset_info,*p))
- p++;
- if (*p)
- *p++= 0;
- query->last_argument= p;
+ static DYNAMIC_STRING ds_filename;
+ const struct command_arg source_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to source"
+ };
+ DBUG_ENTER("do_source");
+
+ check_command_args(command, command->first_argument, source_args,
+ sizeof(source_args)/sizeof(struct command_arg),
+ ' ');
+
/*
- If this file has already been sourced, don't source it again.
- It's already available in the q_lines cache.
+ If this file has already been sourced, don't source it again.
+ It's already available in the q_lines cache.
*/
if (parser.current_line < (parser.read_lines - 1))
- return 0;
- return open_file(name);
+ ; /* Do nothing */
+ else
+ {
+ DBUG_PRINT("info", ("sourcing file: %s", ds_filename.str));
+ open_file(ds_filename.str);
+ }
+
+ dynstr_free(&ds_filename);
+ return;
}
+
#ifdef __WIN__
-/* Variables used for temuprary sh files used for emulating Unix on Windows */
+/* Variables used for temporary sh files used for emulating Unix on Windows */
char tmp_sh_name[64], tmp_sh_cmd[70];
-static void init_tmp_sh_file()
+void init_tmp_sh_file()
{
/* Format a name for the tmp sh file that is unique for this process */
my_snprintf(tmp_sh_name, sizeof(tmp_sh_name), "tmp_%d.sh", getpid());
@@ -1123,13 +1504,15 @@ static void init_tmp_sh_file()
my_snprintf(tmp_sh_cmd, sizeof(tmp_sh_cmd), "sh %s", tmp_sh_name);
}
-static void free_tmp_sh_file()
+
+void free_tmp_sh_file()
{
my_delete(tmp_sh_name, MYF(0));
}
#endif
-FILE* my_popen(DYNAMIC_STRING* ds_cmd, const char* mode)
+
+FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
{
#ifdef __WIN__
/* Dump the command into a sh script file and execute with popen */
@@ -1145,49 +1528,49 @@ FILE* my_popen(DYNAMIC_STRING* ds_cmd, const char* mode)
Execute given command.
SYNOPSIS
- do_exec()
- query called command
+ do_exec()
+ query called command
DESCRIPTION
- exec <command>
+ exec <command>
- Execute the text between exec and end of line in a subprocess.
- The error code returned from the subprocess is checked against the
- expected error array, previously set with the --error command.
- It can thus be used to execute a command that shall fail.
+ Execute the text between exec and end of line in a subprocess.
+ The error code returned from the subprocess is checked against the
+ expected error array, previously set with the --error command.
+ It can thus be used to execute a command that shall fail.
NOTE
- Although mysqltest is executed from cygwin shell, the command will be
- executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
- system for those commands.
+ Although mysqltest is executed from cygwin shell, the command will be
+ executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
+ system for those commands.
*/
-static void do_exec(struct st_query *query)
+void do_exec(struct st_command *command)
{
int error;
char buf[1024];
FILE *res_file;
- char *cmd= query->first_argument;
+ char *cmd= command->first_argument;
DYNAMIC_STRING ds_cmd;
DBUG_ENTER("do_exec");
DBUG_PRINT("enter", ("cmd: '%s'", cmd));
+ /* Skip leading space */
while (*cmd && my_isspace(charset_info, *cmd))
cmd++;
if (!*cmd)
die("Missing argument in exec");
- query->last_argument= query->end;
+ command->last_argument= command->end;
- init_dynamic_string(&ds_cmd, 0, strlen(cmd)+256, 256);
+ init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
/* Eval the command, thus replacing all environment variables */
- do_eval(&ds_cmd, cmd, TRUE);
- cmd= ds_cmd.str;
+ do_eval(&ds_cmd, cmd, command->end, TRUE);
DBUG_PRINT("info", ("Executing '%s' as '%s'",
- query->first_argument, cmd));
+ command->first_argument, ds_cmd.str));
- if (!(res_file= my_popen(&ds_cmd, "r")) && query->abort_on_error)
- die("popen(\"%s\", \"r\") failed", query->first_argument);
+ if (!(res_file= my_popen(&ds_cmd, "r")) && command->abort_on_error)
+ die("popen(\"%s\", \"r\") failed", command->first_argument);
while (fgets(buf, sizeof(buf), res_file))
{
@@ -1202,231 +1585,75 @@ static void do_exec(struct st_query *query)
}
}
error= pclose(res_file);
- if (error != 0)
+ if (error > 0)
{
uint status= WEXITSTATUS(error), i;
my_bool ok= 0;
- if (query->abort_on_error)
- die("command \"%s\" failed", query->first_argument);
+ if (command->abort_on_error)
+ die("command \"%s\" failed", command->first_argument);
DBUG_PRINT("info",
("error: %d, status: %d", error, status));
- for (i= 0; i < query->expected_errors; i++)
+ for (i= 0; i < command->expected_errors.count; i++)
{
DBUG_PRINT("info", ("expected error: %d",
- query->expected_errno[i].code.errnum));
- if ((query->expected_errno[i].type == ERR_ERRNO) &&
- (query->expected_errno[i].code.errnum == status))
+ command->expected_errors.err[i].code.errnum));
+ if ((command->expected_errors.err[i].type == ERR_ERRNO) &&
+ (command->expected_errors.err[i].code.errnum == status))
{
ok= 1;
DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d",
- query->first_argument, status));
+ command->first_argument, status));
}
}
if (!ok)
die("command \"%s\" failed with wrong error: %d",
- query->first_argument, status);
+ command->first_argument, status);
}
- else if (query->expected_errno[0].type == ERR_ERRNO &&
- query->expected_errno[0].code.errnum != 0)
+ else if (command->expected_errors.err[0].type == ERR_ERRNO &&
+ command->expected_errors.err[0].code.errnum != 0)
{
/* Error code we wanted was != 0, i.e. not an expected success */
die("command \"%s\" succeeded - should have failed with errno %d...",
- query->first_argument, query->expected_errno[0].code.errnum);
+ command->first_argument, command->expected_errors.err[0].code.errnum);
}
- free_replace();
+ dynstr_free(&ds_cmd);
DBUG_VOID_RETURN;
}
-/*
- Set variable from the result of a query
-
- SYNOPSIS
- var_query_set()
- var variable to set from query
- query start of query string to execute
- query_end end of the query string to execute
-
-
- DESCRIPTION
- let @<var_name> = `<query>`
-
- Execute the query and assign the first row of result to var as
- a tab separated strings
-
- Also assign each column of the result set to
- variable "$<var_name>_<column_name>"
- Thus the tab separated output can be read from $<var_name> and
- and each individual column can be read as $<var_name>_<col_name>
-
-*/
-
-int var_query_set(VAR* var, const char *query, const char** query_end)
-{
- char* end = (char*)((query_end && *query_end) ?
- *query_end : query + strlen(query));
- MYSQL_RES *res;
- MYSQL_ROW row;
- MYSQL* mysql = &cur_con->mysql;
- LINT_INIT(res);
-
- while (end > query && *end != '`')
- --end;
- if (query == end)
- die("Syntax error in query, missing '`'");
- ++query;
-
- if (mysql_real_query(mysql, query, (int)(end - query)) ||
- !(res = mysql_store_result(mysql)))
- {
- *end = 0;
- die("Error running query '%s': %d: %s", query,
- mysql_errno(mysql) ,mysql_error(mysql));
- }
-
- if ((row = mysql_fetch_row(res)) && row[0])
- {
- /*
- Concatenate all row results with tab in between to allow us to work
- with results from many columns (for example from SHOW VARIABLES)
- */
- DYNAMIC_STRING result;
- uint i;
- ulong *lengths;
- char *end;
- MYSQL_FIELD *fields= mysql_fetch_fields(res);
-
- init_dynamic_string(&result, "", 16384, 65536);
- lengths= mysql_fetch_lengths(res);
- for (i=0; i < mysql_num_fields(res); i++)
- {
- if (row[0])
- {
-#ifdef NOT_YET
- /* Add to <var_name>_<col_name> */
- uint j;
- char var_col_name[MAX_VAR_NAME];
- uint length= snprintf(var_col_name, MAX_VAR_NAME,
- "$%s_%s", var->name, fields[i].name);
- /* Convert characters not allowed in variable names to '_' */
- for (j= 1; j < length; j++)
- {
- if (!my_isvar(charset_info,var_col_name[j]))
- var_col_name[j]= '_';
- }
- var_set(var_col_name, var_col_name + length,
- row[i], row[i] + lengths[i]);
-#endif
- /* Add column to tab separated string */
- dynstr_append_mem(&result, row[i], lengths[i]);
- }
- dynstr_append_mem(&result, "\t", 1);
- }
- end= result.str + result.length-1;
- eval_expr(var, result.str, (const char**) &end);
- dynstr_free(&result);
- }
- else
- eval_expr(var, "", 0);
-
- mysql_free_result(res);
- return 0;
-}
-
-void var_copy(VAR *dest, VAR *src)
-{
- dest->int_val= src->int_val;
- dest->int_dirty= src->int_dirty;
-
- /* Alloc/realloc data for str_val in dest */
- if (dest->alloced_len < src->alloced_len &&
- !(dest->str_val= dest->str_val
- ? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME))
- : my_malloc(src->alloced_len, MYF(MY_WME))))
- die("Out of memory");
- else
- dest->alloced_len= src->alloced_len;
-
- /* Copy str_val data to dest */
- dest->str_val_len= src->str_val_len;
- if (src->str_val_len)
- memcpy(dest->str_val, src->str_val, src->str_val_len);
-}
-
-int eval_expr(VAR* v, const char *p, const char** p_end)
-{
- VAR* vp;
- if (*p == '$')
- {
- if ((vp = var_get(p,p_end,0,0)))
- {
- var_copy(v, vp);
- return 0;
- }
- }
- else if (*p == '`')
- {
- return var_query_set(v, p, p_end);
- }
- else
- {
- int new_val_len = (p_end && *p_end) ?
- (int) (*p_end - p) : (int) strlen(p);
- if (new_val_len + 1 >= v->alloced_len)
- {
- v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
- MIN_VAR_ALLOC : new_val_len + 1;
- if (!(v->str_val =
- v->str_val ? my_realloc(v->str_val, v->alloced_len+1,
- MYF(MY_WME)) :
- my_malloc(v->alloced_len+1, MYF(MY_WME))))
- die("Out of memory");
- }
- v->str_val_len = new_val_len;
- memcpy(v->str_val, p, new_val_len);
- v->str_val[new_val_len] = 0;
- v->int_val=atoi(p);
- v->int_dirty=0;
- return 0;
- }
-
- die("Invalid expr: %s", p);
- return 1;
-}
-
-
enum enum_operator
{
DO_DEC,
DO_INC
};
+
/*
Decrease or increase the value of a variable
SYNOPSIS
- do_modify_var()
- query called command
- operator operation to perform on the var
+ do_modify_var()
+ query called command
+ operator operation to perform on the var
DESCRIPTION
- dec $var_name
- inc $var_name
+ dec $var_name
+ inc $var_name
*/
-int do_modify_var(struct st_query *query,
+int do_modify_var(struct st_command *command,
enum enum_operator operator)
{
- const char *p= query->first_argument;
+ const char *p= command->first_argument;
VAR* v;
if (!*p)
- die("Missing argument to %.*s", query->first_word_len, query->query);
+ die("Missing argument to %.*s", command->first_word_len, command->query);
if (*p != '$')
die("The argument to %.*s must be a variable (start with $)",
- query->first_word_len, query->query);
+ command->first_word_len, command->query);
v= var_get(p, &p, 1, 0);
switch (operator) {
case DO_DEC:
@@ -1440,7 +1667,7 @@ int do_modify_var(struct st_query *query,
break;
}
v->int_dirty= 1;
- query->last_argument= (char*)++p;
+ command->last_argument= (char*)++p;
return 0;
}
@@ -1449,10 +1676,10 @@ int do_modify_var(struct st_query *query,
Wrapper for 'system' function
NOTE
- If mysqltest is executed from cygwin shell, the command will be
- executed in the "windows command interpreter" cmd.exe and we prepend "sh"
- to make it be executed by cygwins "bash". Thus commands like "rm",
- "mkdir" as well as shellscripts can executed by "system" in Windows.
+ If mysqltest is executed from cygwin shell, the command will be
+ executed in the "windows command interpreter" cmd.exe and we prepend "sh"
+ to make it be executed by cygwins "bash". Thus commands like "rm",
+ "mkdir" as well as shellscripts can executed by "system" in Windows.
*/
@@ -1469,20 +1696,19 @@ int my_system(DYNAMIC_STRING* ds_cmd)
/*
-
SYNOPSIS
do_system
- command called command
+ command called command
DESCRIPTION
- system <command>
+ system <command>
- Eval the query to expand any $variables in the command.
- Execute the command with the "system" command.
+ Eval the query to expand any $variables in the command.
+ Execute the command with the "system" command.
*/
-void do_system(struct st_query *command)
+void do_system(struct st_command *command)
{
DYNAMIC_STRING ds_cmd;
DBUG_ENTER("do_system");
@@ -1490,10 +1716,10 @@ void do_system(struct st_query *command)
if (strlen(command->first_argument) == 0)
die("Missing arguments to system, nothing to do!");
- init_dynamic_string(&ds_cmd, 0, strlen(command->first_argument) + 64, 256);
+ init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
/* Eval the system command, thus replacing all environment variables */
- do_eval(&ds_cmd, command->first_argument, TRUE);
+ do_eval(&ds_cmd, command->first_argument, command->end, TRUE);
DBUG_PRINT("info", ("running system command '%s' as '%s'",
command->first_argument, ds_cmd.str));
@@ -1509,6 +1735,304 @@ void do_system(struct st_query *command)
}
command->last_argument= command->end;
+ dynstr_free(&ds_cmd);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_remove_file
+ command called command
+
+ DESCRIPTION
+ remove_file <file_name>
+ Remove the file <file_name>
+*/
+
+void do_remove_file(struct st_command *command)
+{
+ int error;
+ static DYNAMIC_STRING ds_filename;
+ const struct command_arg rm_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to delete"
+ };
+ DBUG_ENTER("do_remove_file");
+
+ check_command_args(command, command->first_argument,
+ rm_args, sizeof(rm_args)/sizeof(struct command_arg),
+ ' ');
+
+ DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
+ error= my_delete(ds_filename.str, MYF(0)) != 0;
+ handle_command_error(command, error);
+ dynstr_free(&ds_filename);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_copy_file
+ command command handle
+
+ DESCRIPTION
+ copy_file <from_file> <to_file>
+ Copy <from_file> to <to_file>
+
+ NOTE! Will fail if <to_file> exists
+*/
+
+void do_copy_file(struct st_command *command)
+{
+ int error;
+ static DYNAMIC_STRING ds_from_file;
+ static DYNAMIC_STRING ds_to_file;
+ const struct command_arg copy_file_args[] = {
+ "from_file", ARG_STRING, TRUE, &ds_from_file, "Filename to copy from",
+ "to_file", ARG_STRING, TRUE, &ds_to_file, "Filename to copy to"
+ };
+ DBUG_ENTER("do_copy_file");
+
+ check_command_args(command, command->first_argument,
+ copy_file_args,
+ sizeof(copy_file_args)/sizeof(struct command_arg),
+ ' ');
+
+ DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
+ error= (my_copy(ds_from_file.str, ds_to_file.str,
+ MYF(MY_DONT_OVERWRITE_FILE)) != 0);
+ handle_command_error(command, error);
+ dynstr_free(&ds_from_file);
+ dynstr_free(&ds_to_file);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_file_exists
+ command called command
+
+ DESCRIPTION
+ fiile_exist <file_name>
+ Check if file <file_name> exists
+*/
+
+void do_file_exist(struct st_command *command)
+{
+ int error;
+ static DYNAMIC_STRING ds_filename;
+ const struct command_arg file_exist_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to check if it exist"
+ };
+ DBUG_ENTER("do_file_exist");
+
+ check_command_args(command, command->first_argument,
+ file_exist_args,
+ sizeof(file_exist_args)/sizeof(struct command_arg),
+ ' ');
+
+ DBUG_PRINT("info", ("Checking for existence of file: %s", ds_filename.str));
+ error= (access(ds_filename.str, F_OK) != 0);
+ handle_command_error(command, error);
+ dynstr_free(&ds_filename);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Read characters from line buffer or file. This is needed to allow
+ my_ungetc() to buffer MAX_DELIMITER_LENGTH characters for a file
+
+ NOTE:
+ This works as long as one doesn't change files (with 'source file_name')
+ when there is things pushed into the buffer. This should however not
+ happen for any tests in the test suite.
+*/
+
+int my_getc(FILE *file)
+{
+ if (line_buffer_pos == line_buffer)
+ return fgetc(file);
+ return *--line_buffer_pos;
+}
+
+
+void my_ungetc(int c)
+{
+ *line_buffer_pos++= (char) c;
+}
+
+
+void read_until_delimiter(DYNAMIC_STRING *ds,
+ DYNAMIC_STRING *ds_delimiter)
+{
+ char c;
+ DBUG_ENTER("read_until_delimiter");
+ DBUG_PRINT("enter", ("delimiter: %s, length: %d",
+ ds_delimiter->str, ds_delimiter->length));
+
+ if (ds_delimiter->length > MAX_DELIMITER_LENGTH)
+ die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
+
+ /* Read from file until delimiter is found */
+ while (1)
+ {
+ c= my_getc(cur_file->file);
+
+ if (c == '\n')
+ cur_file->lineno++;
+
+ if (feof(cur_file->file))
+ die("End of file encountered before '%s' delimiter was found",
+ ds_delimiter->str);
+
+ if (match_delimiter(c, ds_delimiter->str, ds_delimiter->length))
+ {
+ DBUG_PRINT("exit", ("Found delimiter '%s'", ds_delimiter->str));
+ break;
+ }
+ dynstr_append_mem(ds, (const char*)&c, 1);
+ }
+ DBUG_PRINT("exit", ("ds: %s", ds->str));
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_write_file
+ command called command
+
+ DESCRIPTION
+ write_file <file_name> [<delimiter>];
+ <what to write line 1>
+ <...>
+ < what to write line n>
+ EOF
+
+ --write_file <file_name>;
+ <what to write line 1>
+ <...>
+ < what to write line n>
+ EOF
+
+ Write everything between the "write_file" command and 'delimiter'
+ to "file_name"
+
+ NOTE! Overwrites existing file
+
+ Default <delimiter> is EOF
+
+*/
+
+void do_write_file(struct st_command *command)
+{
+ static DYNAMIC_STRING ds_content;
+ static DYNAMIC_STRING ds_filename;
+ static DYNAMIC_STRING ds_delimiter;
+ const struct command_arg write_file_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to write to",
+ "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until"
+ };
+ DBUG_ENTER("do_write_file");
+
+ check_command_args(command,
+ command->first_argument,
+ write_file_args,
+ sizeof(write_file_args)/sizeof(struct command_arg),
+ ' ');
+
+ /* If no delimiter was provided, use EOF */
+ if (ds_delimiter.length == 0)
+ dynstr_set(&ds_delimiter, "EOF");
+
+ init_dynamic_string(&ds_content, "", 1024, 1024);
+ read_until_delimiter(&ds_content, &ds_delimiter);
+ DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str));
+ str_to_file(ds_filename.str, ds_content.str, ds_content.length);
+ dynstr_free(&ds_content);
+ dynstr_free(&ds_filename);
+ dynstr_free(&ds_delimiter);
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ SYNOPSIS
+ do_perl
+ command command handle
+
+ DESCRIPTION
+ perl [<delimiter>];
+ <perlscript line 1>
+ <...>
+ <perlscript line n>
+ EOF
+
+ Execute everything after "perl" until <delimiter> as perl.
+ Useful for doing more advanced things
+ but still being able to execute it on all platforms.
+
+ Default <delimiter> is EOF
+*/
+
+void do_perl(struct st_command *command)
+{
+ int error;
+ char buf[FN_REFLEN];
+ FILE *res_file;
+ static DYNAMIC_STRING ds_script;
+ static DYNAMIC_STRING ds_delimiter;
+ const struct command_arg perl_args[] = {
+ "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until"
+ };
+ DBUG_ENTER("do_perl");
+
+ check_command_args(command,
+ command->first_argument,
+ perl_args,
+ sizeof(perl_args)/sizeof(struct command_arg),
+ ' ');
+
+ /* If no delimiter was provided, use EOF */
+ if (ds_delimiter.length == 0)
+ dynstr_set(&ds_delimiter, "EOF");
+
+ init_dynamic_string(&ds_script, "", 1024, 1024);
+ read_until_delimiter(&ds_script, &ds_delimiter);
+
+ DBUG_PRINT("info", ("Executing perl: %s", ds_script.str));
+
+ /* Format a name for a tmp .pl file that is unique for this process */
+ my_snprintf(buf, sizeof(buf), "%s/tmp/tmp_%d.pl",
+ getenv("MYSQLTEST_VARDIR"), getpid());
+ str_to_file(buf, ds_script.str, ds_script.length);
+
+ /* Format the perl <filename> command */
+ my_snprintf(buf, sizeof(buf), "perl %s/tmp/tmp_%d.pl",
+ getenv("MYSQLTEST_VARDIR"), getpid());
+
+ if (!(res_file= popen(buf, "r")) && command->abort_on_error)
+ die("popen(\"%s\", \"r\") failed", buf);
+
+ while (fgets(buf, sizeof(buf), res_file))
+ {
+ if (disable_result_log)
+ {
+ buf[strlen(buf)-1]=0;
+ DBUG_PRINT("exec_result",("%s", buf));
+ }
+ else
+ {
+ replace_dynstr_append(&ds_res, buf);
+ }
+ }
+ error= pclose(res_file);
+ handle_command_error(command, WEXITSTATUS(error));
+ dynstr_free(&ds_script);
+ dynstr_free(&ds_delimiter);
DBUG_VOID_RETURN;
}
@@ -1519,45 +2043,73 @@ void do_system(struct st_query *command)
for variable names to be escaped using \
SYNOPSIS
- do_echo()
- q called command
+ do_echo()
+ command called command
DESCRIPTION
- echo text
- Print the text after echo until end of command to result file
+ echo text
+ Print the text after echo until end of command to result file
- echo $<var_name>
- Print the content of the variable <var_name> to result file
+ echo $<var_name>
+ Print the content of the variable <var_name> to result file
- echo Some text $<var_name>
- Print "Some text" plus the content of the variable <var_name> to
- result file
+ echo Some text $<var_name>
+ Print "Some text" plus the content of the variable <var_name> to
+ result file
- echo Some text \$<var_name>
- Print "Some text" plus $<var_name> to result file
+ echo Some text \$<var_name>
+ Print "Some text" plus $<var_name> to result file
*/
-int do_echo(struct st_query *command)
+int do_echo(struct st_command *command)
{
- DYNAMIC_STRING *ds, ds_echo;
+ DYNAMIC_STRING ds_echo;
- ds= &ds_res;
-
- init_dynamic_string(&ds_echo, "", 256, 256);
- do_eval(&ds_echo, command->first_argument, FALSE);
- dynstr_append_mem(ds, ds_echo.str, ds_echo.length);
- dynstr_append_mem(ds, "\n", 1);
+ init_dynamic_string(&ds_echo, "", command->query_len, 256);
+ do_eval(&ds_echo, command->first_argument, command->end, FALSE);
+ dynstr_append_mem(&ds_res, ds_echo.str, ds_echo.length);
+ dynstr_append_mem(&ds_res, "\n", 1);
dynstr_free(&ds_echo);
command->last_argument= command->end;
- return 0;
+ return(0);
}
-int do_sync_with_master2(long offset)
+void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused)))
{
- MYSQL_RES* res;
+ static int SLAVE_POLL_INTERVAL= 300000;
+ MYSQL* mysql = &cur_con->mysql;
+ for (;;)
+ {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int done;
+ LINT_INIT(res);
+
+ if (mysql_query(mysql,"show status like 'Slave_running'") ||
+ !(res=mysql_store_result(mysql)))
+ die("Query failed while probing slave for stop: %s",
+ mysql_error(mysql));
+ if (!(row=mysql_fetch_row(res)) || !row[1])
+ {
+ mysql_free_result(res);
+ die("Strange result from query while probing slave for stop");
+ }
+ done = !strcmp(row[1],"OFF");
+ mysql_free_result(res);
+ if (done)
+ break;
+ my_sleep(SLAVE_POLL_INTERVAL);
+ }
+ return;
+}
+
+
+void do_sync_with_master2(long offset)
+{
+ MYSQL_RES *res;
MYSQL_ROW row;
- MYSQL* mysql= &cur_con->mysql;
+ MYSQL *mysql= &cur_con->mysql;
char query_buf[FN_REFLEN+128];
int tries= 0;
int rpl_parse;
@@ -1573,7 +2125,7 @@ int do_sync_with_master2(long offset)
wait_for_position:
if (mysql_query(mysql, query_buf))
- die("failed in %s: %d: %s", query_buf, mysql_errno(mysql),
+ die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql),
mysql_error(mysql));
if (!(res= mysql_store_result(mysql)))
@@ -1586,9 +2138,9 @@ wait_for_position:
It may be that the slave SQL thread has not started yet, though START
SLAVE has been issued ?
*/
- if (tries++ == 3)
+ if (tries++ == 30)
die("could not sync with master ('%s' returned NULL)", query_buf);
- sleep(1); /* So at most we will wait 3 seconds and make 4 tries */
+ sleep(1); /* So at most we will wait 30 seconds and make 31 tries */
mysql_free_result(res);
goto wait_for_position;
}
@@ -1596,13 +2148,14 @@ wait_for_position:
if (rpl_parse)
mysql_enable_rpl_parse(mysql);
- return 0;
+ return;
}
-int do_sync_with_master(struct st_query *query)
+
+void do_sync_with_master(struct st_command *command)
{
long offset= 0;
- char *p= query->first_argument;
+ char *p= command->first_argument;
const char *offset_start= p;
if (*offset_start)
{
@@ -1611,24 +2164,168 @@ int do_sync_with_master(struct st_query *query)
if(*p && !my_isspace(charset_info, *p))
die("Invalid integer argument \"%s\"", offset_start);
- query->last_argument= p;
+ command->last_argument= p;
}
- return do_sync_with_master2(offset);
+ do_sync_with_master2(offset);
+ return;
}
+
+/*
+ when ndb binlog is on, this call will wait until last updated epoch
+ (locally in the mysqld) has been received into the binlog
+*/
int do_save_master_pos()
{
- MYSQL_RES* res;
+ MYSQL_RES *res;
MYSQL_ROW row;
- MYSQL* mysql = &cur_con->mysql;
+ MYSQL *mysql = &cur_con->mysql;
const char *query;
int rpl_parse;
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
+#ifdef HAVE_NDB_BINLOG
+ /*
+ Wait for ndb binlog to be up-to-date with all changes
+ done on the local mysql server
+ */
+ {
+ ulong have_ndbcluster;
+ if (mysql_query(mysql, query= "show variables like 'have_ndbcluster'"))
+ die("'%s' failed: %d %s", query,
+ mysql_errno(mysql), mysql_error(mysql));
+ if (!(res= mysql_store_result(mysql)))
+ die("mysql_store_result() returned NULL for '%s'", query);
+ if (!(row= mysql_fetch_row(res)))
+ die("Query '%s' returned empty result", query);
+
+ have_ndbcluster= strcmp("YES", row[1]) == 0;
+ mysql_free_result(res);
+
+ if (have_ndbcluster)
+ {
+ ulonglong start_epoch= 0, applied_epoch= 0,
+ latest_epoch=0, latest_trans_epoch=0,
+ latest_handled_binlog_epoch= 0, latest_received_binlog_epoch= 0,
+ latest_applied_binlog_epoch= 0;
+ int count= 0;
+ int do_continue= 1;
+ while (do_continue)
+ {
+ const char binlog[]= "binlog";
+ const char latest_epoch_str[]=
+ "latest_epoch=";
+ const char latest_trans_epoch_str[]=
+ "latest_trans_epoch=";
+ const char latest_received_binlog_epoch_str[]=
+ "latest_received_binlog_epoch";
+ const char latest_handled_binlog_epoch_str[]=
+ "latest_handled_binlog_epoch=";
+ const char latest_applied_binlog_epoch_str[]=
+ "latest_applied_binlog_epoch=";
+ if (count)
+ sleep(1);
+ if (mysql_query(mysql, query= "show engine ndb status"))
+ die("failed in '%s': %d %s", query,
+ mysql_errno(mysql), mysql_error(mysql));
+ if (!(res= mysql_store_result(mysql)))
+ die("mysql_store_result() returned NULL for '%s'", query);
+ while ((row= mysql_fetch_row(res)))
+ {
+ if (strcmp(row[1], binlog) == 0)
+ {
+ const char *status= row[2];
+
+ /* latest_epoch */
+ while (*status && strncmp(status, latest_epoch_str,
+ sizeof(latest_epoch_str)-1))
+ status++;
+ if (*status)
+ {
+ status+= sizeof(latest_epoch_str)-1;
+ latest_epoch= strtoull(status, (char**) 0, 10);
+ }
+ else
+ die("result does not contain '%s' in '%s'",
+ latest_epoch_str, query);
+ /* latest_trans_epoch */
+ while (*status && strncmp(status, latest_trans_epoch_str,
+ sizeof(latest_trans_epoch_str)-1))
+ status++;
+ if (*status)
+ {
+ status+= sizeof(latest_trans_epoch_str)-1;
+ latest_trans_epoch= strtoull(status, (char**) 0, 10);
+ }
+ else
+ die("result does not contain '%s' in '%s'",
+ latest_trans_epoch_str, query);
+ /* latest_received_binlog_epoch */
+ while (*status &&
+ strncmp(status, latest_received_binlog_epoch_str,
+ sizeof(latest_received_binlog_epoch_str)-1))
+ status++;
+ if (*status)
+ {
+ status+= sizeof(latest_received_binlog_epoch_str)-1;
+ latest_received_binlog_epoch= strtoull(status, (char**) 0, 10);
+ }
+ else
+ die("result does not contain '%s' in '%s'",
+ latest_received_binlog_epoch_str, query);
+ /* latest_handled_binlog */
+ while (*status &&
+ strncmp(status, latest_handled_binlog_epoch_str,
+ sizeof(latest_handled_binlog_epoch_str)-1))
+ status++;
+ if (*status)
+ {
+ status+= sizeof(latest_handled_binlog_epoch_str)-1;
+ latest_handled_binlog_epoch= strtoull(status, (char**) 0, 10);
+ }
+ else
+ die("result does not contain '%s' in '%s'",
+ latest_handled_binlog_epoch_str, query);
+ /* latest_applied_binlog_epoch */
+ while (*status &&
+ strncmp(status, latest_applied_binlog_epoch_str,
+ sizeof(latest_applied_binlog_epoch_str)-1))
+ status++;
+ if (*status)
+ {
+ status+= sizeof(latest_applied_binlog_epoch_str)-1;
+ latest_applied_binlog_epoch= strtoull(status, (char**) 0, 10);
+ }
+ else
+ die("result does not contain '%s' in '%s'",
+ latest_applied_binlog_epoch_str, query);
+ if (count == 0)
+ start_epoch= latest_trans_epoch;
+ break;
+ }
+ }
+ if (!row)
+ die("result does not contain '%s' in '%s'",
+ binlog, query);
+ if (latest_applied_binlog_epoch > applied_epoch)
+ count= 0;
+ applied_epoch= latest_applied_binlog_epoch;
+ count++;
+ if (latest_handled_binlog_epoch >= start_epoch)
+ do_continue= 0;
+ else if (count > 30)
+ {
+ break;
+ }
+ mysql_free_result(res);
+ }
+ }
+ }
+#endif
if (mysql_query(mysql, query= "show master status"))
- die("failed in show master status: %d: %s",
+ die("failed in 'show master status': %d %s",
mysql_errno(mysql), mysql_error(mysql));
if (!(res = mysql_store_result(mysql)))
@@ -1650,28 +2347,29 @@ int do_save_master_pos()
Assign the variable <var_name> with <var_val>
SYNOPSIS
- do_let()
- query called command
+ do_let()
+ query called command
DESCRIPTION
- let $<var_name>=<var_val><delimiter>
+ let $<var_name>=<var_val><delimiter>
- <var_name> - is the string string found between the $ and =
- <var_val> - is the content between the = and <delimiter>, it may span
- multiple line and contain any characters except <delimiter>
- <delimiter> - is a string containing of one or more chars, default is ;
+ <var_name> - is the string string found between the $ and =
+ <var_val> - is the content between the = and <delimiter>, it may span
+ multiple line and contain any characters except <delimiter>
+ <delimiter> - is a string containing of one or more chars, default is ;
RETURN VALUES
- Program will die if error detected
+ Program will die if error detected
*/
-int do_let(struct st_query *query)
+void do_let(struct st_command *command)
{
- int ret;
- char *p= query->first_argument;
+ char *p= command->first_argument;
char *var_name, *var_name_end;
DYNAMIC_STRING let_rhs_expr;
+ DBUG_ENTER("do_let");
+
init_dynamic_string(&let_rhs_expr, "", 512, 2048);
/* Find <var_name> */
@@ -1681,7 +2379,8 @@ int do_let(struct st_query *query)
while (*p && (*p != '=') && !my_isspace(charset_info,*p))
p++;
var_name_end= p;
- if (var_name+1 == var_name_end)
+ if (var_name == var_name_end ||
+ (var_name+1 == var_name_end && *var_name == '$'))
die("Missing variable name in let");
while (my_isspace(charset_info,*p))
p++;
@@ -1692,34 +2391,18 @@ int do_let(struct st_query *query)
while (*p && my_isspace(charset_info,*p))
p++;
- do_eval(&let_rhs_expr, p, FALSE);
+ do_eval(&let_rhs_expr, p, command->end, FALSE);
- query->last_argument= query->end;
+ command->last_argument= command->end;
/* Assign var_val to var_name */
- ret= var_set(var_name, var_name_end, let_rhs_expr.str,
- (let_rhs_expr.str + let_rhs_expr.length));
+ var_set(var_name, var_name_end, let_rhs_expr.str,
+ (let_rhs_expr.str + let_rhs_expr.length));
dynstr_free(&let_rhs_expr);
-
- return(ret);
-}
-
-
-/*
- Store an integer (typically the returncode of the last SQL)
- statement in the mysqltest builtin variable $mysql_errno, by
- simulating of a user statement "let $mysql_errno= <integer>"
-*/
-
-int var_set_errno(int sql_errno)
-{
- const char *var_name= "$mysql_errno";
- char var_val[21];
- uint length= my_sprintf(var_val, (var_val, "%d", sql_errno));
- return var_set(var_name, var_name + 12, var_val, var_val + length);
+ DBUG_VOID_RETURN;
}
-int do_rpl_probe(struct st_query *query __attribute__((unused)))
+int do_rpl_probe(struct st_command *command __attribute__((unused)))
{
DBUG_ENTER("do_rpl_probe");
if (mysql_rpl_probe(&cur_con->mysql))
@@ -1728,14 +2411,14 @@ int do_rpl_probe(struct st_query *query __attribute__((unused)))
}
-int do_enable_rpl_parse(struct st_query *query __attribute__((unused)))
+int do_enable_rpl_parse(struct st_command *command __attribute__((unused)))
{
mysql_enable_rpl_parse(&cur_con->mysql);
return 0;
}
-int do_disable_rpl_parse(struct st_query *query __attribute__((unused)))
+int do_disable_rpl_parse(struct st_command *command __attribute__((unused)))
{
mysql_disable_rpl_parse(&cur_con->mysql);
return 0;
@@ -1743,17 +2426,17 @@ int do_disable_rpl_parse(struct st_query *query __attribute__((unused)))
/*
- Sleep the number of specifed seconds
+ Sleep the number of specified seconds
SYNOPSIS
- do_sleep()
- q called command
- real_sleep use the value from opt_sleep as number of seconds to sleep
- if real_sleep is false
+ do_sleep()
+ q called command
+ real_sleep use the value from opt_sleep as number of seconds to sleep
+ if real_sleep is false
DESCRIPTION
- sleep <seconds>
- real_sleep <seconds>
+ sleep <seconds>
+ real_sleep <seconds>
The difference between the sleep and real_sleep commands is that sleep
uses the delay from the --sleep command-line option if there is one.
@@ -1764,26 +2447,26 @@ int do_disable_rpl_parse(struct st_query *query __attribute__((unused)))
used for cpu-independent delays.
*/
-int do_sleep(struct st_query *query, my_bool real_sleep)
+int do_sleep(struct st_command *command, my_bool real_sleep)
{
int error= 0;
- char *p= query->first_argument;
- char *sleep_start, *sleep_end= query->end;
+ char *p= command->first_argument;
+ char *sleep_start, *sleep_end= command->end;
double sleep_val;
while (my_isspace(charset_info, *p))
p++;
if (!*p)
- die("Missing argument to %.*s", query->first_word_len, query->query);
+ die("Missing argument to %.*s", command->first_word_len, command->query);
sleep_start= p;
/* Check that arg starts with a digit, not handled by my_strtod */
if (!my_isdigit(charset_info, *sleep_start))
- die("Invalid argument to %.*s \"%s\"", query->first_word_len, query->query,
- query->first_argument);
+ die("Invalid argument to %.*s \"%s\"", command->first_word_len,
+ command->query,command->first_argument);
sleep_val= my_strtod(sleep_start, &sleep_end, &error);
if (error)
- die("Invalid argument to %.*s \"%s\"", query->first_word_len, query->query,
- query->first_argument);
+ die("Invalid argument to %.*s \"%s\"", command->first_word_len,
+ command->query, command->first_argument);
/* Fixed sleep time selected by --sleep option */
if (opt_sleep >= 0 && !real_sleep)
@@ -1792,13 +2475,15 @@ int do_sleep(struct st_query *query, my_bool real_sleep)
DBUG_PRINT("info", ("sleep_val: %f", sleep_val));
if (sleep_val)
my_sleep((ulong) (sleep_val * 1000000L));
- query->last_argument= sleep_end;
+ command->last_argument= sleep_end;
return 0;
}
-static void get_file_name(char *filename, struct st_query *q)
+
+void do_get_file_name(struct st_command *command,
+ char* dest, uint dest_max_len)
{
- char *p= q->first_argument, *name;
+ char *p= command->first_argument, *name;
if (!*p)
die("Missing file name argument");
name= p;
@@ -1806,13 +2491,14 @@ static void get_file_name(char *filename, struct st_query *q)
p++;
if (*p)
*p++= 0;
- q->last_argument= p;
- strmake(filename, name, FN_REFLEN);
+ command->last_argument= p;
+ strmake(dest, name, dest_max_len);
}
-static void set_charset(struct st_query *q)
+
+void do_set_charset(struct st_command *command)
{
- char *charset_name= q->first_argument;
+ char *charset_name= command->first_argument;
char *p;
if (!charset_name || !*charset_name)
@@ -1823,72 +2509,182 @@ static void set_charset(struct st_query *q)
p++;
if(*p)
*p++= 0;
- q->last_argument= p;
+ command->last_argument= p;
charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
if (!charset_info)
- abort_not_supported_test();
+ abort_not_supported_test("Test requires charset '%s'", charset_name);
}
-static uint get_errcodes(match_err *to,struct st_query *q)
+
+#if MYSQL_VERSION_ID >= 50000
+/* List of error names to error codes, available from 5.0 */
+typedef struct
{
- char *p= q->first_argument;
+ const char *name;
+ uint code;
+} st_error;
+
+static st_error global_error_names[] =
+{
+#include <mysqld_ername.h>
+ { 0, 0 }
+};
+
+uint get_errcode_from_name(char *error_name, char *error_end)
+{
+ /* SQL error as string */
+ st_error *e= global_error_names;
+
+ DBUG_ENTER("get_errcode_from_name");
+ DBUG_PRINT("enter", ("error_name: %s", error_name));
+
+ /* Loop through the array of known error names */
+ for (; e->name; e++)
+ {
+ /*
+ If we get a match, we need to check the length of the name we
+ matched against in case it was longer than what we are checking
+ (as in ER_WRONG_VALUE vs. ER_WRONG_VALUE_COUNT).
+ */
+ if (!strncmp(error_name, e->name, (int) (error_end - error_name)) &&
+ (uint) strlen(e->name) == (uint) (error_end - error_name))
+ {
+ DBUG_RETURN(e->code);
+ }
+ }
+ if (!e->name)
+ die("Unknown SQL error name '%s'", error_name);
+ DBUG_RETURN(0);
+}
+#else
+uint get_errcode_from_name(char *error_name __attribute__((unused)),
+ char *error_end __attribute__((unused)))
+{
+ abort_not_in_this_version();
+ return 0; /* Never reached */
+}
+#endif
+
+
+
+void do_get_errcodes(struct st_command *command)
+{
+ struct st_match_err *to= saved_expected_errors.err;
+ char *p= command->first_argument;
uint count= 0;
- DBUG_ENTER("get_errcodes");
+ DBUG_ENTER("do_get_errcodes");
if (!*p)
- die("Missing argument in %s", q->query);
+ die("Missing argument(s) to 'error'");
do
{
+ char *end;
+
+ /* Skip leading spaces */
+ while (*p && *p == ' ')
+ p++;
+
+ /* Find end */
+ end= p;
+ while (*end && *end != ',' && *end != ' ')
+ end++;
+
if (*p == 'S')
{
- /* SQLSTATE string */
- char *end= ++p + SQLSTATE_LENGTH;
- char *to_ptr= to[count].code.sqlstate;
+ char *to_ptr= to->code.sqlstate;
- for (; my_isalnum(charset_info, *p) && p != end; p++)
- *to_ptr++= *p;
- *to_ptr= 0;
+ /*
+ SQLSTATE string
+ - Must be SQLSTATE_LENGTH long
+ - May contain only digits[0-9] and _uppercase_ letters
+ */
+ p++; /* Step past the S */
+ if ((end - p) != SQLSTATE_LENGTH)
+ die("The sqlstate must be exactly %d chars long", SQLSTATE_LENGTH);
- to[count].type= ERR_SQLSTATE;
+ /* Check sqlstate string validity */
+ while (*p && p < end)
+ {
+ if (my_isdigit(charset_info, *p) || my_isupper(charset_info, *p))
+ *to_ptr++= *p++;
+ else
+ die("The sqlstate may only consist of digits[0-9] " \
+ "and _uppercase_ letters");
+ }
+
+ *to_ptr= 0;
+ to->type= ERR_SQLSTATE;
+ DBUG_PRINT("info", ("ERR_SQLSTATE: %s", to->code.sqlstate));
+ }
+ else if (*p == 's')
+ {
+ die("The sqlstate definition must start with an uppercase S");
}
else if (*p == 'E')
{
- /* SQL error as string */
- st_error *e= global_error;
- char *start= p++;
+ /* Error name string */
- for (; *p == '_' || my_isalnum(charset_info, *p); p++)
- ;
- for (; e->name; e++)
- {
- if (!strncmp(start, e->name, (int) (p - start)))
- {
- to[count].code.errnum= (uint) e->code;
- to[count].type= ERR_ERRNO;
- break;
- }
- }
- if (!e->name)
- die("Unknown SQL error '%s'", start);
+ DBUG_PRINT("info", ("Error name: %s", p));
+ to->code.errnum= get_errcode_from_name(p, end);
+ to->type= ERR_ERRNO;
+ DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
+ }
+ else if (*p == 'e')
+ {
+ die("The error name definition must start with an uppercase E");
}
else
{
long val;
+ char *start= p;
+ /* Check that the string passed to str2int only contain digits */
+ while (*p && p != end)
+ {
+ if (!my_isdigit(charset_info, *p))
+ die("Invalid argument to error: '%s' - "\
+ "the errno may only consist of digits[0-9]",
+ command->first_argument);
+ p++;
+ }
+
+ /* Convert the sting to int */
+ if (!str2int(start, 10, (long) INT_MIN, (long) INT_MAX, &val))
+ die("Invalid argument to error: '%s'", command->first_argument);
- if (!(p= str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val)))
- die("Invalid argument in %s", q->query);
- to[count].code.errnum= (uint) val;
- to[count].type= ERR_ERRNO;
+ to->code.errnum= (uint) val;
+ to->type= ERR_ERRNO;
+ DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum));
}
+ to++;
count++;
- } while (*(p++) == ',');
- q->last_argument= (p - 1);
- to[count].type= ERR_EMPTY; /* End of data */
- DBUG_RETURN(count);
+
+ if (count >= (sizeof(saved_expected_errors.err) /
+ sizeof(struct st_match_err)))
+ die("Too many errorcodes specified");
+
+ /* Set pointer to the end of the last error code */
+ p= end;
+
+ /* Find next ',' */
+ while (*p && *p != ',')
+ p++;
+
+ if (*p)
+ p++; /* Step past ',' */
+
+ } while (*p);
+
+ command->last_argument= p;
+ to->type= ERR_EMPTY; /* End of data */
+
+ DBUG_PRINT("info", ("Expected errors: %d", count));
+ saved_expected_errors.count= count;
+ DBUG_VOID_RETURN;
}
+
/*
Get a string; Return ptr to end of string
Strings may be surrounded by " or '
@@ -1896,11 +2692,10 @@ static uint get_errcodes(match_err *to,struct st_query *q)
If string is a '$variable', return the value of the variable.
*/
-
-static char *get_string(char **to_ptr, char **from_ptr,
- struct st_query *q)
+char *get_string(char **to_ptr, char **from_ptr,
+ struct st_command *command)
{
- reg1 char c,sep;
+ char c, sep;
char *to= *to_ptr, *from= *from_ptr, *start=to;
DBUG_ENTER("get_string");
@@ -1946,7 +2741,7 @@ static char *get_string(char **to_ptr, char **from_ptr,
*to++=c;
}
if (*from != ' ' && *from)
- die("Wrong string argument in %s", q->query);
+ die("Wrong string argument in %s", command->query);
while (my_isspace(charset_info,*from)) /* Point to next string */
from++;
@@ -1970,71 +2765,24 @@ static char *get_string(char **to_ptr, char **from_ptr,
}
-/*
- Get arguments for replace. The syntax is:
- replace from to [from to ...]
- Where each argument may be quoted with ' or "
- A argument may also be a variable, in which case the value of the
- variable is replaced.
-*/
-
-static void get_replace(struct st_query *q)
+void set_reconnect(MYSQL* mysql, int val)
{
- uint i;
- char *from= q->first_argument;
- char *buff,*start;
- char word_end_chars[256],*pos;
- POINTER_ARRAY to_array,from_array;
- DBUG_ENTER("get_replace");
-
- free_replace();
-
- bzero((char*) &to_array,sizeof(to_array));
- bzero((char*) &from_array,sizeof(from_array));
- if (!*from)
- die("Missing argument in %s", q->query);
- start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
- while (*from)
- {
- char *to=buff;
- to=get_string(&buff, &from, q);
- if (!*from)
- die("Wrong number of arguments to replace_result in '%s'", q->query);
- insert_pointer_name(&from_array,to);
- to=get_string(&buff, &from, q);
- insert_pointer_name(&to_array,to);
- }
- for (i=1,pos=word_end_chars ; i < 256 ; i++)
- if (my_isspace(charset_info,i))
- *pos++= i;
- *pos=0; /* End pointer */
- if (!(glob_replace=init_replace((char**) from_array.typelib.type_names,
- (char**) to_array.typelib.type_names,
- (uint) from_array.typelib.count,
- word_end_chars)))
- die("Can't initialize replace from '%s'", q->query);
- free_pointer_array(&from_array);
- free_pointer_array(&to_array);
- my_free(start, MYF(0));
- q->last_argument= q->end;
+ my_bool reconnect= val;
+ DBUG_ENTER("set_reconnect");
+ DBUG_PRINT("info", ("val: %d", val));
+#if MYSQL_VERSION_ID < 50000
+ mysql->reconnect= reconnect;
+#else
+ mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
+#endif
DBUG_VOID_RETURN;
}
-void free_replace()
-{
- DBUG_ENTER("free_replace");
- if (glob_replace)
- {
- my_free((char*) glob_replace,MYF(0));
- glob_replace=0;
- }
- DBUG_VOID_RETURN;
-}
-struct connection * find_connection_by_name(const char *name)
+struct st_connection * find_connection_by_name(const char *name)
{
- struct connection *con;
- for (con= cons; con < next_con; con++)
+ struct st_connection *con;
+ for (con= connections; con < next_con; con++)
{
if (!strcmp(con->name, name))
{
@@ -2056,10 +2804,10 @@ int select_connection_name(const char *name)
}
-int select_connection(struct st_query *query)
+int select_connection(struct st_command *command)
{
char *name;
- char *p= query->first_argument;
+ char *p= command->first_argument;
DBUG_ENTER("select_connection");
if (!*p)
@@ -2069,15 +2817,16 @@ int select_connection(struct st_query *query)
p++;
if (*p)
*p++= 0;
- query->last_argument= p;
+ command->last_argument= p;
return select_connection_name(name);
}
-int close_connection(struct st_query *q)
+void do_close_connection(struct st_command *command)
{
- char *p= q->first_argument, *name;
- struct connection *con;
+ char *p= command->first_argument, *name;
+ struct st_connection *con;
+
DBUG_ENTER("close_connection");
DBUG_PRINT("enter",("name: '%s'",p));
@@ -2089,13 +2838,17 @@ int close_connection(struct st_query *q)
if (*p)
*p++= 0;
- q->last_argument= p;
- for (con= cons; con < next_con; con++)
+ command->last_argument= p;
+
+ /* Loop through connection pool for connection to close */
+ for (con= connections; con < next_con; con++)
{
+ DBUG_PRINT("info", ("con->name: %s", con->name));
if (!strcmp(con->name, name))
{
+ DBUG_PRINT("info", ("Closing connection %s", con->name));
#ifndef EMBEDDED_LIBRARY
- if (q->type == Q_DIRTY_CLOSE)
+ if (command->type == Q_DIRTY_CLOSE)
{
if (con->mysql.net.vio)
{
@@ -2109,127 +2862,80 @@ int close_connection(struct st_query *q)
mysql_close(con->util_mysql);
con->util_mysql= 0;
my_free(con->name, MYF(0));
+
/*
- When the connection is closed set name to "closed_connection"
- to make it possible to reuse the connection name.
- The connection slot will not be reused
- */
+ When the connection is closed set name to "closed_connection"
+ to make it possible to reuse the connection name.
+ The connection slot will not be reused
+ */
if (!(con->name = my_strdup("closed_connection", MYF(MY_WME))))
die("Out of memory");
- DBUG_RETURN(0);
+
+ DBUG_VOID_RETURN;
}
}
die("connection '%s' not found in connection pool", name);
- DBUG_RETURN(1); /* Never reached */
-}
-
-
-/*
- This one now is a hack - we may want to improve in in the
- future to handle quotes. For now we assume that anything that is not
- a comma, a space or ) belongs to the argument. space is a chopper, comma or
- ) are delimiters/terminators
-
- SYNOPSIS
- safe_get_param
- str - string to get param from
- arg - pointer to string where result will be stored
- msg - Message to display if param is not found
- if msg is 0 this param is not required and param may be empty
-
- RETURNS
- pointer to str after param
-
-*/
-
-char* safe_get_param(char *str, char** arg, const char *msg)
-{
- DBUG_ENTER("safe_get_param");
- if(!*str)
- {
- if (msg)
- die(msg);
- *arg= str;
- DBUG_RETURN(str);
- }
- while (*str && my_isspace(charset_info,*str))
- str++;
- *arg= str;
- while (*str && *str != ',' && *str != ')')
- str++;
- if (msg && !*arg)
- die(msg);
-
- *str++= 0;
- DBUG_RETURN(str);
}
-#ifndef EMBEDDED_LIBRARY
-void init_manager()
-{
- if (!(manager=mysql_manager_init(0)))
- die("Failed in mysql_manager_init()");
- if (!mysql_manager_connect(manager,manager_host,manager_user,
- manager_pass,manager_port))
- die("Could not connect to MySQL manager: %s(%d)",manager->last_error,
- manager->last_errno);
-
-}
-#endif
-
/*
Connect to a server doing several retries if needed.
SYNOPSIS
- safe_connect()
- con - connection structure to be used
- host, user, pass, - connection parameters
- db, port, sock
+ safe_connect()
+ con - connection structure to be used
+ host, user, pass, - connection parameters
+ db, port, sock
NOTE
- Sometimes in a test the client starts before
- the server - to solve the problem, we try again
- after some sleep if connection fails the first
- time
+ Sometimes in a test the client starts before
+ the server - to solve the problem, we try again
+ after some sleep if connection fails the first
+ time
- This function will try to connect to the given server
- "opt_max_connect_retries" times and sleep "connection_retry_sleep"
- seconds between attempts before finally giving up.
- This helps in situation when the client starts
- before the server (which happens sometimes).
- It will ignore any errors during these retries. One should use
- connect_n_handle_errors() if he expects a connection error and wants
- handle as if it was an error from a usual statement.
+ This function will try to connect to the given server
+ "opt_max_connect_retries" times and sleep "connection_retry_sleep"
+ seconds between attempts before finally giving up.
+ This helps in situation when the client starts
+ before the server (which happens sometimes).
+ It will only ignore connection errors during these retries.
- RETURN VALUE
- 0 - success, non-0 - failure
*/
-int safe_connect(MYSQL* mysql, const char *host, const char *user,
- const char *pass, const char *db, int port, const char *sock)
+void safe_connect(MYSQL* mysql, const char *name, const char *host,
+ const char *user, const char *pass, const char *db,
+ int port, const char *sock)
{
- int con_error= 1;
- my_bool reconnect= 1;
- static int connection_retry_sleep= 2; /* Seconds */
- int i;
- for (i= 0; i < opt_max_connect_retries; i++)
+ int failed_attempts= 0;
+ static ulong connection_retry_sleep= 100000; /* Microseconds */
+
+ DBUG_ENTER("safe_connect");
+ while(!mysql_real_connect(mysql, host,user, pass, db, port, sock,
+ CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
{
- if (mysql_real_connect(mysql, host,user, pass, db, port, sock,
- CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
+ /*
+ Connect failed
+
+ Only allow retry if this was an error indicating the server
+ could not be contacted
+ */
+
+ if (mysql_errno(mysql) == CR_CONNECTION_ERROR &&
+ failed_attempts < opt_max_connect_retries)
+ my_sleep(connection_retry_sleep);
+ else
{
- con_error= 0;
- break;
+ if (failed_attempts > 0)
+ die("Could not open connection '%s' after %d attempts: %d %s", name,
+ failed_attempts, mysql_errno(mysql), mysql_error(mysql));
+ else
+ die("Could not open connection '%s': %d %s", name,
+ mysql_errno(mysql), mysql_error(mysql));
}
- sleep(connection_retry_sleep);
+ failed_attempts++;
}
- /*
- TODO: change this to 0 in future versions, but the 'kill' test relies on
- existing behavior
- */
- mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
- return con_error;
+ DBUG_VOID_RETURN;
}
@@ -2237,45 +2943,41 @@ int safe_connect(MYSQL* mysql, const char *host, const char *user,
Connect to a server and handle connection errors in case they occur.
SYNOPSIS
- connect_n_handle_errors()
- q - context of connect "query" (command)
- con - connection structure to be used
- host, user, pass, - connection parameters
- db, port, sock
- create_conn - out parameter, set to zero if connection was
- not established and is not touched otherwise
+ connect_n_handle_errors()
+ q - context of connect "query" (command)
+ con - connection structure to be used
+ host, user, pass, - connection parameters
+ db, port, sock
DESCRIPTION
- This function will try to establish a connection to server and handle
- possible errors in the same manner as if "connect" was usual SQL-statement
- (If error is expected it will ignore it once it occurs and log the
- "statement" to the query log).
- Unlike safe_connect() it won't do several attempts.
+ This function will try to establish a connection to server and handle
+ possible errors in the same manner as if "connect" was usual SQL-statement
+ (If error is expected it will ignore it once it occurs and log the
+ "statement" to the query log).
+ Unlike safe_connect() it won't do several attempts.
+
+ RETURN VALUES
+ 1 - Connected
+ 0 - Not connected
- RETURN VALUE
- 0 - success, non-0 - failure
*/
-int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
+int connect_n_handle_errors(struct st_command *command,
+ MYSQL* con, const char* host,
const char* user, const char* pass,
- const char* db, int port, const char* sock,
- int* create_conn)
+ const char* db, int port, const char* sock)
{
DYNAMIC_STRING *ds;
- my_bool reconnect= 1;
- int error= 0;
ds= &ds_res;
- if (!disable_query_log)
+ /* Only log if an error is expected */
+ if (!command->abort_on_error &&
+ !disable_query_log)
{
/*
- It is nice to have connect() statement logged in result file
- in this case.
- QQ: Should we do this only if we are expecting an error ?
+ Log the connect to result log
*/
- char port_buff[22]; /* This should be enough for any int */
- char *port_end;
dynstr_append_mem(ds, "connect(", 8);
replace_dynstr_append(ds, host);
dynstr_append_mem(ds, ",", 1);
@@ -2286,8 +2988,7 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
if (db)
replace_dynstr_append(ds, db);
dynstr_append_mem(ds, ",", 1);
- port_end= int10_to_str(port, port_buff, 10);
- replace_dynstr_append_mem(ds, port_buff, port_end - port_buff);
+ replace_dynstr_append_uint(ds, port);
dynstr_append_mem(ds, ",", 1);
if (sock)
replace_dynstr_append(ds, sock);
@@ -2298,205 +2999,216 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
CLIENT_MULTI_STATEMENTS))
{
- handle_error("connect", q, mysql_errno(con), mysql_error(con),
+ handle_error(command, mysql_errno(con), mysql_error(con),
mysql_sqlstate(con), ds);
- *create_conn= 0;
- goto err;
+ return 0; /* Not connected */
}
- handle_no_error(q);
-
- /*
- TODO: change this to 0 in future versions, but the 'kill' test relies on
- existing behavior
- */
- mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect);
-
-err:
- free_replace();
- return error;
+ handle_no_error(command);
+ return 1; /* Connected */
}
/*
Open a new connection to MySQL Server with the parameters
- specified
+ specified. Make the new connection the current connection.
SYNOPSIS
- do_connect()
- q called command
+ do_connect()
+ q called command
DESCRIPTION
- connect(<name>,<host>,<user>,<pass>,<db>,[<port>,<sock>[<opts>]]);
-
- <name> - name of the new connection
- <host> - hostname of server
- <user> - user to connect as
- <pass> - password used when connecting
- <db> - initial db when connected
- <port> - server port
- <sock> - server socket
- <opts> - options to use for the connection
- SSL - use SSL if available
- COMPRESS - use compression if available
-
- */
-
-int do_connect(struct st_query *q)
-{
- char *con_name, *con_user,*con_pass, *con_host, *con_port_str,
- *con_db, *con_sock, *con_options;
- char *con_buf, *p;
- char buff[FN_REFLEN];
- int con_port;
- bool con_ssl= 0;
- bool con_compress= 0;
- int free_con_sock= 0;
- int error= 0;
- int create_conn= 1;
- VAR *var_port, *var_sock;
+ connect(<name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]]);
+ connect <name>,<host>,<user>,[<pass>,[<db>,[<port>,<sock>[<opts>]]]];
+
+ <name> - name of the new connection
+ <host> - hostname of server
+ <user> - user to connect as
+ <pass> - password used when connecting
+ <db> - initial db when connected
+ <port> - server port
+ <sock> - server socket
+ <opts> - options to use for the connection
+ * SSL - use SSL if available
+ * COMPRESS - use compression if available
+
+*/
+
+void do_connect(struct st_command *command)
+{
+ int con_port= port;
+ char *con_options;
+ bool con_ssl= 0, con_compress= 0;
+ char *ptr;
+
+ static DYNAMIC_STRING ds_connection_name;
+ static DYNAMIC_STRING ds_host;
+ static DYNAMIC_STRING ds_user;
+ static DYNAMIC_STRING ds_password;
+ static DYNAMIC_STRING ds_database;
+ static DYNAMIC_STRING ds_port;
+ static DYNAMIC_STRING ds_sock;
+ static DYNAMIC_STRING ds_options;
+ const struct command_arg connect_args[] = {
+ "connection name", ARG_STRING, TRUE, &ds_connection_name,
+ "Name of the connection",
+ "host", ARG_STRING, TRUE, &ds_host, "Host to connect to",
+ "user", ARG_STRING, FALSE, &ds_user, "User to connect as",
+ "passsword", ARG_STRING, FALSE, &ds_password,
+ "Password used when connecting",
+ "database", ARG_STRING, FALSE, &ds_database,
+ "Dtabase to select after connect",
+ "port", ARG_STRING, FALSE, &ds_port, "Port to connect to",
+ "socket", ARG_STRING, FALSE, &ds_sock, "Socket to connect with",
+ "options", ARG_STRING, FALSE, &ds_options,
+ "Options to use while connecting"
+ };
DBUG_ENTER("do_connect");
- DBUG_PRINT("enter",("connect: %s", q->first_argument));
-
- /* Make a copy of query before parsing, safe_get_param will modify */
- if (!(con_buf= my_strdup(q->first_argument, MYF(MY_WME))))
- die("Could not allocate con_buf");
- p= con_buf;
-
- if (*p != '(')
- die("Syntax error in connect - expected '(' found '%c'", *p);
- p++;
- p= safe_get_param(p, &con_name, "Missing connection name");
- p= safe_get_param(p, &con_host, "Missing connection host");
- p= safe_get_param(p, &con_user, "Missing connection user");
- p= safe_get_param(p, &con_pass, "Missing connection password");
- p= safe_get_param(p, &con_db, "Missing connection db");
+ DBUG_PRINT("enter",("connect: %s", command->first_argument));
- /* Port */
- p= safe_get_param(p, &con_port_str, 0);
- if (*con_port_str)
+ /* Remove parenteses around connect arguments */
+ if ((ptr= strstr(command->first_argument, "(")))
{
- if (*con_port_str == '$')
+ /* Replace it with a space */
+ *ptr= ' ';
+ if ((ptr= strstr(command->first_argument, ")")))
{
- if (!(var_port= var_get(con_port_str, 0, 0, 0)))
- die("Unknown variable '%s'", con_port_str+1);
- con_port= var_port->int_val;
+ /* Replace it with \0 */
+ *ptr= 0;
}
else
- {
- con_port= atoi(con_port_str);
- if (con_port == 0)
- die("Illegal argument for port: '%s'", con_port_str);
- }
+ die("connect - argument list started with '(' must be ended with ')'");
}
- else
+
+ check_command_args(command, command->first_argument, connect_args,
+ sizeof(connect_args)/sizeof(struct command_arg),
+ ',');
+
+ /* Port */
+ if (ds_port.length)
{
- con_port= port;
+ con_port= atoi(ds_port.str);
+ if (con_port == 0)
+ die("Illegal argument for port: '%s'", ds_port.str);
}
/* Sock */
- p= safe_get_param(p, &con_sock, 0);
- if (*con_sock)
+ if (ds_sock.length)
{
- if (*con_sock == '$')
+ /*
+ If the socket is specified just as a name without path
+ append tmpdir in front
+ */
+ if (*ds_sock.str != FN_LIBCHAR)
{
- if (!(var_sock= var_get(con_sock, 0, 0, 0)))
- die("Unknown variable '%s'", con_sock+1);
- if (!(con_sock= (char*)my_malloc(var_sock->str_val_len+1, MYF(0))))
- die("Out of memory");
- free_con_sock= 1;
- memcpy(con_sock, var_sock->str_val, var_sock->str_val_len);
- con_sock[var_sock->str_val_len]= 0;
+ char buff[FN_REFLEN];
+ fn_format(buff, ds_sock.str, TMPDIR, "", 0);
+ dynstr_set(&ds_sock, buff);
}
}
else
{
- con_sock= (char*) unix_sock;
+ /* No socket specified, use default */
+ dynstr_set(&ds_sock, unix_sock);
}
+ DBUG_PRINT("info", ("socket: %s", ds_sock.str));
+
/* Options */
- p= safe_get_param(p, &con_options, 0);
+ con_options= ds_options.str;
while (*con_options)
{
- char* str= con_options;
- while (*str && !my_isspace(charset_info, *str))
- str++;
- *str++= 0;
- if (!strcmp(con_options, "SSL"))
+ char* end;
+ /* Step past any spaces in beginning of option*/
+ while (*con_options && my_isspace(charset_info, *con_options))
+ con_options++;
+ /* Find end of this option */
+ end= con_options;
+ while (*end && !my_isspace(charset_info, *end))
+ end++;
+ if (!strncmp(con_options, "SSL", 3))
con_ssl= 1;
- else if (!strcmp(con_options, "COMPRESS"))
+ else if (!strncmp(con_options, "COMPRESS", 8))
con_compress= 1;
else
- die("Illegal option to connect: %s", con_options);
- con_options= str;
+ die("Illegal option to connect: %.*s",
+ (int) (end - con_options), con_options);
+ /* Process next option */
+ con_options= end;
}
- /* Note: 'p' is pointing into the copy 'con_buf' */
- q->last_argument= q->first_argument + (p - con_buf);
- if (next_con == cons_end)
- die("Connection limit exhausted - increase MAX_CONS in mysqltest.c");
+ if (next_con == connections_end)
+ die("Connection limit exhausted, you can have max %d connections",
+ (int) (sizeof(connections)/sizeof(struct st_connection)));
- if (find_connection_by_name(con_name))
- die("Connection %s already exists", con_name);
+ if (find_connection_by_name(ds_connection_name.str))
+ die("Connection %s already exists", ds_connection_name.str);
if (!mysql_init(&next_con->mysql))
die("Failed on mysql_init()");
if (opt_compress || con_compress)
mysql_options(&next_con->mysql, MYSQL_OPT_COMPRESS, NullS);
mysql_options(&next_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
- mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name);
+ mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME,
+ charset_info->csname);
+ if (opt_charsets_dir)
+ mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR,
+ opt_charsets_dir);
#ifdef HAVE_OPENSSL
if (opt_use_ssl || con_ssl)
{
- /* Turn on ssl_verify_server_cert only if host is "localhost" */
- opt_ssl_verify_server_cert= !strcmp(con_host, "localhost");
-
mysql_ssl_set(&next_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+#if MYSQL_VERSION_ID >= 50000
+ /* Turn on ssl_verify_server_cert only if host is "localhost" */
+ opt_ssl_verify_server_cert= !strcmp(ds_connection_name.str, "localhost");
mysql_options(&next_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
+#endif
}
#endif
- if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR)
- con_sock=fn_format(buff, con_sock, TMPDIR, "",0);
- if (!con_db[0])
- con_db= db;
+
+ /* Use default db name */
+ if (ds_database.length == 0)
+ dynstr_set(&ds_database, db);
+
/* Special database to allow one to connect without a database name */
- if (con_db && !strcmp(con_db,"*NO-ONE*"))
- con_db= 0;
- if (q->abort_on_error)
- {
- if (safe_connect(&next_con->mysql, con_host, con_user, con_pass,
- con_db, con_port, con_sock ? con_sock: 0))
- die("Could not open connection '%s': %d %s", con_name,
- mysql_errno(&next_con->mysql), mysql_error(&next_con->mysql));
- }
- else
- error= connect_n_handle_errors(q, &next_con->mysql, con_host, con_user,
- con_pass, con_db, con_port, con_sock,
- &create_conn);
+ if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
+ dynstr_set(&ds_database, "");
+
- if (create_conn)
+ if (connect_n_handle_errors(command, &next_con->mysql,
+ ds_host.str,ds_user.str,
+ ds_password.str, ds_database.str,
+ con_port, ds_sock.str))
{
- if (!(next_con->name= my_strdup(con_name, MYF(MY_WME))))
- die(NullS);
+ DBUG_PRINT("info", ("Inserting connection %s in connection pool",
+ ds_connection_name.str));
+ if (!(next_con->name= my_strdup(ds_connection_name.str, MYF(MY_WME))))
+ die("Out of memory");
cur_con= next_con++;
}
- if (free_con_sock)
- my_free(con_sock, MYF(MY_WME));
- my_free(con_buf, MYF(MY_WME));
- DBUG_RETURN(error);
+
+ dynstr_free(&ds_connection_name);
+ dynstr_free(&ds_host);
+ dynstr_free(&ds_user);
+ dynstr_free(&ds_password);
+ dynstr_free(&ds_database);
+ dynstr_free(&ds_port);
+ dynstr_free(&ds_sock);
+ dynstr_free(&ds_options);
+ DBUG_VOID_RETURN;
}
-int do_done(struct st_query *q)
+int do_done(struct st_command *command)
{
/* Check if empty block stack */
if (cur_block == block_stack)
{
- if (*q->query != '}')
+ if (*command->query != '}')
die("Stray 'end' command - end of block before beginning");
die("Stray '}' - end of block before beginning");
}
@@ -2522,31 +3234,31 @@ int do_done(struct st_query *q)
Process start of a "if" or "while" statement
SYNOPSIS
- do_block()
- cmd Type of block
- q called command
+ do_block()
+ cmd Type of block
+ q called command
DESCRIPTION
- if ([!]<expr>)
- {
- <block statements>
- }
+ if ([!]<expr>)
+ {
+ <block statements>
+ }
- while ([!]<expr>)
- {
- <block statements>
- }
+ while ([!]<expr>)
+ {
+ <block statements>
+ }
- Evaluates the <expr> and if it evaluates to
- greater than zero executes the following code block.
- A '!' can be used before the <expr> to indicate it should
- be executed if it evaluates to zero.
+ Evaluates the <expr> and if it evaluates to
+ greater than zero executes the following code block.
+ A '!' can be used before the <expr> to indicate it should
+ be executed if it evaluates to zero.
- */
+*/
-void do_block(enum block_cmd cmd, struct st_query* q)
+void do_block(enum block_cmd cmd, struct st_command* command)
{
- char *p= q->first_argument;
+ char *p= command->first_argument;
const char *expr_start, *expr_end;
VAR v;
const char *cmd_name= (cmd == cmd_while ? "while" : "if");
@@ -2590,9 +3302,7 @@ void do_block(enum block_cmd cmd, struct st_query* q)
while (*p && my_isspace(charset_info, *p))
p++;
- if (*p == '{')
- die("Missing newline between %s and '{'", cmd_name);
- if (*p)
+ if (*p && *p != '{')
die("Missing '{' after %s. Found \"%s\"", cmd_name, p);
var_init(&v,0,0,0,0);
@@ -2613,43 +3323,41 @@ void do_block(enum block_cmd cmd, struct st_query* q)
}
-/*
- Read characters from line buffer or file. This is needed to allow
- my_ungetc() to buffer MAX_DELIMITER characters for a file
+void do_delimiter(struct st_command* command)
+{
+ char* p= command->first_argument;
+ DBUG_ENTER("do_delimiter");
+ DBUG_PRINT("enter", ("first_argument: %s", command->first_argument));
- NOTE:
- This works as long as one doesn't change files (with 'source file_name')
- when there is things pushed into the buffer. This should however not
- happen for any tests in the test suite.
-*/
+ while (*p && my_isspace(charset_info, *p))
+ p++;
-int my_getc(FILE *file)
-{
- if (line_buffer_pos == line_buffer)
- return fgetc(file);
- return *--line_buffer_pos;
-}
+ if (!(*p))
+ die("Can't set empty delimiter");
-void my_ungetc(int c)
-{
- *line_buffer_pos++= (char) c;
+ strmake(delimiter, p, sizeof(delimiter) - 1);
+ delimiter_length= strlen(delimiter);
+
+ DBUG_PRINT("exit", ("delimiter: %s", delimiter));
+ command->last_argument= p + delimiter_length;
+ DBUG_VOID_RETURN;
}
-my_bool end_of_query(int c)
+my_bool match_delimiter(int c, const char *delim, uint length)
{
uint i;
- char tmp[MAX_DELIMITER];
+ char tmp[MAX_DELIMITER_LENGTH];
- if (c != *delimiter)
+ if (c != *delim)
return 0;
- for (i= 1; i < delimiter_length &&
- (c= my_getc(cur_file->file)) == *(delimiter + i);
+ for (i= 1; i < length &&
+ (c= my_getc(cur_file->file)) == *(delim + i);
i++)
tmp[i]= c;
- if (i == delimiter_length)
+ if (i == length)
return 1; /* Found delimiter */
/* didn't find delimiter, push back things that we read */
@@ -2660,45 +3368,51 @@ my_bool end_of_query(int c)
}
+my_bool end_of_query(int c)
+{
+ return match_delimiter(c, delimiter, delimiter_length);
+}
+
+
/*
Read one "line" from the file
SYNOPSIS
- read_line
- buf buffer for the read line
- size size of the buffer i.e max size to read
+ read_line
+ buf buffer for the read line
+ size size of the buffer i.e max size to read
DESCRIPTION
- This function actually reads several lines and adds them to the
- buffer buf. It continues to read until it finds what it believes
- is a complete query.
+ This function actually reads several lines and adds them to the
+ buffer buf. It continues to read until it finds what it believes
+ is a complete query.
- Normally that means it will read lines until it reaches the
- "delimiter" that marks end of query. Default delimiter is ';'
- The function should be smart enough not to detect delimiter's
- found inside strings surrounded with '"' and '\'' escaped strings.
+ Normally that means it will read lines until it reaches the
+ "delimiter" that marks end of query. Default delimiter is ';'
+ The function should be smart enough not to detect delimiter's
+ found inside strings surrounded with '"' and '\'' escaped strings.
- If the first line in a query starts with '#' or '-' this line is treated
- as a comment. A comment is always terminated when end of line '\n' is
- reached.
+ If the first line in a query starts with '#' or '-' this line is treated
+ as a comment. A comment is always terminated when end of line '\n' is
+ reached.
*/
int read_line(char *buf, int size)
{
- int c;
- char quote;
+ char c, last_quote;
char *p= buf, *buf_end= buf + size - 1;
- int no_save= 0;
- enum {R_NORMAL, R_Q, R_Q_IN_Q, R_SLASH_IN_Q,
- R_COMMENT, R_LINE_START} state= R_LINE_START;
+ int skip_char= 0;
+ enum {R_NORMAL, R_Q, R_SLASH_IN_Q,
+ R_COMMENT, R_LINE_START} state= R_LINE_START;
DBUG_ENTER("read_line");
- LINT_INIT(quote);
+ LINT_INIT(last_quote);
start_lineno= cur_file->lineno;
+ DBUG_PRINT("info", ("Starting to read at lineno: %d", start_lineno));
for (; p < buf_end ;)
{
- no_save= 0;
+ skip_char= 0;
c= my_getc(cur_file->file);
if (feof(cur_file->file))
{
@@ -2714,12 +3428,13 @@ int read_line(char *buf, int size)
{
/* We're back at the first file, check if
all { have matching }
- */
+ */
if (cur_block != block_stack)
die("Missing end of block");
- DBUG_PRINT("info", ("end of file"));
- DBUG_RETURN(1);
+ *p= 0;
+ DBUG_PRINT("info", ("end of file at line %d", cur_file->lineno));
+ DBUG_RETURN(1);
}
cur_file--;
start_lineno= cur_file->lineno;
@@ -2733,61 +3448,86 @@ int read_line(char *buf, int size)
/* Convert cr/lf to lf */
if (p != buf && *(p-1) == '\r')
- *(p-1)= 0;
+ p--;
}
switch(state) {
case R_NORMAL:
- /* Only accept '{' in the beginning of a line */
if (end_of_query(c))
{
*p= 0;
+ DBUG_PRINT("exit", ("Found delimiter '%s' at line %d",
+ delimiter, cur_file->lineno));
DBUG_RETURN(0);
}
- else if (c == '\'' || c == '"' || c == '`')
+ else if ((c == '{' &&
+ (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
+ (uchar*) buf, min(5, p - buf), 0) ||
+ !my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
+ (uchar*) buf, min(2, p - buf), 0))))
{
- quote= c;
- state= R_Q;
+ /* Only if and while commands can be terminated by { */
+ *p++= c;
+ *p= 0;
+ DBUG_PRINT("exit", ("Found '{' indicating start of block at line %d",
+ cur_file->lineno));
+ DBUG_RETURN(0);
}
- else if (c == '\n')
+ else if (c == '\'' || c == '"' || c == '`')
{
- state = R_LINE_START;
+ last_quote= c;
+ state= R_Q;
}
break;
+
case R_COMMENT:
if (c == '\n')
{
+ /* Comments are terminated by newline */
*p= 0;
+ DBUG_PRINT("exit", ("Found newline in comment at line: %d",
+ cur_file->lineno));
DBUG_RETURN(0);
}
break;
+
case R_LINE_START:
- /* Only accept start of comment if this is the first line in query */
- if ((cur_file->lineno == start_lineno) &&
- (c == '#' || c == '-' || parsing_disabled))
+ if (c == '#' || c == '-')
{
+ /* A # or - in the first position of the line - this is a comment */
state = R_COMMENT;
}
else if (my_isspace(charset_info, c))
{
+ /* Skip all space at begining of line */
if (c == '\n')
- start_lineno= cur_file->lineno; /* Query hasn't started yet */
- no_save= 1;
+ {
+ /* Query hasn't started yet */
+ start_lineno= cur_file->lineno;
+ DBUG_PRINT("info", ("Query hasn't started yet, start_lineno: %d",
+ start_lineno));
+ }
+ skip_char= 1;
}
- else if (c == '}')
+ else if (end_of_query(c))
{
- *buf++= '}';
- *buf= 0;
+ *p= 0;
+ DBUG_PRINT("exit", ("Found delimiter '%s' at line: %d",
+ delimiter, cur_file->lineno));
DBUG_RETURN(0);
}
- else if (end_of_query(c) || c == '{')
+ else if (c == '}')
{
+ /* A "}" need to be by itself in the begining of a line to terminate */
+ *p++= c;
*p= 0;
+ DBUG_PRINT("exit", ("Found '}' in begining of a line at line: %d",
+ cur_file->lineno));
DBUG_RETURN(0);
}
else if (c == '\'' || c == '"' || c == '`')
{
- quote= c;
+ last_quote= c;
state= R_Q;
}
else
@@ -2795,29 +3535,19 @@ int read_line(char *buf, int size)
break;
case R_Q:
- if (c == quote)
- state= R_Q_IN_Q;
+ if (c == last_quote)
+ state= R_NORMAL;
else if (c == '\\')
state= R_SLASH_IN_Q;
break;
- case R_Q_IN_Q:
- if (end_of_query(c))
- {
- *p= 0;
- DBUG_RETURN(0);
- }
- if (c != quote)
- state= R_NORMAL;
- else
- state= R_Q;
- break;
+
case R_SLASH_IN_Q:
state= R_Q;
break;
}
- if (!no_save)
+ if (!skip_char)
{
/* Could be a multibyte character */
/* This code is based on the code in "sql_load.cc" */
@@ -2835,7 +3565,7 @@ int read_line(char *buf, int size)
for (i= 1; i < charlen; i++)
{
if (feof(cur_file->file))
- goto found_eof; /* FIXME: could we just break here?! */
+ goto found_eof;
c= my_getc(cur_file->file);
*p++ = c;
}
@@ -2852,99 +3582,253 @@ int read_line(char *buf, int size)
*p++= c;
}
}
- *p= 0; /* Always end with \0 */
- DBUG_RETURN(feof(cur_file->file));
+ die("The input buffer is too small for this query.x\n" \
+ "check your query or increase MAX_QUERY and recompile");
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Convert the read query to result format version 1
+
+ That is: After newline, all spaces need to be skipped
+ unless the previous char was a quote
+
+ This is due to an old bug that has now been fixed, but the
+ version 1 output format is preserved by using this function
+
+*/
+
+void convert_to_format_v1(char* query)
+{
+ int last_c_was_quote= 0;
+ char *p= query, *write= query;
+ char *end= strend(query);
+ char last_c;
+
+ while (p <= end)
+ {
+ if (*p == '\n' && !last_c_was_quote)
+ {
+ *write++ = *p++; /* Save the newline */
+
+ /* Skip any spaces on next line */
+ while (*p && my_isspace(charset_info, *p))
+ p++;
+
+ last_c_was_quote= 0;
+ }
+ else if (*p == '\'' || *p == '"' || *p == '`')
+ {
+ last_c= *p;
+ *write++ = *p++;
+
+ /* Copy anything until the next quote of same type */
+ while (*p && *p != last_c)
+ *write++ = *p++;
+
+ *write++ = *p++;
+
+ last_c_was_quote= 1;
+ }
+ else
+ {
+ *write++ = *p++;
+ last_c_was_quote= 0;
+ }
+ }
}
+
/*
- Create a query from a set of lines
+ Check a command that is about to be sent (or should have been
+ sent if parsing was enabled) to mysql server for
+ suspicious things and generate warnings.
+*/
+
+void scan_command_for_warnings(struct st_command *command)
+{
+ const char *ptr= command->query;
+ DBUG_ENTER("scan_command_for_warnings");
+ DBUG_PRINT("enter", ("query: %s", command->query));
+
+ while(*ptr)
+ {
+ /*
+ Look for query's that lines that start with a -- comment
+ and has a mysqltest command
+ */
+ if (ptr[0] == '\n' &&
+ ptr[1] && ptr[1] == '-' &&
+ ptr[2] && ptr[2] == '-' &&
+ ptr[3])
+ {
+ uint type;
+ char save;
+ char *end, *start= (char*)ptr+3;
+ /* Skip leading spaces */
+ while (*start && my_isspace(charset_info, *start))
+ start++;
+ end= start;
+ /* Find end of command(next space) */
+ while (*end && !my_isspace(charset_info, *end))
+ end++;
+ save= *end;
+ *end= 0;
+ DBUG_PRINT("info", ("Checking '%s'", start));
+ type= find_type(start, &command_typelib, 1+2);
+ if (type)
+ warning_msg("Embedded mysqltest command '--%s' detected in "
+ "query '%s' was this intentional? ",
+ start, command->query);
+ *end= save;
+ }
+
+ ptr++;
+ }
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Check for unexpected "junk" after the end of query
+ This is normally caused by missing delimiters or when
+ switching between different delimiters
+*/
+
+void check_eol_junk_line(const char *line)
+{
+ const char *p= line;
+ DBUG_ENTER("check_eol_junk_line");
+ DBUG_PRINT("enter", ("line: %s", line));
+
+ /* Check for extra delimiter */
+ if (*p && !strncmp(p, delimiter, delimiter_length))
+ die("Extra delimiter \"%s\" found", delimiter);
+
+ /* Allow trailing # comment */
+ if (*p && *p != '#')
+ {
+ if (*p == '\n')
+ die("Missing delimiter");
+ die("End of line junk detected: \"%s\"", p);
+ }
+ DBUG_VOID_RETURN;
+}
+
+void check_eol_junk(const char *eol)
+{
+ const char *p= eol;
+ DBUG_ENTER("check_eol_junk");
+ DBUG_PRINT("enter", ("eol: %s", eol));
+
+ /* Skip past all spacing chars and comments */
+ while (*p && (my_isspace(charset_info, *p) || *p == '#' || *p == '\n'))
+ {
+ /* Skip past comments started with # and ended with newline */
+ if (*p && *p == '#')
+ {
+ p++;
+ while (*p && *p != '\n')
+ p++;
+ }
+
+ /* Check this line */
+ if (*p && *p == '\n')
+ check_eol_junk_line(p);
+
+ if (*p)
+ p++;
+ }
+
+ check_eol_junk_line(p);
+
+ DBUG_VOID_RETURN;
+}
+
+
+
+/*
+ Create a command from a set of lines
SYNOPSIS
- read_query()
- q_ptr pointer where to return the new query
+ read_command()
+ command_ptr pointer where to return the new query
DESCRIPTION
- Converts lines returned by read_line into a query, this involves
- parsing the first word in the read line to find the query type.
+ Converts lines returned by read_line into a command, this involves
+ parsing the first word in the read line to find the command type.
- A -- comment may contain a valid query as the first word after the
- comment start. Thus it's always checked to see if that is the case.
- The advantage with this approach is to be able to execute commands
- terminated by new line '\n' regardless how many "delimiter" it contain.
+ A -- comment may contain a valid query as the first word after the
+ comment start. Thus it's always checked to see if that is the case.
+ The advantage with this approach is to be able to execute commands
+ terminated by new line '\n' regardless how many "delimiter" it contain.
*/
-static char read_query_buf[MAX_QUERY];
+#define MAX_QUERY (256*1024) /* 256K -- a test in sp-big is >128K */
+static char read_command_buf[MAX_QUERY];
-int read_query(struct st_query** q_ptr)
+int read_command(struct st_command** command_ptr)
{
- char *p= read_query_buf;
- struct st_query* q;
- DBUG_ENTER("read_query");
+ char *p= read_command_buf;
+ struct st_command* command;
+ DBUG_ENTER("read_command");
if (parser.current_line < parser.read_lines)
{
- get_dynamic(&q_lines, (gptr) q_ptr, parser.current_line) ;
+ get_dynamic(&q_lines, (gptr) command_ptr, parser.current_line) ;
DBUG_RETURN(0);
}
- if (!(*q_ptr= q= (struct st_query*) my_malloc(sizeof(*q), MYF(MY_WME))) ||
- insert_dynamic(&q_lines, (gptr) &q))
+ if (!(*command_ptr= command=
+ (struct st_command*) my_malloc(sizeof(*command), MYF(MY_WME))) ||
+ insert_dynamic(&q_lines, (gptr) &command))
die(NullS);
- q->record_file[0]= 0;
- q->require_file= 0;
- q->first_word_len= 0;
+ command->require_file[0]= 0;
+ command->first_word_len= 0;
+ command->query_len= 0;
- q->type= Q_UNKNOWN;
- q->query_buf= q->query= 0;
- read_query_buf[0]= 0;
- if (read_line(read_query_buf, sizeof(read_query_buf)))
+ command->type= Q_UNKNOWN;
+ command->query_buf= command->query= 0;
+ read_command_buf[0]= 0;
+ if (read_line(read_command_buf, sizeof(read_command_buf)))
{
- check_eol_junk(read_query_buf);
+ check_eol_junk(read_command_buf);
DBUG_RETURN(1);
}
-
- DBUG_PRINT("info", ("query: %s", read_query_buf));
- if (*p == '#')
- {
- q->type= Q_COMMENT;
- /* This goto is to avoid losing the "expected error" info. */
- goto end;
- }
- if (!parsing_disabled)
- {
- memcpy((gptr) q->expected_errno, (gptr) global_expected_errno,
- sizeof(global_expected_errno));
- q->expected_errors= global_expected_errors;
- q->abort_on_error= (global_expected_errors == 0 && abort_on_error);
- }
- if (p[0] == '-' && p[1] == '-')
+ convert_to_format_v1(read_command_buf);
+
+ DBUG_PRINT("info", ("query: %s", read_command_buf));
+ if (*p == '#')
{
- q->type= Q_COMMENT_WITH_COMMAND;
- p+= 2; /* To calculate first word */
+ command->type= Q_COMMENT;
}
- else if (!parsing_disabled)
+ else if (p[0] == '-' && p[1] == '-')
{
- while (*p && my_isspace(charset_info, *p))
- p++ ;
+ command->type= Q_COMMENT_WITH_COMMAND;
+ p+= 2; /* Skip past -- */
}
-end:
+ /* Skip leading spaces */
while (*p && my_isspace(charset_info, *p))
p++;
- if (!(q->query_buf= q->query= my_strdup(p, MYF(MY_WME))))
- die(NullS);
+ if (!(command->query_buf= command->query= my_strdup(p, MYF(MY_WME))))
+ die("Out of memory");
/* Calculate first word and first argument */
- for (p= q->query; *p && !my_isspace(charset_info, *p) ; p++) ;
- q->first_word_len= (uint) (p - q->query);
+ for (p= command->query; *p && !my_isspace(charset_info, *p) ; p++) ;
+ command->first_word_len= (uint) (p - command->query);
+
+ /* Skip spaces between command and first argument */
while (*p && my_isspace(charset_info, *p))
p++;
- q->first_argument= p;
- q->end= strend(q->query);
+ command->first_argument= p;
+
+ command->end= strend(command->query);
+ command->query_len= (command->end - command->query);
parser.read_lines++;
DBUG_RETURN(0);
}
@@ -2956,8 +3840,9 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
{"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir,
(gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"big-test", 'B', "Define BIG_TEST to 1.", (gptr*) &opt_big_test,
- (gptr*) &opt_big_test, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"character-sets-dir", OPT_CHARSETS_DIR,
+ "Directory where character sets are.", (gptr*) &opt_charsets_dir,
+ (gptr*) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"compress", 'C', "Use the compressed server/client protocol.",
(gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
@@ -2975,24 +3860,16 @@ static struct my_option my_long_options[] =
#endif
{"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"manager-host", OPT_MANAGER_HOST, "Undocumented: Used for debugging.",
- (gptr*) &manager_host, (gptr*) &manager_host, 0, GET_STR, REQUIRED_ARG,
- 0, 0, 0, 0, 0, 0},
- {"manager-password", OPT_MANAGER_PASSWD, "Undocumented: Used for debugging.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"manager-port", OPT_MANAGER_PORT, "Undocumented: Used for debugging.",
- (gptr*) &manager_port, (gptr*) &manager_port, 0, GET_INT, REQUIRED_ARG,
- MYSQL_MANAGER_PORT, 0, 0, 0, 0, 0},
- {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging.",
- (gptr*) &manager_user, (gptr*) &manager_user, 0, GET_STR, REQUIRED_ARG, 0,
- 0, 0, 0, 0, 0},
- {"manager-wait-timeout", OPT_MANAGER_WAIT_TIMEOUT,
- "Undocumented: Used for debugging.", (gptr*) &manager_wait_timeout,
- (gptr*) &manager_wait_timeout, 0, GET_INT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0},
+ {"include", 'i', "Include SQL before each test case.", (gptr*) &opt_include,
+ (gptr*) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"mark-progress", OPT_MARK_PROGRESS,
+ "Write linenumber and elapsed time to <testname>.progress ",
+ (gptr*) &opt_mark_progress, (gptr*) &opt_mark_progress, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"max-connect-retries", OPT_MAX_CONNECT_RETRIES,
"Max number of connection attempts when connecting to server",
(gptr*) &opt_max_connect_retries, (gptr*) &opt_max_connect_retries, 0,
- GET_INT, REQUIRED_ARG, 5, 1, 10, 0, 0, 0},
+ GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0},
{"password", 'p', "Password to use when connecting to server.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection.", (gptr*) &port,
@@ -3005,8 +3882,8 @@ static struct my_option my_long_options[] =
{"record", 'r', "Record output of test_file into result file.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"result-file", 'R', "Read/Store result from/in this file.",
- (gptr*) &result_file, (gptr*) &result_file, 0, GET_STR, REQUIRED_ARG,
- 0, 0, 0, 0, 0, 0},
+ (gptr*) &result_file_name, (gptr*) &result_file_name, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-arg", 'A', "Send option value to embedded server as a parameter.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-file", 'F', "Read embedded server arguments from file.",
@@ -3047,7 +3924,7 @@ static struct my_option my_long_options[] =
#include <help_start.h>
-static void print_version(void)
+void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,MTEST_VERSION,
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
@@ -3068,6 +3945,52 @@ void usage()
#include <help_end.h>
+/*
+ Read arguments for embedded server and put them into
+ embedded_server_args[]
+*/
+
+void read_embedded_server_arguments(const char *name)
+{
+ char argument[1024],buff[FN_REFLEN], *str=0;
+ FILE *file;
+
+ if (!test_if_hard_path(name))
+ {
+ strxmov(buff, opt_basedir, name, NullS);
+ name=buff;
+ }
+ fn_format(buff, name, "", "", MY_UNPACK_FILENAME);
+
+ if (!embedded_server_arg_count)
+ {
+ embedded_server_arg_count=1;
+ embedded_server_args[0]= (char*) ""; /* Progname */
+ }
+ if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
+ die("Failed to open file %s", buff);
+
+ while (embedded_server_arg_count < MAX_EMBEDDED_SERVER_ARGS &&
+ (str=fgets(argument,sizeof(argument), file)))
+ {
+ *(strend(str)-1)=0; /* Remove end newline */
+ if (!(embedded_server_args[embedded_server_arg_count]=
+ (char*) my_strdup(str,MYF(MY_WME))))
+ {
+ my_fclose(file,MYF(0));
+ die("Out of memory");
+
+ }
+ embedded_server_arg_count++;
+ }
+ my_fclose(file,MYF(0));
+ if (str)
+ die("Too many arguments in option file: %s",name);
+
+ return;
+}
+
+
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
@@ -3081,41 +4004,36 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'r':
record = 1;
break;
- case (int)OPT_MANAGER_PASSWD:
- my_free(manager_pass,MYF(MY_ALLOW_ZERO_PTR));
- manager_pass=my_strdup(argument, MYF(MY_FAE));
- while (*argument) *argument++= 'x'; /* Destroy argument */
- break;
case 'x':
+ {
+ char buff[FN_REFLEN];
+ if (!test_if_hard_path(argument))
{
- char buff[FN_REFLEN];
- if (!test_if_hard_path(argument))
- {
- strxmov(buff, opt_basedir, argument, NullS);
- argument= buff;
- }
- fn_format(buff, argument, "", "", 4);
- DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
- if (!(cur_file->file=
- my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
- die("Could not open %s: errno = %d", buff, errno);
- cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
- cur_file->lineno= 1;
- break;
+ strxmov(buff, opt_basedir, argument, NullS);
+ argument= buff;
}
+ fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
+ DBUG_ASSERT(cur_file == file_stack && cur_file->file == 0);
+ if (!(cur_file->file=
+ my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
+ die("Could not open %s: errno = %d", buff, errno);
+ cur_file->file_name= my_strdup(buff, MYF(MY_FAE));
+ cur_file->lineno= 1;
+ break;
+ }
case 'm':
+ {
+ static char buff[FN_REFLEN];
+ if (!test_if_hard_path(argument))
{
- static char buff[FN_REFLEN];
- if (!test_if_hard_path(argument))
- {
- strxmov(buff, opt_basedir, argument, NullS);
- argument= buff;
- }
- fn_format(buff, argument, "", "", 4);
- timer_file= buff;
- unlink(timer_file); /* Ignore error, may not exist */
- break;
+ strxmov(buff, opt_basedir, argument, NullS);
+ argument= buff;
}
+ fn_format(buff, argument, "", "", MY_UNPACK_FILENAME);
+ timer_file= buff;
+ unlink(timer_file); /* Ignore error, may not exist */
+ break;
+ }
case 'p':
if (argument)
{
@@ -3137,7 +4055,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
embedded_server_arg_count=1;
embedded_server_args[0]= (char*) "";
}
- if (embedded_server_arg_count == MAX_SERVER_ARGS-1 ||
+ if (embedded_server_arg_count == MAX_EMBEDDED_SERVER_ARGS-1 ||
!(embedded_server_args[embedded_server_arg_count++]=
my_strdup(argument, MYF(MY_FAE))))
{
@@ -3145,8 +4063,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
break;
case 'F':
- if (read_server_arguments(argument))
- die(NullS);
+ read_embedded_server_arguments(argument);
break;
case OPT_SKIP_SAFEMALLOC:
#ifdef SAFEMALLOC
@@ -3187,16 +4104,16 @@ int parse_args(int argc, char **argv)
/*
- Write the content of str into file
+ Write the content of str into file
- SYNOPSIS
- str_to_file
- fname - name of file to truncate/create and write to
- str - content to write to file
- size - size of content witten to file
+ SYNOPSIS
+ str_to_file
+ fname - name of file to truncate/create and write to
+ str - content to write to file
+ size - size of content witten to file
*/
-static void str_to_file(const char *fname, char *str, int size)
+void str_to_file(const char *fname, char *str, int size)
{
int fd;
char buff[FN_REFLEN];
@@ -3205,10 +4122,10 @@ static void str_to_file(const char *fname, char *str, int size)
strxmov(buff, opt_basedir, fname, NullS);
fname= buff;
}
- fn_format(buff,fname,"","",4);
+ fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
if ((fd= my_open(buff, O_WRONLY | O_CREAT | O_TRUNC,
- MYF(MY_WME | MY_FFNF))) < 0)
+ MYF(MY_WME | MY_FFNF))) < 0)
die("Could not open %s: errno = %d", buff, errno);
if (my_write(fd, (byte*)str, size, MYF(MY_WME|MY_FNABP)))
die("write failed");
@@ -3216,16 +4133,48 @@ static void str_to_file(const char *fname, char *str, int size)
}
-void dump_result_to_reject_file(const char *record_file, char *buf, int size)
+void dump_result_to_reject_file(char *buf, int size)
{
char reject_file[FN_REFLEN];
- str_to_file(fn_format(reject_file, record_file,"",".reject",2), buf, size);
+ str_to_file(fn_format(reject_file, result_file_name, "", ".reject",
+ MY_REPLACE_EXT),
+ buf, size);
}
-void dump_result_to_log_file(const char *record_file, char *buf, int size)
+void dump_result_to_log_file(char *buf, int size)
{
char log_file[FN_REFLEN];
- str_to_file(fn_format(log_file, record_file,"",".log",2), buf, size);
+ str_to_file(fn_format(log_file, result_file_name, "", ".log",
+ MY_REPLACE_EXT),
+ buf, size);
+}
+
+void dump_progress(void)
+{
+ char log_file[FN_REFLEN];
+ str_to_file(fn_format(log_file, result_file_name, "", ".progress",
+ MY_REPLACE_EXT),
+ ds_progress.str, ds_progress.length);
+}
+
+void dump_warning_messages(void)
+{
+ char warn_file[FN_REFLEN];
+
+ str_to_file(fn_format(warn_file, result_file_name, "", ".warnings",
+ MY_REPLACE_EXT),
+ ds_warning_messages.str, ds_warning_messages.length);
+}
+
+void check_regerr(my_regex_t* r, int err)
+{
+ char err_buf[1024];
+
+ if (err)
+ {
+ my_regerror(err,r,err_buf,sizeof(err_buf));
+ die("Regex error: %s\n", err_buf);
+ }
}
@@ -3237,12 +4186,12 @@ DYNAMIC_ARRAY patterns;
init_win_path_patterns
DESCRIPTION
- Setup string patterns that will be used to detect filenames that
- needs to be converted from Win to Unix format
+ Setup string patterns that will be used to detect filenames that
+ needs to be converted from Win to Unix format
*/
-static void init_win_path_patterns()
+void init_win_path_patterns()
{
/* List of string patterns to match in order to find paths */
const char* paths[] = { "$MYSQL_TEST_DIR",
@@ -3269,7 +4218,7 @@ static void init_win_path_patterns()
p= my_strdup(paths[i], MYF(MY_FAE));
if (insert_dynamic(&patterns, (gptr) &p))
- die(NullS);
+ die(NullS);
DBUG_PRINT("info", ("p: %s", p));
while (*p)
@@ -3282,7 +4231,7 @@ static void init_win_path_patterns()
DBUG_VOID_RETURN;
}
-static void free_win_path_patterns()
+void free_win_path_patterns()
{
uint i= 0;
for (i=0 ; i < patterns.elements ; i++)
@@ -3297,17 +4246,17 @@ static void free_win_path_patterns()
fix_win_paths
DESCRIPTION
- Search the string 'val' for the patterns that are known to be
- strings that contain filenames. Convert all \ to / in the
- filenames that are found.
-
- Ex:
- val = 'Error "c:\mysql\mysql-test\var\test\t1.frm" didn't exist'
- => $MYSQL_TEST_DIR is found by strstr
- => all \ from c:\mysql\m... until next space is converted into /
+ Search the string 'val' for the patterns that are known to be
+ strings that contain filenames. Convert all \ to / in the
+ filenames that are found.
+
+ Ex:
+ val = 'Error "c:\mysql\mysql-test\var\test\t1.frm" didn't exist'
+ => $MYSQL_TEST_DIR is found by strstr
+ => all \ from c:\mysql\m... until next space is converted into /
*/
-static void fix_win_paths(const char* val, int len)
+void fix_win_paths(const char *val, int len)
{
uint i;
char *p;
@@ -3317,6 +4266,7 @@ static void fix_win_paths(const char* val, int len)
{
const char** pattern= dynamic_element(&patterns, i, const char**);
DBUG_PRINT("info", ("pattern: %s", *pattern));
+ if (strlen(*pattern) == 0) continue;
/* Search for the path in string */
while ((p= strstr(val, *pattern)))
{
@@ -3336,34 +4286,14 @@ static void fix_win_paths(const char* val, int len)
}
#endif
-/* Append the string to ds, with optional replace */
-static void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
- const char *val, int len)
-{
-#ifdef __WIN__
- fix_win_paths(val, len);
-#endif
-
- if (glob_replace)
- replace_strings_append(glob_replace, ds, val, len);
- else
- dynstr_append_mem(ds, val, len);
-}
-
-
-/* Append zero-terminated string to ds, with optional replace */
-static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
-{
- replace_dynstr_append_mem(ds, val, strlen(val));
-}
/*
Append the result for one field to the dynamic string ds
*/
-static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
- const char* val, ulonglong len, bool is_null)
+void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
+ const char* val, ulonglong len, bool is_null)
{
if (col_idx < max_replace_column && replace_column[col_idx])
{
@@ -3414,7 +4344,7 @@ static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field,
Values may be converted with 'replace_column'
*/
-static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
+void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
{
MYSQL_ROW row;
uint num_fields= mysql_num_fields(res);
@@ -3431,7 +4361,6 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
if (!display_result_vertically)
dynstr_append_mem(ds, "\n", 1);
}
- free_replace_column();
}
@@ -3440,8 +4369,8 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
with '\t'. Values may be converted with 'replace_column'
*/
-static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
- MYSQL_FIELD *fields, uint num_fields)
+void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
+ MYSQL_FIELD *fields, uint num_fields)
{
MYSQL_BIND *bind;
my_bool *is_null;
@@ -3466,7 +4395,7 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
bind[i].is_null= &is_null[i];
bind[i].length= &length[i];
- DBUG_PRINT("bind", ("col[%d]: buffer_type: %d, buffer_length: %d",
+ DBUG_PRINT("bind", ("col[%d]: buffer_type: %d, buffer_length: %lu",
i, bind[i].buffer_type, bind[i].buffer_length));
}
@@ -3487,8 +4416,6 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
- free_replace_column();
-
for (i= 0; i < num_fields; i++)
{
/* Free data for output */
@@ -3505,9 +4432,9 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
Append metadata for fields to output
*/
-static void append_metadata(DYNAMIC_STRING *ds,
- MYSQL_FIELD *field,
- uint num_fields)
+void append_metadata(DYNAMIC_STRING *ds,
+ MYSQL_FIELD *field,
+ uint num_fields)
{
MYSQL_FIELD *field_end;
dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
@@ -3518,44 +4445,36 @@ static void append_metadata(DYNAMIC_STRING *ds,
field < field_end ;
field++)
{
- char buff[22];
dynstr_append_mem(ds, field->catalog,
- field->catalog_length);
+ field->catalog_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->db, field->db_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->org_table,
- field->org_table_length);
+ field->org_table_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->table,
- field->table_length);
+ field->table_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->org_name,
- field->org_name_length);
+ field->org_name_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, field->name, field->name_length);
dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->type, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->type);
dynstr_append_mem(ds, "\t", 1);
- longlong10_to_str((unsigned int) field->length, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->length);
dynstr_append_mem(ds, "\t", 1);
- longlong10_to_str((unsigned int) field->max_length, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->max_length);
dynstr_append_mem(ds, "\t", 1);
dynstr_append_mem(ds, (char*) (IS_NOT_NULL(field->flags) ?
"N" : "Y"), 1);
dynstr_append_mem(ds, "\t", 1);
-
- int10_to_str((int) field->flags, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->flags);
dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->decimals, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->decimals);
dynstr_append_mem(ds, "\t", 1);
- int10_to_str((int) field->charsetnr, buff, 10);
- dynstr_append(ds, buff);
+ replace_dynstr_append_uint(ds, field->charsetnr);
dynstr_append_mem(ds, "\n", 1);
}
}
@@ -3565,11 +4484,11 @@ static void append_metadata(DYNAMIC_STRING *ds,
Append affected row count and other info to output
*/
-static void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows,
- const char *info)
+void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows,
+ const char *info)
{
- char buf[40];
- sprintf(buf,"affected rows: %llu\n", affected_rows);
+ char buf[40], buff2[21];
+ sprintf(buf,"affected rows: %s\n", llstr(affected_rows, buff2));
dynstr_append(ds, buf);
if (info)
{
@@ -3581,12 +4500,12 @@ static void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows,
/*
- Display the table headings with the names tab separated
+ Display the table headings with the names tab separated
*/
-static void append_table_headings(DYNAMIC_STRING *ds,
- MYSQL_FIELD *field,
- uint num_fields)
+void append_table_headings(DYNAMIC_STRING *ds,
+ MYSQL_FIELD *field,
+ uint num_fields)
{
uint col_idx;
for (col_idx= 0; col_idx < num_fields; col_idx++)
@@ -3602,10 +4521,10 @@ static void append_table_headings(DYNAMIC_STRING *ds,
Fetch warnings from server and append to ds
RETURN VALUE
- Number of warnings appended to ds
+ Number of warnings appended to ds
*/
-static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
+int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
{
uint count;
MYSQL_RES *warn_res;
@@ -3653,9 +4572,9 @@ static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql)
error - function will not return
*/
-static void run_query_normal(struct connection *cn, struct st_query *command,
- int flags, char *query, int query_len,
- DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
+void run_query_normal(struct st_connection *cn, struct st_command *command,
+ int flags, char *query, int query_len,
+ DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings)
{
MYSQL_RES *res= 0;
MYSQL *mysql= &cn->mysql;
@@ -3664,14 +4583,14 @@ static void run_query_normal(struct connection *cn, struct st_query *command,
DBUG_PRINT("enter",("flags: %d", flags));
DBUG_PRINT("enter", ("query: '%-.60s'", query));
- if (flags & QUERY_SEND)
+ if (flags & QUERY_SEND_FLAG)
{
/*
- Send the query
- */
+ Send the query
+ */
if (do_send_query(cn, query, query_len, flags))
{
- handle_error(query, command, mysql_errno(mysql), mysql_error(mysql),
+ handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
@@ -3681,7 +4600,7 @@ static void run_query_normal(struct connection *cn, struct st_query *command,
Here we handle 'reap' command, so we need to check if the
query's thread was finished and probably wait
*/
- else if (flags & QUERY_REAP)
+ else if (flags & QUERY_REAP_FLAG)
{
pthread_mutex_lock(&cn->mutex);
while (!cn->query_done)
@@ -3689,8 +4608,7 @@ static void run_query_normal(struct connection *cn, struct st_query *command,
pthread_mutex_unlock(&cn->mutex);
}
#endif /*EMBEDDED_LIBRARY*/
-
- if (!(flags & QUERY_REAP))
+ if (!(flags & QUERY_REAP_FLAG))
DBUG_VOID_RETURN;
do
@@ -3698,22 +4616,22 @@ static void run_query_normal(struct connection *cn, struct st_query *command,
/*
When on first result set, call mysql_read_query_result to retrieve
answer to the query sent earlier
- */
+ */
if ((counter==0) && mysql_read_query_result(mysql))
{
- handle_error(query, command, mysql_errno(mysql), mysql_error(mysql),
+ handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
/*
- Store the result. If res is NULL, use mysql_field_count to
- determine if that was expected
- */
+ Store the result. If res is NULL, use mysql_field_count to
+ determine if that was expected
+ */
if (!(res= mysql_store_result(mysql)) && mysql_field_count(mysql))
{
- handle_error(query, command, mysql_errno(mysql), mysql_error(mysql),
+ handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
@@ -3769,7 +4687,7 @@ static void run_query_normal(struct connection *cn, struct st_query *command,
if (err > 0)
{
/* We got an error from mysql_next_result, maybe expected */
- handle_error(query, command, mysql_errno(mysql), mysql_error(mysql),
+ handle_error(command, mysql_errno(mysql), mysql_error(mysql),
mysql_sqlstate(mysql), ds);
goto end;
}
@@ -3779,7 +4697,6 @@ static void run_query_normal(struct connection *cn, struct st_query *command,
handle_no_error(command);
end:
- free_replace();
/*
We save the return code (mysql_errno(mysql)) from the last call sent
@@ -3795,56 +4712,62 @@ end:
Handle errors which occurred during execution
SYNOPSIS
- handle_error()
- query - query string
- q - query context
- err_errno - error number
- err_error - error message
- err_sqlstate - sql state
- ds - dynamic string which is used for output buffer
+ handle_error()
+ q - query context
+ err_errno - error number
+ err_error - error message
+ err_sqlstate - sql state
+ ds - dynamic string which is used for output buffer
NOTE
- If there is an unexpected error this function will abort mysqltest
- immediately.
+ If there is an unexpected error this function will abort mysqltest
+ immediately.
RETURN VALUE
- error - function will not return
+ error - function will not return
*/
-static void handle_error(const char *query, struct st_query *q,
- unsigned int err_errno, const char *err_error,
- const char *err_sqlstate, DYNAMIC_STRING *ds)
+void handle_error(struct st_command *command,
+ unsigned int err_errno, const char *err_error,
+ const char *err_sqlstate, DYNAMIC_STRING *ds)
{
uint i;
DBUG_ENTER("handle_error");
- if (q->require_file)
+ if (command->require_file[0])
{
/*
The query after a "--require" failed. This is fine as long the server
returned a valid reponse. Don't allow 2013 or 2006 to trigger an
abort_not_supported_test
- */
+ */
if (err_errno == CR_SERVER_LOST ||
err_errno == CR_SERVER_GONE_ERROR)
- die("require query '%s' failed: %d: %s", query, err_errno, err_error);
- abort_not_supported_test();
+ die("require query '%s' failed: %d: %s", command->query,
+ err_errno, err_error);
+
+ /* Abort the run of this test, pass the failed query as reason */
+ abort_not_supported_test("Query '%s' failed, required functionality" \
+ "not supported", command->query);
}
- if (q->abort_on_error)
- die("query '%s' failed: %d: %s", query, err_errno, err_error);
+ if (command->abort_on_error)
+ die("query '%s' failed: %d: %s", command->query, err_errno, err_error);
- for (i= 0 ; (uint) i < q->expected_errors ; i++)
+ DBUG_PRINT("info", ("expected_errors.count: %d",
+ command->expected_errors.count));
+ for (i= 0 ; (uint) i < command->expected_errors.count ; i++)
{
- if (((q->expected_errno[i].type == ERR_ERRNO) &&
- (q->expected_errno[i].code.errnum == err_errno)) ||
- ((q->expected_errno[i].type == ERR_SQLSTATE) &&
- (strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0)))
+ if (((command->expected_errors.err[i].type == ERR_ERRNO) &&
+ (command->expected_errors.err[i].code.errnum == err_errno)) ||
+ ((command->expected_errors.err[i].type == ERR_SQLSTATE) &&
+ (strncmp(command->expected_errors.err[i].code.sqlstate,
+ err_sqlstate, SQLSTATE_LENGTH) == 0)))
{
if (!disable_result_log)
{
- if (q->expected_errors == 1)
+ if (command->expected_errors.count == 1)
{
/* Only log error if there is one possible error */
dynstr_append_mem(ds, "ERROR ", 6);
@@ -3854,9 +4777,9 @@ static void handle_error(const char *query, struct st_query *q,
dynstr_append_mem(ds,"\n",1);
}
/* Don't log error if we may not get an error */
- else if (q->expected_errno[0].type == ERR_SQLSTATE ||
- (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0))
+ else if (command->expected_errors.err[0].type == ERR_SQLSTATE ||
+ (command->expected_errors.err[0].type == ERR_ERRNO &&
+ command->expected_errors.err[0].code.errnum != 0))
dynstr_append(ds,"Got one of the listed errors\n");
}
/* OK */
@@ -3864,7 +4787,8 @@ static void handle_error(const char *query, struct st_query *q,
}
}
- DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors));
+ DBUG_PRINT("info",("i: %d expected_errors: %d", i,
+ command->expected_errors.count));
if (!disable_result_log)
{
@@ -3877,13 +4801,14 @@ static void handle_error(const char *query, struct st_query *q,
if (i)
{
- if (q->expected_errno[0].type == ERR_ERRNO)
+ if (command->expected_errors.err[0].type == ERR_ERRNO)
die("query '%s' failed with wrong errno %d: '%s', instead of %d...",
- q->query, err_errno, err_error, q->expected_errno[0].code.errnum);
+ command->query, err_errno, err_error,
+ command->expected_errors.err[0].code.errnum);
else
die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...",
- q->query, err_sqlstate, err_error,
- q->expected_errno[0].code.sqlstate);
+ command->query, err_sqlstate, err_error,
+ command->expected_errors.err[0].code.sqlstate);
}
DBUG_VOID_RETURN;
@@ -3894,30 +4819,30 @@ static void handle_error(const char *query, struct st_query *q,
Handle absence of errors after execution
SYNOPSIS
- handle_no_error()
- q - context of query
+ handle_no_error()
+ q - context of query
RETURN VALUE
- error - function will not return
+ error - function will not return
*/
-static void handle_no_error(struct st_query *q)
+void handle_no_error(struct st_command *command)
{
DBUG_ENTER("handle_no_error");
- if (q->expected_errno[0].type == ERR_ERRNO &&
- q->expected_errno[0].code.errnum != 0)
+ if (command->expected_errors.err[0].type == ERR_ERRNO &&
+ command->expected_errors.err[0].code.errnum != 0)
{
/* Error code we wanted was != 0, i.e. not an expected success */
die("query '%s' succeeded - should have failed with errno %d...",
- q->query, q->expected_errno[0].code.errnum);
+ command->query, command->expected_errors.err[0].code.errnum);
}
- else if (q->expected_errno[0].type == ERR_SQLSTATE &&
- strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
+ else if (command->expected_errors.err[0].type == ERR_SQLSTATE &&
+ strcmp(command->expected_errors.err[0].code.sqlstate,"00000") != 0)
{
/* SQLSTATE we wanted was != "00000", i.e. not an expected success */
die("query '%s' succeeded - should have failed with sqlstate %s...",
- q->query, q->expected_errno[0].code.sqlstate);
+ command->query, command->expected_errors.err[0].code.sqlstate);
}
DBUG_VOID_RETURN;
@@ -3939,9 +4864,9 @@ static void handle_no_error(struct st_query *q)
error - function will not return
*/
-static void run_query_stmt(MYSQL *mysql, struct st_query *command,
- char *query, int query_len, DYNAMIC_STRING *ds,
- DYNAMIC_STRING *ds_warnings)
+void run_query_stmt(MYSQL *mysql, struct st_command *command,
+ char *query, int query_len, DYNAMIC_STRING *ds,
+ DYNAMIC_STRING *ds_warnings)
{
MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */
MYSQL_STMT *stmt;
@@ -3972,7 +4897,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
*/
if (mysql_stmt_prepare(stmt, query, query_len))
{
- handle_error(query, command, mysql_stmt_errno(stmt),
+ handle_error(command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end;
}
@@ -3989,6 +4914,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
parameter markers.
*/
+#if MYSQL_VERSION_ID >= 50000
if (cursor_protocol_enabled)
{
/*
@@ -3999,13 +4925,14 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
}
+#endif
/*
Execute the query
*/
if (mysql_stmt_execute(stmt))
{
- handle_error(query, command, mysql_stmt_errno(stmt),
+ handle_error(command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end;
}
@@ -4019,8 +4946,8 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
/*
We instruct that we want to update the "max_length" field in
- mysql_stmt_store_result(), this is our only way to know how much
- buffer to allocate for result data
+ mysql_stmt_store_result(), this is our only way to know how much
+ buffer to allocate for result data
*/
{
my_bool one= 1;
@@ -4035,7 +4962,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
*/
if (mysql_stmt_store_result(stmt))
{
- handle_error(query, command, mysql_stmt_errno(stmt),
+ handle_error(command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end;
}
@@ -4105,8 +5032,6 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
}
end:
- free_replace();
-
if (!disable_warnings)
{
dynstr_free(&ds_prepare_warnings);
@@ -4118,6 +5043,7 @@ end:
to the server into the mysqltest builtin variable $mysql_errno. This
variable then can be used from the test case itself.
*/
+
var_set_errno(mysql_stmt_errno(stmt));
#ifndef BUG15518_FIXED
mysql_stmt_close(stmt);
@@ -4135,7 +5061,7 @@ end:
as view, sp etc.
*/
-static int util_query(MYSQL* org_mysql, const char* query){
+int util_query(MYSQL* org_mysql, const char* query){
MYSQL* mysql;
DBUG_ENTER("util_query");
@@ -4146,11 +5072,9 @@ static int util_query(MYSQL* org_mysql, const char* query){
if (!(mysql= mysql_init(mysql)))
die("Failed in mysql_init()");
- if (safe_connect(mysql, org_mysql->host, org_mysql->user,
- org_mysql->passwd, org_mysql->db, org_mysql->port,
- org_mysql->unix_socket))
- die("Could not open util connection: %d %s",
- mysql_errno(mysql), mysql_error(mysql));
+ safe_connect(mysql, "util", org_mysql->host, org_mysql->user,
+ org_mysql->passwd, org_mysql->db, org_mysql->port,
+ org_mysql->unix_socket);
cur_con->util_mysql= mysql;
}
@@ -4164,8 +5088,8 @@ static int util_query(MYSQL* org_mysql, const char* query){
Run query
flags control the phased/stages of query execution to be performed
- if QUERY_SEND bit is on, the query will be sent. If QUERY_REAP is on
- the result will be read - for regular query, both bits must be on
+ if QUERY_SEND_FLAG bit is on, the query will be sent. If QUERY_REAP_FLAG
+ is on the result will be read - for regular query, both bits must be on
SYNPOSIS
run_query
@@ -4174,8 +5098,7 @@ static int util_query(MYSQL* org_mysql, const char* query){
*/
-static void run_query(struct connection *cn, struct st_query *command,
- int flags)
+void run_query(struct st_connection *cn, struct st_command *command, int flags)
{
MYSQL *mysql= &cn->mysql;
DYNAMIC_STRING *ds;
@@ -4185,17 +5108,21 @@ static void run_query(struct connection *cn, struct st_query *command,
char *query;
int query_len;
my_bool view_created= 0, sp_created= 0;
- my_bool complete_query= ((flags & QUERY_SEND) && (flags & QUERY_REAP));
+ my_bool complete_query= ((flags & QUERY_SEND_FLAG) &&
+ (flags & QUERY_REAP_FLAG));
init_dynamic_string(&ds_warnings, NULL, 0, 256);
+ /* Scan for warning before sendign to server */
+ scan_command_for_warnings(command);
+
/*
Evaluate query if this is an eval command
- */
+ */
if (command->type == Q_EVAL)
{
- init_dynamic_string(&eval_query, "", 16384, 65536);
- do_eval(&eval_query, command->query, FALSE);
+ init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
+ do_eval(&eval_query, command->query, command->end, FALSE);
query = eval_query.str;
query_len = eval_query.length;
}
@@ -4206,23 +5133,23 @@ static void run_query(struct connection *cn, struct st_query *command,
}
/*
- When command->record_file is set the output of _this_ query
+ When command->require_file is set the output of _this_ query
should be compared with an already existing file
Create a temporary dynamic string to contain the output from
this query.
- */
- if (command->record_file[0])
+ */
+ if (command->require_file[0])
{
- init_dynamic_string(&ds_result, "", 16384, 65536);
+ init_dynamic_string(&ds_result, "", 1024, 1024);
ds= &ds_result;
}
else
ds= &ds_res;
/*
- Log the query into the output buffer
+ Log the query into the output buffer
*/
- if (!disable_query_log && (flags & QUERY_SEND))
+ if (!disable_query_log && (flags & QUERY_SEND_FLAG))
{
replace_dynstr_append_mem(ds, query, query_len);
dynstr_append_mem(ds, delimiter, delimiter_length);
@@ -4234,8 +5161,8 @@ static void run_query(struct connection *cn, struct st_query *command,
match_re(&view_re, query))
{
/*
- Create the query as a view.
- Use replace since view can exist from a failed mysqltest run
+ Create the query as a view.
+ Use replace since view can exist from a failed mysqltest run
*/
DYNAMIC_STRING query_str;
init_dynamic_string(&query_str,
@@ -4247,7 +5174,7 @@ static void run_query(struct connection *cn, struct st_query *command,
/*
Failed to create the view, this is not fatal
just run the query the normal way
- */
+ */
DBUG_PRINT("view_create_error",
("Failed to create view '%s': %d: %s", query_str.str,
mysql_errno(mysql), mysql_error(mysql)));
@@ -4260,14 +5187,14 @@ static void run_query(struct connection *cn, struct st_query *command,
{
/*
Yes, it was possible to create this query as a view
- */
+ */
view_created= 1;
query= (char*)"SELECT * FROM mysqltest_tmp_v";
query_len = strlen(query);
/*
- Collect warnings from create of the view that should otherwise
- have been produced when the SELECT was executed
+ Collect warnings from create of the view that should otherwise
+ have been produced when the SELECT was executed
*/
append_warnings(&ds_warnings, cur_con->util_mysql);
}
@@ -4346,26 +5273,14 @@ static void run_query(struct connection *cn, struct st_query *command,
mysql_errno(mysql), mysql_error(mysql));
}
- if (command->record_file[0])
+ if (command->require_file[0])
{
- /* A result file was specified for _this_ query */
- if (record)
- {
- /*
- Recording in progress
- Dump the output from _this_ query to the specified record_file
- */
- str_to_file(command->record_file, ds->str, ds->length);
-
- } else {
-
- /*
- The output from _this_ query should be checked against an already
- existing file which has been specified using --require or --result
- */
- check_result(ds, command->record_file, command->require_file);
- }
+ /* A result file was specified for _this_ query
+ and the output should be checked against an already
+ existing file which has been specified using --require or --result
+ */
+ check_require(ds, command->require_file);
}
dynstr_free(&ds_warnings);
@@ -4375,12 +5290,12 @@ static void run_query(struct connection *cn, struct st_query *command,
dynstr_free(&eval_query);
}
+/****************************************************************************/
+/*
+ Functions to detect different SQL statements
+*/
-/****************************************************************************\
- * Functions to detect different SQL statements
-\****************************************************************************/
-
-static char *re_eprint(int err)
+char *re_eprint(int err)
{
static char epbuf[100];
size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL,
@@ -4389,7 +5304,7 @@ static char *re_eprint(int err)
return(epbuf);
}
-static void init_re_comp(my_regex_t *re, const char* str)
+void init_re_comp(my_regex_t *re, const char* str)
{
int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB),
&my_charset_latin1);
@@ -4402,11 +5317,11 @@ static void init_re_comp(my_regex_t *re, const char* str)
}
}
-static void init_re(void)
+void init_re(void)
{
/*
- Filter for queries that can be run using the
- MySQL Prepared Statements C API
+ Filter for queries that can be run using the
+ MySQL Prepared Statements C API
*/
const char *ps_re_str =
"^("
@@ -4423,13 +5338,13 @@ static void init_re(void)
"[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])";
/*
- Filter for queries that can be run using the
- Stored procedures
+ Filter for queries that can be run using the
+ Stored procedures
*/
const char *sp_re_str =ps_re_str;
/*
- Filter for queries that can be run as views
+ Filter for queries that can be run as views
*/
const char *view_re_str =
"^("
@@ -4441,7 +5356,7 @@ static void init_re(void)
}
-static int match_re(my_regex_t *re, char *str)
+int match_re(my_regex_t *re, char *str)
{
int err= my_regexec(re, str, (size_t)0, NULL, 0);
@@ -4459,7 +5374,7 @@ static int match_re(my_regex_t *re, char *str)
return 0;
}
-static void free_re(void)
+void free_re(void)
{
my_regfree(&ps_re);
my_regfree(&sp_re);
@@ -4469,207 +5384,186 @@ static void free_re(void)
/****************************************************************************/
-void get_query_type(struct st_query* q)
+void get_command_type(struct st_command* command)
{
char save;
uint type;
- DBUG_ENTER("get_query_type");
+ DBUG_ENTER("get_command_type");
- if (!parsing_disabled && *q->query == '}')
+ if (*command->query == '}')
{
- q->type = Q_END_BLOCK;
+ command->type = Q_END_BLOCK;
DBUG_VOID_RETURN;
}
- if (q->type != Q_COMMENT_WITH_COMMAND)
- q->type= parsing_disabled ? Q_COMMENT : Q_QUERY;
- save=q->query[q->first_word_len];
- q->query[q->first_word_len]=0;
- type=find_type(q->query, &command_typelib, 1+2);
- q->query[q->first_word_len]=save;
+ save= command->query[command->first_word_len];
+ command->query[command->first_word_len]= 0;
+ type= find_type(command->query, &command_typelib, 1+2);
+ command->query[command->first_word_len]= save;
if (type > 0)
{
- q->type=(enum enum_commands) type; /* Found command */
+ command->type=(enum enum_commands) type; /* Found command */
+
/*
- If queries are disabled, only recognize
- --enable_parsing and --disable_parsing
+ Look for case where "query" was explicitly specified to
+ force command being sent to server
*/
- if (parsing_disabled && q->type != Q_ENABLE_PARSING &&
- q->type != Q_DISABLE_PARSING)
- q->type= Q_COMMENT;
+ if (type == Q_QUERY)
+ {
+ /* Skip the "query" part */
+ command->query= command->first_argument;
+ }
}
- else if (q->type == Q_COMMENT_WITH_COMMAND &&
- q->first_word_len &&
- q->query[q->first_word_len-1] == ';')
+ else
{
- /*
- Detect comment with command using extra delimiter
- Ex --disable_query_log;
- ^ Extra delimiter causing the command
- to be skipped
- */
- save= q->query[q->first_word_len-1];
- q->query[q->first_word_len-1]= 0;
- type= find_type(q->query, &command_typelib, 1+2);
- q->query[q->first_word_len-1]= save;
- if (type > 0)
- die("Extra delimiter \";\" found");
- }
- DBUG_VOID_RETURN;
-}
+ /* No mysqltest command matched */
+ if (command->type != Q_COMMENT_WITH_COMMAND)
+ {
+ /* A query that will sent to mysqld */
+ command->type= Q_QUERY;
+ }
+ else
+ {
+ /* -- comment that didn't contain a mysqltest command */
+ command->type= Q_COMMENT;
+ warning_msg("Suspicious command '--%s' detected, was this intentional? "\
+ "Use # instead of -- to avoid this warning",
+ command->query);
+
+ if (command->first_word_len &&
+ strcmp(command->query + command->first_word_len - 1, delimiter) == 0)
+ {
+ /*
+ Detect comment with command using extra delimiter
+ Ex --disable_query_log;
+ ^ Extra delimiter causing the command
+ to be skipped
+ */
+ save= command->query[command->first_word_len-1];
+ command->query[command->first_word_len-1]= 0;
+ if (find_type(command->query, &command_typelib, 1+2) > 0)
+ die("Extra delimiter \";\" found");
+ command->query[command->first_word_len-1]= save;
-static byte *get_var_key(const byte* var, uint* len,
- my_bool __attribute__((unused)) t)
-{
- register char* key;
- key = ((VAR*)var)->name;
- *len = ((VAR*)var)->name_len;
- return (byte*)key;
-}
-
-static VAR *var_init(VAR *v, const char *name, int name_len, const char *val,
- int val_len)
-{
- int val_alloc_len;
- VAR *tmp_var;
- if (!name_len && name)
- name_len = strlen(name);
- if (!val_len && val)
- val_len = strlen(val) ;
- val_alloc_len = val_len + 16; /* room to grow */
- if (!(tmp_var=v) && !(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
- + name_len+1, MYF(MY_WME))))
- die("Out of memory");
-
- tmp_var->name = (name) ? (char*) tmp_var + sizeof(*tmp_var) : 0;
- tmp_var->alloced = (v == 0);
+ }
+ }
+ }
- if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME))))
- die("Out of memory");
+ /* Set expected error on command */
+ memcpy(&command->expected_errors, &saved_expected_errors,
+ sizeof(saved_expected_errors));
+ DBUG_PRINT("info", ("There are %d expected errors",
+ command->expected_errors.count));
+ command->abort_on_error= (command->expected_errors.count == 0 &&
+ abort_on_error);
- if (name)
- strmake(tmp_var->name, name, name_len);
- if (val)
- strmake(tmp_var->str_val, val, val_len);
- tmp_var->name_len = name_len;
- tmp_var->str_val_len = val_len;
- tmp_var->alloced_len = val_alloc_len;
- tmp_var->int_val = (val) ? atoi(val) : 0;
- tmp_var->int_dirty = 0;
- return tmp_var;
+ DBUG_VOID_RETURN;
}
-static void var_free(void *v)
-{
- my_free(((VAR*) v)->str_val, MYF(MY_WME));
- if (((VAR*)v)->alloced)
- my_free((char*) v, MYF(MY_WME));
-}
-static VAR* var_from_env(const char *name, const char *def_val)
-{
- const char *tmp;
- VAR *v;
- if (!(tmp = getenv(name)))
- tmp = def_val;
+/*
+ Record how many milliseconds it took to execute the test file
+ up until the current line and save it in the dynamic string ds_progress.
- v = var_init(0, name, strlen(name), tmp, strlen(tmp));
- my_hash_insert(&var_hash, (byte*)v);
- return v;
-}
+ The ds_progress will be dumped to <test_name>.progress when
+ test run completes
+*/
-static void init_var_hash(MYSQL *mysql)
+void mark_progress(struct st_command* command __attribute__((unused)),
+ int line)
{
- VAR *v;
- DBUG_ENTER("init_var_hash");
- if (hash_init(&var_hash, charset_info,
- 1024, 0, 0, get_var_key, var_free, MYF(0)))
- die("Variable hash initialization failed");
- my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0,
- (opt_big_test) ? "1" : "0", 0));
- v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0);
- my_hash_insert(&var_hash, (byte*) v);
- v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
- my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"DB", 2, db, 0);
- my_hash_insert(&var_hash, (byte*) v);
- DBUG_VOID_RETURN;
-}
+ char buf[32], *end;
+ ulonglong timer= timer_now();
+ if (!progress_start)
+ progress_start= timer;
+ timer-= progress_start;
-static void mark_progress(int line)
-{
-#ifdef NOT_YET
- static FILE* fp = NULL;
- static double first;
+ /* Milliseconds since start */
+ end= longlong2str(timer, buf, 10);
+ dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
+ dynstr_append_mem(&ds_progress, "\t", 1);
- struct timeval tv;
- double now;
+ /* Parser line number */
+ end= int10_to_str(line, buf, 10);
+ dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
+ dynstr_append_mem(&ds_progress, "\t", 1);
- if (!fp)
- {
+ /* Filename */
+ dynstr_append(&ds_progress, cur_file->file_name);
+ dynstr_append_mem(&ds_progress, ":", 1);
- fp = fopen("/tmp/mysqltest_progress.log", "wt");
+ /* Line in file */
+ end= int10_to_str(cur_file->lineno, buf, 10);
+ dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
- if (!fp)
- {
- abort();
- }
- gettimeofday(&tv, NULL);
- first = tv.tv_sec * 1e6 + tv.tv_usec;
- }
+ dynstr_append_mem(&ds_progress, "\n", 1);
- gettimeofday(&tv, NULL);
- now = tv.tv_sec * 1e6 + tv.tv_usec;
-
- fprintf(fp, "%d %f\n", parser.current_line, (now - first) / 1e6);
-#endif
}
+
int main(int argc, char **argv)
{
- struct st_query *q;
- my_bool require_file=0, q_send_flag=0, abort_flag= 0,
- query_executed= 0;
+ struct st_command *command;
+ my_bool q_send_flag= 0, abort_flag= 0;
+ uint command_executed= 0, last_command_executed= 0;
char save_file[FN_REFLEN];
MY_STAT res_info;
MY_INIT(argv[0]);
- /* Use all time until exit if no explicit 'start_timer' */
- timer_start= timer_now();
+ save_file[0]= 0;
+ TMPDIR[0]= 0;
- save_file[0]=0;
- TMPDIR[0]=0;
+ /* Init expected errors */
+ memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
- /* Init cons */
- memset(cons, 0, sizeof(cons));
- cons_end = cons + MAX_CONS;
- next_con = cons + 1;
- cur_con = cons;
+ /* Init connections */
+ memset(connections, 0, sizeof(connections));
+ connections_end= connections +
+ (sizeof(connections)/sizeof(struct st_connection)) - 1;
+ next_con= connections + 1;
+ cur_con= connections;
/* Init file stack */
memset(file_stack, 0, sizeof(file_stack));
- file_stack_end= file_stack + MAX_INCLUDE_DEPTH - 1;
+ file_stack_end=
+ file_stack + (sizeof(file_stack)/sizeof(struct st_test_file)) - 1;
cur_file= file_stack;
/* Init block stack */
memset(block_stack, 0, sizeof(block_stack));
- block_stack_end= block_stack + BLOCK_STACK_DEPTH - 1;
+ block_stack_end=
+ block_stack + (sizeof(block_stack)/sizeof(struct st_block)) - 1;
cur_block= block_stack;
cur_block->ok= TRUE; /* Outer block should always be executed */
cur_block->cmd= cmd_none;
- my_init_dynamic_array(&q_lines, sizeof(struct st_query*), INIT_Q_LINES,
- INIT_Q_LINES);
+ my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024);
+
+ if (hash_init(&var_hash, charset_info,
+ 1024, 0, 0, get_var_key, var_free, MYF(0)))
+ die("Variable hash initialization failed");
memset(&master_pos, 0, sizeof(master_pos));
- init_dynamic_string(&ds_res, "", 0, 65536);
+ parser.current_line= parser.read_lines= 0;
+ memset(&var_reg, 0, sizeof(var_reg));
+
+#ifdef __WIN__
+ init_tmp_sh_file();
+ init_win_path_patterns();
+#endif
+
+ init_dynamic_string(&ds_res, "", 65536, 65536);
+ init_dynamic_string(&ds_progress, "", 0, 2048);
+ init_dynamic_string(&ds_warning_messages, "", 0, 2048);
parse_args(argc, argv);
- DBUG_PRINT("info",("result_file: '%s'", result_file ? result_file : ""));
+ DBUG_PRINT("info",("result_file: '%s'",
+ result_file_name ? result_file_name : ""));
if (mysql_server_init(embedded_server_arg_count,
embedded_server_args,
(char**) embedded_server_groups))
@@ -4680,10 +5574,6 @@ int main(int argc, char **argv)
cur_file->file_name= my_strdup("<stdin>", MYF(MY_WME));
cur_file->lineno= 1;
}
-#ifndef EMBEDDED_LIBRARY
- if (manager_host)
- init_manager();
-#endif
init_re();
ps_protocol_enabled= ps_protocol;
sp_protocol_enabled= sp_protocol;
@@ -4698,32 +5588,37 @@ int main(int argc, char **argv)
if (opt_compress)
mysql_options(&cur_con->mysql,MYSQL_OPT_COMPRESS,NullS);
mysql_options(&cur_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
- mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name);
+ mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_NAME,
+ charset_info->csname);
+ if (opt_charsets_dir)
+ mysql_options(&cur_con->mysql, MYSQL_SET_CHARSET_DIR,
+ opt_charsets_dir);
#ifdef HAVE_OPENSSL
+
+#if MYSQL_VERSION_ID >= 50000
opt_ssl_verify_server_cert= TRUE; /* Always on in mysqltest */
+#endif
+
if (opt_use_ssl)
{
mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
+#if MYSQL_VERSION_ID >= 50000
mysql_options(&cur_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
+#endif
}
#endif
if (!(cur_con->name = my_strdup("default", MYF(MY_WME))))
die("Out of memory");
- if (safe_connect(&cur_con->mysql, host, user, pass, db, port, unix_sock))
- die("Could not open connection '%s': %d %s", cur_con->name,
- mysql_errno(&cur_con->mysql), mysql_error(&cur_con->mysql));
-
- init_var_hash(&cur_con->mysql);
+ safe_connect(&cur_con->mysql, cur_con->name, host, user, pass,
+ db, port, unix_sock);
-#ifdef __WIN__
- init_tmp_sh_file();
- init_win_path_patterns();
-#endif
+ /* Use all time until exit if no explicit 'start_timer' */
+ timer_start= timer_now();
/*
Initialize $mysql_errno with -1, so we can
@@ -4732,26 +5627,40 @@ int main(int argc, char **argv)
*/
var_set_errno(-1);
- while (!abort_flag && !read_query(&q))
+ if (opt_include)
+ {
+ open_file(opt_include);
+ }
+
+ while (!read_command(&command) && !abort_flag)
{
int current_line_inc = 1, processed = 0;
- if (q->type == Q_UNKNOWN || q->type == Q_COMMENT_WITH_COMMAND)
- get_query_type(q);
+ if (command->type == Q_UNKNOWN || command->type == Q_COMMENT_WITH_COMMAND)
+ get_command_type(command);
+
+ if (parsing_disabled &&
+ command->type != Q_ENABLE_PARSING &&
+ command->type != Q_DISABLE_PARSING)
+ {
+ command->type= Q_COMMENT;
+ scan_command_for_warnings(command);
+ }
+
if (cur_block->ok)
{
- q->last_argument= q->first_argument;
+ command->last_argument= command->first_argument;
processed = 1;
- switch (q->type) {
+ switch (command->type) {
case Q_CONNECT:
- do_connect(q);
+ do_connect(command);
break;
- case Q_CONNECTION: select_connection(q); break;
+ case Q_CONNECTION: select_connection(command); break;
case Q_DISCONNECT:
case Q_DIRTY_CLOSE:
- close_connection(q); break;
- case Q_RPL_PROBE: do_rpl_probe(q); break;
- case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break;
- case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
+ do_close_connection(command); break;
+ case Q_RPL_PROBE: do_rpl_probe(command); break;
+ case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(command); break;
+ case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(command); break;
case Q_ENABLE_QUERY_LOG: disable_query_log=0; break;
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break;
@@ -4766,23 +5675,21 @@ int main(int argc, char **argv)
case Q_DISABLE_INFO: disable_info=1; break;
case Q_ENABLE_METADATA: display_metadata=1; break;
case Q_DISABLE_METADATA: display_metadata=0; break;
- case Q_SOURCE: do_source(q); break;
- case Q_SLEEP: do_sleep(q, 0); break;
- case Q_REAL_SLEEP: do_sleep(q, 1); break;
- case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(q); break;
- case Q_REQUIRE_MANAGER: do_require_manager(q); break;
-#ifndef EMBEDDED_LIBRARY
- case Q_SERVER_START: do_server_start(q); break;
- case Q_SERVER_STOP: do_server_stop(q); break;
-#endif
- case Q_INC: do_modify_var(q, DO_INC); break;
- case Q_DEC: do_modify_var(q, DO_DEC); break;
- case Q_ECHO: do_echo(q); query_executed= 1; break;
- case Q_SYSTEM: do_system(q); break;
+ case Q_SOURCE: do_source(command); break;
+ case Q_SLEEP: do_sleep(command, 0); break;
+ case Q_REAL_SLEEP: do_sleep(command, 1); break;
+ case Q_WAIT_FOR_SLAVE_TO_STOP: do_wait_for_slave_to_stop(command); break;
+ case Q_INC: do_modify_var(command, DO_INC); break;
+ case Q_DEC: do_modify_var(command, DO_DEC); break;
+ case Q_ECHO: do_echo(command); command_executed++; break;
+ case Q_SYSTEM: do_system(command); break;
+ case Q_REMOVE_FILE: do_remove_file(command); break;
+ case Q_FILE_EXIST: do_file_exist(command); break;
+ case Q_WRITE_FILE: do_write_file(command); break;
+ case Q_COPY_FILE: do_copy_file(command); break;
+ case Q_PERL: do_perl(command); break;
case Q_DELIMITER:
- strmake(delimiter, q->first_argument, sizeof(delimiter) - 1);
- delimiter_length= strlen(delimiter);
- q->last_argument= q->first_argument+delimiter_length;
+ do_delimiter(command);
break;
case Q_DISPLAY_VERTICAL_RESULTS:
display_result_vertically= TRUE;
@@ -4790,129 +5697,128 @@ int main(int argc, char **argv)
case Q_DISPLAY_HORIZONTAL_RESULTS:
display_result_vertically= FALSE;
break;
- case Q_LET: do_let(q); break;
+ case Q_LET: do_let(command); break;
case Q_EVAL_RESULT:
eval_result = 1; break;
case Q_EVAL:
- if (q->query == q->query_buf)
+ if (command->query == command->query_buf)
{
- q->query= q->first_argument;
- q->first_word_len= 0;
+ command->query= command->first_argument;
+ command->first_word_len= 0;
}
/* fall through */
case Q_QUERY_VERTICAL:
case Q_QUERY_HORIZONTAL:
{
my_bool old_display_result_vertically= display_result_vertically;
- /* fix up query pointer if this is first iteration for this line */
- if (q->query == q->query_buf)
- q->query += q->first_word_len + 1;
- display_result_vertically= (q->type==Q_QUERY_VERTICAL);
+
+ /* Remove "query_*" if this is first iteration */
+ if (command->query == command->query_buf)
+ command->query= command->first_argument;
+
+ display_result_vertically= (command->type == Q_QUERY_VERTICAL);
if (save_file[0])
{
- strmov(q->record_file,save_file);
- q->require_file=require_file;
- save_file[0]=0;
+ strmake(command->require_file, save_file, sizeof(save_file));
+ save_file[0]= 0;
}
- run_query(cur_con, q, QUERY_REAP|QUERY_SEND);
+ run_query(cur_con, command, QUERY_REAP_FLAG|QUERY_SEND_FLAG);
display_result_vertically= old_display_result_vertically;
- q->last_argument= q->end;
- query_executed= 1;
+ command->last_argument= command->end;
+ command_executed++;
break;
}
case Q_QUERY:
case Q_REAP:
{
- /*
- We read the result always regardless of the mode for both full
- query and read-result only (reap)
- */
- int flags = QUERY_REAP;
- if (q->type != Q_REAP) /* for a full query, enable the send stage */
- flags |= QUERY_SEND;
- if (q_send_flag)
- {
- flags= QUERY_SEND;
- q_send_flag=0;
- }
+ int flags;
+ if (q_send_flag)
+ {
+ /* Last command was an empty 'send' */
+ flags= QUERY_SEND_FLAG;
+ q_send_flag= 0;
+ }
+ else if (command->type == Q_REAP)
+ {
+ flags= QUERY_REAP_FLAG;
+ }
+ else
+ {
+ /* full query, both reap and send */
+ flags= QUERY_REAP_FLAG | QUERY_SEND_FLAG;
+ }
+
if (save_file[0])
{
- strmov(q->record_file,save_file);
- q->require_file=require_file;
- save_file[0]=0;
+ strmake(command->require_file, save_file, sizeof(save_file));
+ save_file[0]= 0;
}
- /*
- To force something being sent as a query to the mysqld one can
- use the prefix "query". Remove "query" from string before executing
- */
- if (strncmp(q->query, "query ", 6) == 0)
- {
- q->query= q->first_argument;
- }
- run_query(cur_con, q, flags);
- query_executed= 1;
- q->last_argument= q->end;
+ run_query(cur_con, command, flags);
+ command_executed++;
+ command->last_argument= command->end;
break;
}
case Q_SEND:
- if (!q->query[q->first_word_len])
- {
- /* This happens when we use 'send' on its own line */
- q_send_flag=1;
- break;
- }
- /* fix up query pointer if this is first iteration for this line */
- if (q->query == q->query_buf)
- q->query += q->first_word_len;
+ if (!*command->first_argument)
+ {
+ /*
+ This is a send without arguments, it indicates that _next_ query
+ should be send only
+ */
+ q_send_flag= 1;
+ break;
+ }
+
+ /* Remove "send" if this is first iteration */
+ if (command->query == command->query_buf)
+ command->query= command->first_argument;
+
/*
run_query() can execute a query partially, depending on the flags.
- QUERY_SEND flag without QUERY_REAP tells it to just send the
- query and read the result some time later when reap instruction
+ QUERY_SEND_FLAG flag without QUERY_REAP_FLAG tells it to just send
+ the query and read the result some time later when reap instruction
is given on this connection.
- */
- run_query(cur_con, q, QUERY_SEND);
- query_executed= 1;
- q->last_argument= q->end;
+ */
+ run_query(cur_con, command, QUERY_SEND_FLAG);
+ command_executed++;
+ command->last_argument= command->end;
break;
- case Q_RESULT:
- get_file_name(save_file,q);
- require_file=0;
+ case Q_REQUIRE:
+ do_get_file_name(command, save_file, sizeof(save_file));
break;
case Q_ERROR:
- global_expected_errors=get_errcodes(global_expected_errno,q);
- break;
- case Q_REQUIRE:
- get_file_name(save_file,q);
- require_file=1;
+ do_get_errcodes(command);
break;
case Q_REPLACE:
- get_replace(q);
+ do_get_replace(command);
break;
+ case Q_REPLACE_REGEX:
+ do_get_replace_regex(command);
+ break;
case Q_REPLACE_COLUMN:
- get_replace_column(q);
+ do_get_replace_column(command);
break;
case Q_SAVE_MASTER_POS: do_save_master_pos(); break;
- case Q_SYNC_WITH_MASTER: do_sync_with_master(q); break;
+ case Q_SYNC_WITH_MASTER: do_sync_with_master(command); break;
case Q_SYNC_SLAVE_WITH_MASTER:
{
do_save_master_pos();
- if (*q->first_argument)
- select_connection(q);
+ if (*command->first_argument)
+ select_connection(command);
else
select_connection_name("slave");
do_sync_with_master2(0);
break;
}
case Q_COMMENT: /* Ignore row */
- case Q_COMMENT_WITH_COMMAND:
- q->last_argument= q->end;
+ command->last_argument= command->end;
break;
case Q_PING:
(void) mysql_ping(&cur_con->mysql);
break;
case Q_EXEC:
- do_exec(q);
- query_executed= 1;
+ do_exec(command);
+ command_executed++;
break;
case Q_START_TIMER:
/* Overwrite possible earlier start of timer */
@@ -4921,10 +5827,9 @@ int main(int argc, char **argv)
case Q_END_TIMER:
/* End timer before ending mysqltest */
timer_output();
- got_end_timer= TRUE;
break;
case Q_CHARACTER_SET:
- set_charset(q);
+ do_set_charset(command);
break;
case Q_DISABLE_PS_PROTOCOL:
ps_protocol_enabled= 0;
@@ -4933,33 +5838,40 @@ int main(int argc, char **argv)
ps_protocol_enabled= ps_protocol;
break;
case Q_DISABLE_RECONNECT:
- {
- my_bool reconnect= 0;
- mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
+ set_reconnect(&cur_con->mysql, 0);
break;
- }
case Q_ENABLE_RECONNECT:
- {
- my_bool reconnect= 1;
- mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
+ set_reconnect(&cur_con->mysql, 1);
break;
- }
case Q_DISABLE_PARSING:
- parsing_disabled++;
+ if (parsing_disabled == 0)
+ parsing_disabled= 1;
+ else
+ die("Parsing is already disabled");
break;
case Q_ENABLE_PARSING:
/*
Ensure we don't get parsing_disabled < 0 as this would accidentally
disable code we don't want to have disabled
*/
- if (parsing_disabled > 0)
- parsing_disabled--;
+ if (parsing_disabled == 1)
+ parsing_disabled= 0;
+ else
+ die("Parsing is already enabled");
+ break;
+ case Q_DIE:
+ /* Abort test with error code and error message */
+ die("%s", command->first_argument);
break;
-
case Q_EXIT:
+ /* Stop processing any more commands */
abort_flag= 1;
break;
+ case Q_RESULT:
+ die("result, deprecated command");
+ break;
+
default:
processed= 0;
break;
@@ -4969,32 +5881,46 @@ int main(int argc, char **argv)
if (!processed)
{
current_line_inc= 0;
- switch (q->type) {
- case Q_WHILE: do_block(cmd_while, q); break;
- case Q_IF: do_block(cmd_if, q); break;
- case Q_END_BLOCK: do_done(q); break;
+ switch (command->type) {
+ case Q_WHILE: do_block(cmd_while, command); break;
+ case Q_IF: do_block(cmd_if, command); break;
+ case Q_END_BLOCK: do_done(command); break;
default: current_line_inc = 1; break;
}
}
else
- check_eol_junk(q->last_argument);
+ check_eol_junk(command->last_argument);
- if (q->type != Q_ERROR)
+ if (command->type != Q_ERROR &&
+ command->type != Q_COMMENT)
{
/*
- As soon as any non "error" command has been executed,
+ As soon as any non "error" command or comment has been executed,
the array with expected errors should be cleared
*/
- global_expected_errors= 0;
- bzero((gptr) global_expected_errno, sizeof(global_expected_errno));
+ memset(&saved_expected_errors, 0, sizeof(saved_expected_errors));
}
+ if (command_executed != last_command_executed)
+ {
+ /*
+ As soon as any command has been executed,
+ the replace structures should be cleared
+ */
+ free_all_replace();
+ }
+ last_command_executed= command_executed;
+
parser.current_line += current_line_inc;
- mark_progress(parser.current_line);
+ if ( opt_mark_progress )
+ mark_progress(command, parser.current_line);
}
start_lineno= 0;
+ if (parsing_disabled)
+ die("Test ended with parsing disabled");
+
/*
The whole test has been executed _sucessfully_.
Time to compare result or save it to record file.
@@ -5002,25 +5928,27 @@ int main(int argc, char **argv)
*/
if (ds_res.length)
{
- if (result_file)
+ if (result_file_name)
{
+ /* A result file has been specified */
+
if (record)
{
- /* Dump the output from test to result file */
- str_to_file(result_file, ds_res.str, ds_res.length);
+ /* Recording - dump the output from test to result file */
+ str_to_file(result_file_name, ds_res.str, ds_res.length);
}
else
{
/* Check that the output from test is equal to result file
- detect missing result file
- detect zero size result file
- */
- check_result(&ds_res, result_file, 0);
+ */
+ check_result(&ds_res);
}
}
else
{
- /* No result_file specified to compare with, print to stdout */
+ /* No result_file_name specified to compare with, print to stdout */
printf("%s", ds_res.str);
}
}
@@ -5029,7 +5957,8 @@ int main(int argc, char **argv)
die("The test didn't produce any output");
}
- if (!query_executed && result_file && my_stat(result_file, &res_info, 0))
+ if (!command_executed &&
+ result_file_name && my_stat(result_file_name, &res_info, 0))
{
/*
my_stat() successful on result file. Check if we have not run a
@@ -5041,8 +5970,16 @@ int main(int argc, char **argv)
die("No queries executed but result file found!");
}
- if (!got_end_timer)
- timer_output(); /* No end_timer cmd, end it */
+ if ( opt_mark_progress && result_file_name )
+ dump_progress();
+
+ /* Dump warning messages */
+ if (result_file_name && ds_warning_messages.length)
+ dump_warning_messages();
+
+ dynstr_free(&ds_res);
+
+ timer_output();
free_used_memory();
my_end(MY_CHECK_ERROR);
@@ -5055,101 +5992,188 @@ int main(int argc, char **argv)
/*
- Read arguments for embedded server and put them into
- embedded_server_args_count and embedded_server_args[]
-*/
+ A primitive timer that give results in milliseconds if the
+ --timer-file=<filename> is given. The timer result is written
+ to that file when the result is available. To not confuse
+ mysql-test-run with an old obsolete result, we remove the file
+ before executing any commands. The time we measure is
+ - If no explicit 'start_timer' or 'end_timer' is given in the
+ test case, the timer measure how long we execute in mysqltest.
-static int read_server_arguments(const char *name)
-{
- char argument[1024],buff[FN_REFLEN], *str=0;
- FILE *file;
+ - If only 'start_timer' is given we measure how long we execute
+ from that point until we terminate mysqltest.
- if (!test_if_hard_path(name))
+ - If only 'end_timer' is given we measure how long we execute
+ from that we enter mysqltest to the 'end_timer' is command is
+ executed.
+
+ - If both 'start_timer' and 'end_timer' are given we measure
+ the time between executing the two commands.
+*/
+
+void timer_output(void)
+{
+ if (timer_file)
{
- strxmov(buff, opt_basedir, name, NullS);
- name=buff;
+ char buf[32], *end;
+ ulonglong timer= timer_now() - timer_start;
+ end= longlong2str(timer, buf, 10);
+ str_to_file(timer_file,buf, (int) (end-buf));
+ /* Timer has been written to the file, don't use it anymore */
+ timer_file= 0;
}
- fn_format(buff,name,"","",4);
+}
- if (!embedded_server_arg_count)
+
+ulonglong timer_now(void)
+{
+ return my_getsystime() / 10000;
+}
+
+
+/*
+ Get arguments for replace_columns. The syntax is:
+ replace-column column_number to_string [column_number to_string ...]
+ Where each argument may be quoted with ' or "
+ A argument may also be a variable, in which case the value of the
+ variable is replaced.
+*/
+
+void do_get_replace_column(struct st_command *command)
+{
+ char *from= command->first_argument;
+ char *buff, *start;
+ DBUG_ENTER("get_replace_columns");
+
+ free_replace_column();
+ if (!*from)
+ die("Missing argument in %s", command->query);
+
+ /* Allocate a buffer for results */
+ start= buff= my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
+ while (*from)
{
- embedded_server_arg_count=1;
- embedded_server_args[0]= (char*) ""; /* Progname */
+ char *to;
+ uint column_number;
+
+ to= get_string(&buff, &from, command);
+ if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
+ die("Wrong column number to replace_column in '%s'", command->query);
+ if (!*from)
+ die("Wrong number of arguments to replace_column in '%s'", command->query);
+ to= get_string(&buff, &from, command);
+ my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
+ replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
+ set_if_bigger(max_replace_column, column_number);
}
- if (!(file=my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME))))
- return 1;
- while (embedded_server_arg_count < MAX_SERVER_ARGS &&
- (str=fgets(argument,sizeof(argument), file)))
+ my_free(start, MYF(0));
+ command->last_argument= command->end;
+}
+
+
+void free_replace_column()
+{
+ uint i;
+ for (i=0 ; i < max_replace_column ; i++)
{
- *(strend(str)-1)=0; /* Remove end newline */
- if (!(embedded_server_args[embedded_server_arg_count]=
- (char*) my_strdup(str,MYF(MY_WME))))
+ if (replace_column[i])
{
- my_fclose(file,MYF(0));
- return 1;
+ my_free(replace_column[i], 0);
+ replace_column[i]= 0;
}
- embedded_server_arg_count++;
}
- my_fclose(file,MYF(0));
- if (str)
- {
- fprintf(stderr,"Too many arguments in option file: %s\n",name);
- return 1;
- }
- return 0;
+ max_replace_column= 0;
}
-/****************************************************************************\
- *
- * A primitive timer that give results in milliseconds if the
- * --timer-file=<filename> is given. The timer result is written
- * to that file when the result is available. To not confuse
- * mysql-test-run with an old obsolete result, we remove the file
- * before executing any commands. The time we measure is
- *
- * - If no explicit 'start_timer' or 'end_timer' is given in the
- * test case, the timer measure how long we execute in mysqltest.
- *
- * - If only 'start_timer' is given we measure how long we execute
- * from that point until we terminate mysqltest.
- *
- * - If only 'end_timer' is given we measure how long we execute
- * from that we enter mysqltest to the 'end_timer' is command is
- * executed.
- *
- * - If both 'start_timer' and 'end_timer' are given we measure
- * the time between executing the two commands.
- *
-\****************************************************************************/
-
-static void timer_output(void)
+
+/****************************************************************************/
+/*
+ Replace functions
+*/
+
+/* Definitions for replace result */
+
+typedef struct st_pointer_array { /* when using array-strings */
+ TYPELIB typelib; /* Pointer to strings */
+ byte *str; /* Strings is here */
+ int7 *flag; /* Flag about each var. */
+ uint array_allocs,max_count,length,max_length;
+} POINTER_ARRAY;
+
+struct st_replace;
+struct st_replace *init_replace(my_string *from, my_string *to, uint count,
+ my_string word_end_chars);
+int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
+void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds,
+ const char *from, int len);
+void free_pointer_array(POINTER_ARRAY *pa);
+
+struct st_replace *glob_replace;
+
+/*
+ Get arguments for replace. The syntax is:
+ replace from to [from to ...]
+ Where each argument may be quoted with ' or "
+ A argument may also be a variable, in which case the value of the
+ variable is replaced.
+*/
+
+void do_get_replace(struct st_command *command)
{
- if (timer_file)
+ uint i;
+ char *from= command->first_argument;
+ char *buff, *start;
+ char word_end_chars[256], *pos;
+ POINTER_ARRAY to_array, from_array;
+ DBUG_ENTER("get_replace");
+
+ free_replace();
+
+ bzero((char*) &to_array,sizeof(to_array));
+ bzero((char*) &from_array,sizeof(from_array));
+ if (!*from)
+ die("Missing argument in %s", command->query);
+ start= buff= my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
+ while (*from)
{
- char buf[32], *end;
- ulonglong timer= timer_now() - timer_start;
- end= longlong2str(timer, buf, 10);
- str_to_file(timer_file,buf, (int) (end-buf));
+ char *to= buff;
+ to= get_string(&buff, &from, command);
+ if (!*from)
+ die("Wrong number of arguments to replace_result in '%s'",
+ command->query);
+ insert_pointer_name(&from_array,to);
+ to= get_string(&buff, &from, command);
+ insert_pointer_name(&to_array,to);
}
+ for (i= 1,pos= word_end_chars ; i < 256 ; i++)
+ if (my_isspace(charset_info,i))
+ *pos++= i;
+ *pos=0; /* End pointer */
+ if (!(glob_replace= init_replace((char**) from_array.typelib.type_names,
+ (char**) to_array.typelib.type_names,
+ (uint) from_array.typelib.count,
+ word_end_chars)))
+ die("Can't initialize replace from '%s'", command->query);
+ free_pointer_array(&from_array);
+ free_pointer_array(&to_array);
+ my_free(start, MYF(0));
+ command->last_argument= command->end;
+ DBUG_VOID_RETURN;
}
-static ulonglong timer_now(void)
+
+void free_replace()
{
- return my_getsystime() / 10000;
+ DBUG_ENTER("free_replace");
+ if (glob_replace)
+ {
+ my_free((char*) glob_replace,MYF(0));
+ glob_replace=0;
+ }
+ DBUG_VOID_RETURN;
}
-/****************************************************************************
-* Handle replacement of strings
-****************************************************************************/
-
-#define PC_MALLOC 256 /* Bytes for pointers */
-#define PS_MALLOC 512 /* Bytes for data */
-
-#define SPACE_CHAR 256
-#define START_OF_LINE 257
-#define END_OF_LINE 258
-#define LAST_CHAR_CODE 259
typedef struct st_replace {
bool found;
@@ -5163,99 +6187,514 @@ typedef struct st_replace_found {
int from_offset;
} REPLACE_STRING;
-#ifndef WORD_BIT
-#define WORD_BIT (8*sizeof(uint))
-#endif
-
-static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name)
+void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
+ const char *str, int len)
{
- uint i,length,old_count;
- byte *new_pos;
- const char **new_array;
- DBUG_ENTER("insert_pointer_name");
+ reg1 REPLACE *rep_pos;
+ reg2 REPLACE_STRING *rep_str;
+ const char *start, *from;
+ DBUG_ENTER("replace_strings_append");
- if (! pa->typelib.count)
+ start= from= str;
+ rep_pos=rep+1;
+ for (;;)
{
- if (!(pa->typelib.type_names=(const char **)
- my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
- (sizeof(my_string)+sizeof(*pa->flag))*
- (sizeof(my_string)+sizeof(*pa->flag))),MYF(MY_WME))))
- DBUG_RETURN(-1);
- if (!(pa->str= (byte*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
- MYF(MY_WME))))
+ /* Loop through states */
+ DBUG_PRINT("info", ("Looping through states"));
+ while (!rep_pos->found)
+ rep_pos= rep_pos->next[(uchar) *from++];
+
+ /* Does this state contain a string to be replaced */
+ if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
{
- my_free((gptr) pa->typelib.type_names,MYF(0));
- DBUG_RETURN (-1);
+ /* No match found */
+ dynstr_append_mem(ds, start, from - start - 1);
+ DBUG_PRINT("exit", ("Found no more string to replace, appended: %s", start));
+ DBUG_VOID_RETURN;
}
- pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(byte*)+
- sizeof(*pa->flag));
- pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
- pa->length=0;
- pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
- pa->array_allocs=1;
+
+ /* Found a string that needs to be replaced */
+ DBUG_PRINT("info", ("found: %d, to_offset: %d, from_offset: %d, string: %s",
+ rep_str->found, rep_str->to_offset,
+ rep_str->from_offset, rep_str->replace_string));
+
+ /* Append part of original string before replace string */
+ dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
+
+ /* Append replace string */
+ dynstr_append_mem(ds, rep_str->replace_string,
+ strlen(rep_str->replace_string));
+
+ if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
+ {
+ /* End of from string */
+ DBUG_PRINT("exit", ("Found end of from string"));
+ DBUG_VOID_RETURN;
+ }
+ DBUG_ASSERT(from <= str+len);
+ start= from;
+ rep_pos=rep;
}
- length=(uint) strlen(name)+1;
- if (pa->length+length >= pa->max_length)
- {
- if (!(new_pos= (byte*) my_realloc((gptr) pa->str,
- (uint) (pa->max_length+PS_MALLOC),
- MYF(MY_WME))))
- DBUG_RETURN(1);
- if (new_pos != pa->str)
+}
+
+
+/*
+ Regex replace functions
+*/
+
+
+/* Stores regex substitutions */
+
+struct st_regex
+{
+ char* pattern; /* Pattern to be replaced */
+ char* replace; /* String or expression to replace the pattern with */
+ int icase; /* true if the match is case insensitive */
+};
+
+struct st_replace_regex
+{
+ DYNAMIC_ARRAY regex_arr; /* stores a list of st_regex subsitutions */
+
+ /*
+ Temporary storage areas for substitutions. To reduce unnessary copying
+ and memory freeing/allocation, we pre-allocate two buffers, and alternate
+ their use, one for input/one for output, the roles changing on the next
+ st_regex substition. At the end of substitutions buf points to the
+ one containing the final result.
+ */
+ char* buf;
+ char* even_buf;
+ char* odd_buf;
+ int even_buf_len;
+ int odd_buf_len;
+};
+
+struct st_replace_regex *glob_replace_regex= 0;
+
+int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace,
+ char *string, int icase);
+
+
+
+/*
+ Finds the next (non-escaped) '/' in the expression.
+ (If the character '/' is needed, it can be escaped using '\'.)
+*/
+
+#define PARSE_REGEX_ARG \
+ while (p < expr_end) \
+ { \
+ char c= *p; \
+ if (c == '/') \
+ { \
+ if (last_c == '\\') \
+ { \
+ buf_p[-1]= '/'; \
+ } \
+ else \
+ { \
+ *buf_p++ = 0; \
+ break; \
+ } \
+ } \
+ else \
+ *buf_p++ = c; \
+ \
+ last_c= c; \
+ p++; \
+ } \
+ \
+/*
+ Initializes the regular substitution expression to be used in the
+ result output of test.
+
+ Returns: st_replace_regex struct with pairs of substitutions
+*/
+
+struct st_replace_regex* init_replace_regex(char* expr)
+{
+ struct st_replace_regex* res;
+ char* buf,*expr_end;
+ char* p;
+ char* buf_p;
+ uint expr_len= strlen(expr);
+ char last_c = 0;
+ struct st_regex reg;
+
+ /* my_malloc() will die on fail with MY_FAE */
+ res=(struct st_replace_regex*)my_malloc(
+ sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME));
+ my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128);
+
+ buf= (char*)res + sizeof(*res);
+ expr_end= expr + expr_len;
+ p= expr;
+ buf_p= buf;
+
+ /* for each regexp substitution statement */
+ while (p < expr_end)
+ {
+ bzero(&reg,sizeof(reg));
+ /* find the start of the statement */
+ while (p < expr_end)
{
- my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
- for (i=0 ; i < pa->typelib.count ; i++)
- pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
- char*);
- pa->str=new_pos;
+ if (*p == '/')
+ break;
+ p++;
}
- pa->max_length+=PS_MALLOC;
+
+ if (p == expr_end || ++p == expr_end)
+ {
+ if (res->regex_arr.elements)
+ break;
+ else
+ goto err;
+ }
+ /* we found the start */
+ reg.pattern= buf_p;
+
+ /* Find first argument -- pattern string to be removed */
+ PARSE_REGEX_ARG
+
+ if (p == expr_end || ++p == expr_end)
+ goto err;
+
+ /* buf_p now points to the replacement pattern terminated with \0 */
+ reg.replace= buf_p;
+
+ /* Find second argument -- replace string to replace pattern */
+ PARSE_REGEX_ARG
+
+ if (p == expr_end)
+ goto err;
+
+ /* skip the ending '/' in the statement */
+ p++;
+
+ /* Check if we should do matching case insensitive */
+ if (p < expr_end && *p == 'i')
+ reg.icase= 1;
+
+ /* done parsing the statement, now place it in regex_arr */
+ if (insert_dynamic(&res->regex_arr,(gptr) &reg))
+ die("Out of memory");
}
- if (pa->typelib.count >= pa->max_count-1)
+ res->odd_buf_len= res->even_buf_len= 8192;
+ res->even_buf= (char*)my_malloc(res->even_buf_len,MYF(MY_WME+MY_FAE));
+ res->odd_buf= (char*)my_malloc(res->odd_buf_len,MYF(MY_WME+MY_FAE));
+ res->buf= res->even_buf;
+
+ return res;
+
+err:
+ my_free((gptr)res,0);
+ die("Error parsing replace_regex \"%s\"", expr);
+ return 0;
+}
+
+/*
+ Execute all substitutions on val.
+
+ Returns: true if substituition was made, false otherwise
+ Side-effect: Sets r->buf to be the buffer with all substitutions done.
+
+ IN:
+ struct st_replace_regex* r
+ char* val
+ Out:
+ struct st_replace_regex* r
+ r->buf points at the resulting buffer
+ r->even_buf and r->odd_buf might have been reallocated
+ r->even_buf_len and r->odd_buf_len might have been changed
+
+ TODO: at some point figure out if there is a way to do everything
+ in one pass
+*/
+
+int multi_reg_replace(struct st_replace_regex* r,char* val)
+{
+ uint i;
+ char* in_buf, *out_buf;
+ int* buf_len_p;
+
+ in_buf= val;
+ out_buf= r->even_buf;
+ buf_len_p= &r->even_buf_len;
+ r->buf= 0;
+
+ /* For each substitution, do the replace */
+ for (i= 0; i < r->regex_arr.elements; i++)
{
- int len;
- pa->array_allocs++;
- len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
- if (!(new_array=(const char **) my_realloc((gptr) pa->typelib.type_names,
- (uint) len/
- (sizeof(byte*)+sizeof(*pa->flag))*
- (sizeof(byte*)+sizeof(*pa->flag)),
- MYF(MY_WME))))
- DBUG_RETURN(1);
- pa->typelib.type_names=new_array;
- old_count=pa->max_count;
- pa->max_count=len/(sizeof(byte*) + sizeof(*pa->flag));
- pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
- memcpy((byte*) pa->flag,(my_string) (pa->typelib.type_names+old_count),
- old_count*sizeof(*pa->flag));
+ struct st_regex re;
+ char* save_out_buf= out_buf;
+
+ get_dynamic(&r->regex_arr,(gptr)&re,i);
+
+ if (!reg_replace(&out_buf, buf_len_p, re.pattern, re.replace,
+ in_buf, re.icase))
+ {
+ /* if the buffer has been reallocated, make adjustements */
+ if (save_out_buf != out_buf)
+ {
+ if (save_out_buf == r->even_buf)
+ r->even_buf= out_buf;
+ else
+ r->odd_buf= out_buf;
+ }
+
+ r->buf= out_buf;
+ if (in_buf == val)
+ in_buf= r->odd_buf;
+
+ swap_variables(char*,in_buf,out_buf);
+
+ buf_len_p= (out_buf == r->even_buf) ? &r->even_buf_len :
+ &r->odd_buf_len;
+ }
}
- pa->flag[pa->typelib.count]=0; /* Reset flag */
- pa->typelib.type_names[pa->typelib.count++]= pa->str+pa->length;
- pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
- VOID(strmov(pa->str+pa->length,name));
- pa->length+=length;
- DBUG_RETURN(0);
-} /* insert_pointer_name */
+ return (r->buf == 0);
+}
+
+/*
+ Parse the regular expression to be used in all result files
+ from now on.
- /* free pointer array */
+ The syntax is --replace_regex /from/to/i /from/to/i ...
+ i means case-insensitive match. If omitted, the match is
+ case-sensitive
-void free_pointer_array(POINTER_ARRAY *pa)
+*/
+void do_get_replace_regex(struct st_command *command)
{
- if (pa->typelib.count)
+ char *expr= command->first_argument;
+ free_replace_regex();
+ if (!(glob_replace_regex=init_replace_regex(expr)))
+ die("Could not init replace_regex");
+ command->last_argument= command->end;
+}
+
+void free_replace_regex()
+{
+ if (glob_replace_regex)
{
- pa->typelib.count=0;
- my_free((gptr) pa->typelib.type_names,MYF(0));
- pa->typelib.type_names=0;
- my_free((gptr) pa->str,MYF(0));
+ delete_dynamic(&glob_replace_regex->regex_arr);
+ my_free(glob_replace_regex->even_buf,MYF(MY_ALLOW_ZERO_PTR));
+ my_free(glob_replace_regex->odd_buf,MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*) glob_replace_regex,MYF(0));
+ glob_replace_regex=0;
}
-} /* free_pointer_array */
+}
- /* Code for replace rutines */
+
+/*
+ auxiluary macro used by reg_replace
+ makes sure the result buffer has sufficient length
+*/
+#define SECURE_REG_BUF if (buf_len < need_buf_len) \
+ { \
+ int off= res_p - buf; \
+ buf= (char*)my_realloc(buf,need_buf_len,MYF(MY_WME+MY_FAE)); \
+ res_p= buf + off; \
+ buf_len= need_buf_len; \
+ } \
+ \
+/*
+ Performs a regex substitution
+
+ IN:
+
+ buf_p - result buffer pointer. Will change if reallocated
+ buf_len_p - result buffer length. Will change if the buffer is reallocated
+ pattern - regexp pattern to match
+ replace - replacement expression
+ string - the string to perform substituions in
+ icase - flag, if set to 1 the match is case insensitive
+*/
+int reg_replace(char** buf_p, int* buf_len_p, char *pattern,
+ char *replace, char *string, int icase)
+{
+ my_regex_t r;
+ my_regmatch_t *subs;
+ char *buf_end, *replace_end;
+ char *buf= *buf_p;
+ int len;
+ int buf_len, need_buf_len;
+ int cflags= REG_EXTENDED;
+ int err_code;
+ char *res_p,*str_p,*str_end;
+
+ buf_len= *buf_len_p;
+ len= strlen(string);
+ str_end= string + len;
+
+ /* start with a buffer of a reasonable size that hopefully will not
+ need to be reallocated
+ */
+ need_buf_len= len * 2 + 1;
+ res_p= buf;
+
+ SECURE_REG_BUF
+
+ buf_end= buf + buf_len;
+
+ if (icase)
+ cflags|= REG_ICASE;
+
+ if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1)))
+ {
+ check_regerr(&r,err_code);
+ return 1;
+ }
+
+ subs= (my_regmatch_t*)my_malloc(sizeof(my_regmatch_t) * (r.re_nsub+1),
+ MYF(MY_WME+MY_FAE));
+
+ *res_p= 0;
+ str_p= string;
+ replace_end= replace + strlen(replace);
+
+ /* for each pattern match instance perform a replacement */
+ while (!err_code)
+ {
+ /* find the match */
+ err_code= my_regexec(&r,str_p, r.re_nsub+1, subs,
+ (str_p == string) ? REG_NOTBOL : 0);
+
+ /* if regular expression error (eg. bad syntax, or out of memory) */
+ if (err_code && err_code != REG_NOMATCH)
+ {
+ check_regerr(&r,err_code);
+ my_regfree(&r);
+ return 1;
+ }
+
+ /* if match found */
+ if (!err_code)
+ {
+ char* expr_p= replace;
+ int c;
+
+ /*
+ we need at least what we have so far in the buffer + the part
+ before this match
+ */
+ need_buf_len= (res_p - buf) + subs[0].rm_so;
+
+ /* on this pass, calculate the memory for the result buffer */
+ while (expr_p < replace_end)
+ {
+ int back_ref_num= -1;
+ c= *expr_p;
+
+ if (c == '\\' && expr_p + 1 < replace_end)
+ {
+ back_ref_num= expr_p[1] - '0';
+ }
+
+ /* found a valid back_ref (eg. \1)*/
+ if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
+ {
+ int start_off,end_off;
+ if ((start_off=subs[back_ref_num].rm_so) > -1 &&
+ (end_off=subs[back_ref_num].rm_eo) > -1)
+ {
+ need_buf_len += (end_off - start_off);
+ }
+ expr_p += 2;
+ }
+ else
+ {
+ expr_p++;
+ need_buf_len++;
+ }
+ }
+ need_buf_len++;
+ /*
+ now that we know the size of the buffer,
+ make sure it is big enough
+ */
+ SECURE_REG_BUF
+
+ /* copy the pre-match part */
+ if (subs[0].rm_so)
+ {
+ memcpy(res_p, str_p, subs[0].rm_so);
+ res_p+= subs[0].rm_so;
+ }
+
+ expr_p= replace;
+
+ /* copy the match and expand back_refs */
+ while (expr_p < replace_end)
+ {
+ int back_ref_num= -1;
+ c= *expr_p;
+
+ if (c == '\\' && expr_p + 1 < replace_end)
+ {
+ back_ref_num= expr_p[1] - '0';
+ }
+
+ if (back_ref_num >= 0 && back_ref_num <= (int)r.re_nsub)
+ {
+ int start_off,end_off;
+ if ((start_off=subs[back_ref_num].rm_so) > -1 &&
+ (end_off=subs[back_ref_num].rm_eo) > -1)
+ {
+ int block_len= end_off - start_off;
+ memcpy(res_p,str_p + start_off, block_len);
+ res_p += block_len;
+ }
+ expr_p += 2;
+ }
+ else
+ {
+ *res_p++ = *expr_p++;
+ }
+ }
+
+ /* handle the post-match part */
+ if (subs[0].rm_so == subs[0].rm_eo)
+ {
+ if (str_p + subs[0].rm_so >= str_end)
+ break;
+ str_p += subs[0].rm_eo ;
+ *res_p++ = *str_p++;
+ }
+ else
+ {
+ str_p += subs[0].rm_eo;
+ }
+ }
+ else /* no match this time, just copy the string as is */
+ {
+ int left_in_str= str_end-str_p;
+ need_buf_len= (res_p-buf) + left_in_str;
+ SECURE_REG_BUF
+ memcpy(res_p,str_p,left_in_str);
+ res_p += left_in_str;
+ str_p= str_end;
+ }
+ }
+ my_free((gptr)subs, MYF(0));
+ my_regfree(&r);
+ *res_p= 0;
+ *buf_p= buf;
+ *buf_len_p= buf_len;
+ return 0;
+}
+
+
+#ifndef WORD_BIT
+#define WORD_BIT (8*sizeof(uint))
+#endif
#define SET_MALLOC_HUNC 64
+#define LAST_CHAR_CODE 259
typedef struct st_rep_set {
uint *bits; /* Pointer to used sets */
@@ -5287,32 +6726,48 @@ typedef struct st_follow {
} FOLLOWS;
-static int init_sets(REP_SETS *sets,uint states);
-static REP_SET *make_new_set(REP_SETS *sets);
-static void make_sets_invisible(REP_SETS *sets);
-static void free_last_set(REP_SETS *sets);
-static void free_sets(REP_SETS *sets);
-static void internal_set_bit(REP_SET *set, uint bit);
-static void internal_clear_bit(REP_SET *set, uint bit);
-static void or_bits(REP_SET *to,REP_SET *from);
-static void copy_bits(REP_SET *to,REP_SET *from);
-static int cmp_bits(REP_SET *set1,REP_SET *set2);
-static int get_next_bit(REP_SET *set,uint lastpos);
-static int find_set(REP_SETS *sets,REP_SET *find);
-static int find_found(FOUND_SET *found_set,uint table_offset,
- int found_offset);
-static uint start_at_word(my_string pos);
-static uint end_of_word(my_string pos);
-static uint replace_len(my_string pos);
+int init_sets(REP_SETS *sets,uint states);
+REP_SET *make_new_set(REP_SETS *sets);
+void make_sets_invisible(REP_SETS *sets);
+void free_last_set(REP_SETS *sets);
+void free_sets(REP_SETS *sets);
+void internal_set_bit(REP_SET *set, uint bit);
+void internal_clear_bit(REP_SET *set, uint bit);
+void or_bits(REP_SET *to,REP_SET *from);
+void copy_bits(REP_SET *to,REP_SET *from);
+int cmp_bits(REP_SET *set1,REP_SET *set2);
+int get_next_bit(REP_SET *set,uint lastpos);
+int find_set(REP_SETS *sets,REP_SET *find);
+int find_found(FOUND_SET *found_set,uint table_offset,
+ int found_offset);
+uint start_at_word(my_string pos);
+uint end_of_word(my_string pos);
static uint found_sets=0;
- /* Init a replace structure for further calls */
+uint replace_len(my_string str)
+{
+ uint len=0;
+ while (*str)
+ {
+ if (str[0] == '\\' && str[1])
+ str++;
+ str++;
+ len++;
+ }
+ return len;
+}
+
+/* Init a replace structure for further calls */
REPLACE *init_replace(my_string *from, my_string *to,uint count,
my_string word_end_chars)
{
+ static const int SPACE_CHAR= 256;
+ static const int START_OF_LINE= 257;
+ static const int END_OF_LINE= 258;
+
uint i,j,states,set_nr,len,result_len,max_length,found_end,bits_set,bit_nr;
int used_sets,chr,default_state;
char used_chars[LAST_CHAR_CODE],is_word_end[256];
@@ -5365,7 +6820,7 @@ REPLACE *init_replace(my_string *from, my_string *to,uint count,
DBUG_RETURN(0);
}
- /* Init follow_ptr[] */
+ /* Init follow_ptr[] */
for (i=0, states=1, follow_ptr=follow+1 ; i < count ; i++)
{
if (from[i][0] == '\\' && from[i][1] == '^')
@@ -5548,7 +7003,7 @@ REPLACE *init_replace(my_string *from, my_string *to,uint count,
}
}
- /* Alloc replace structure for the replace-state-machine */
+ /* Alloc replace structure for the replace-state-machine */
if ((replace=(REPLACE*) my_malloc(sizeof(REPLACE)*(sets.count)+
sizeof(REPLACE_STRING)*(found_sets+1)+
@@ -5591,7 +7046,7 @@ REPLACE *init_replace(my_string *from, my_string *to,uint count,
}
-static int init_sets(REP_SETS *sets,uint states)
+int init_sets(REP_SETS *sets,uint states)
{
bzero((char*) sets,sizeof(*sets));
sets->size_of_bits=((states+7)/8);
@@ -5607,16 +7062,16 @@ static int init_sets(REP_SETS *sets,uint states)
return 0;
}
- /* Make help sets invisible for nicer codeing */
+/* Make help sets invisible for nicer codeing */
-static void make_sets_invisible(REP_SETS *sets)
+void make_sets_invisible(REP_SETS *sets)
{
sets->invisible=sets->count;
sets->set+=sets->count;
sets->count=0;
}
-static REP_SET *make_new_set(REP_SETS *sets)
+REP_SET *make_new_set(REP_SETS *sets)
{
uint i,count,*bit_buffer;
REP_SET *set;
@@ -5634,7 +7089,7 @@ static REP_SET *make_new_set(REP_SETS *sets)
}
count=sets->count+sets->invisible+SET_MALLOC_HUNC;
if (!(set=(REP_SET*) my_realloc((gptr) sets->set_buffer,
- sizeof(REP_SET)*count,
+ sizeof(REP_SET)*count,
MYF(MY_WME))))
return 0;
sets->set_buffer=set;
@@ -5653,34 +7108,34 @@ static REP_SET *make_new_set(REP_SETS *sets)
return make_new_set(sets);
}
-static void free_last_set(REP_SETS *sets)
+void free_last_set(REP_SETS *sets)
{
sets->count--;
sets->extra++;
return;
}
-static void free_sets(REP_SETS *sets)
+void free_sets(REP_SETS *sets)
{
my_free((gptr)sets->set_buffer,MYF(0));
my_free((gptr)sets->bit_buffer,MYF(0));
return;
}
-static void internal_set_bit(REP_SET *set, uint bit)
+void internal_set_bit(REP_SET *set, uint bit)
{
set->bits[bit / WORD_BIT] |= 1 << (bit % WORD_BIT);
return;
}
-static void internal_clear_bit(REP_SET *set, uint bit)
+void internal_clear_bit(REP_SET *set, uint bit)
{
set->bits[bit / WORD_BIT] &= ~ (1 << (bit % WORD_BIT));
return;
}
-static void or_bits(REP_SET *to,REP_SET *from)
+void or_bits(REP_SET *to,REP_SET *from)
{
reg1 uint i;
for (i=0 ; i < to->size_of_bits ; i++)
@@ -5688,22 +7143,22 @@ static void or_bits(REP_SET *to,REP_SET *from)
return;
}
-static void copy_bits(REP_SET *to,REP_SET *from)
+void copy_bits(REP_SET *to,REP_SET *from)
{
memcpy((byte*) to->bits,(byte*) from->bits,
(size_t) (sizeof(uint) * to->size_of_bits));
}
-static int cmp_bits(REP_SET *set1,REP_SET *set2)
+int cmp_bits(REP_SET *set1,REP_SET *set2)
{
return bcmp((byte*) set1->bits,(byte*) set2->bits,
sizeof(uint) * set1->size_of_bits);
}
- /* Get next set bit from set. */
+/* Get next set bit from set. */
-static int get_next_bit(REP_SET *set,uint lastpos)
+int get_next_bit(REP_SET *set,uint lastpos)
{
uint pos,*start,*end,bits;
@@ -5724,11 +7179,11 @@ static int get_next_bit(REP_SET *set,uint lastpos)
return pos;
}
- /* find if there is a same set in sets. If there is, use it and
- free given set, else put in given set in sets and return its
- position */
+/* find if there is a same set in sets. If there is, use it and
+ free given set, else put in given set in sets and return its
+ position */
-static int find_set(REP_SETS *sets,REP_SET *find)
+int find_set(REP_SETS *sets,REP_SET *find)
{
uint i;
for (i=0 ; i < sets->count-1 ; i++)
@@ -5742,14 +7197,14 @@ static int find_set(REP_SETS *sets,REP_SET *find)
return i; /* return new postion */
}
- /* find if there is a found_set with same table_offset & found_offset
- If there is return offset to it, else add new offset and return pos.
- Pos returned is -offset-2 in found_set_structure because it is
- saved in set->next and set->next[] >= 0 points to next set and
- set->next[] == -1 is reserved for end without replaces.
- */
+/* find if there is a found_set with same table_offset & found_offset
+ If there is return offset to it, else add new offset and return pos.
+ Pos returned is -offset-2 in found_set_structure because it is
+ saved in set->next and set->next[] >= 0 points to next set and
+ set->next[] == -1 is reserved for end without replaces.
+*/
-static int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
+int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
{
int i;
for (i=0 ; (uint) i < found_sets ; i++)
@@ -5762,145 +7217,153 @@ static int find_found(FOUND_SET *found_set,uint table_offset, int found_offset)
return -i-2; /* return new postion */
}
- /* Return 1 if regexp starts with \b or ends with \b*/
+/* Return 1 if regexp starts with \b or ends with \b*/
-static uint start_at_word(my_string pos)
+uint start_at_word(my_string pos)
{
return (((!bcmp(pos,"\\b",2) && pos[2]) || !bcmp(pos,"\\^",2)) ? 1 : 0);
}
-static uint end_of_word(my_string pos)
+uint end_of_word(my_string pos)
{
my_string end=strend(pos);
return ((end > pos+2 && !bcmp(end-2,"\\b",2)) ||
(end >= pos+2 && !bcmp(end-2,"\\$",2))) ?
- 1 : 0;
+ 1 : 0;
}
+/****************************************************************************
+ * Handle replacement of strings
+ ****************************************************************************/
-static uint replace_len(my_string str)
-{
- uint len=0;
- while (*str)
- {
- if (str[0] == '\\' && str[1])
- str++;
- str++;
- len++;
- }
- return len;
-}
-
+#define PC_MALLOC 256 /* Bytes for pointers */
+#define PS_MALLOC 512 /* Bytes for data */
-/* Replace strings while appending to ds */
-void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
- const char *str, int len)
+int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name)
{
- reg1 REPLACE *rep_pos;
- reg2 REPLACE_STRING *rep_str;
- const char *start, *from;
- DBUG_ENTER("replace_strings_append");
+ uint i,length,old_count;
+ byte *new_pos;
+ const char **new_array;
+ DBUG_ENTER("insert_pointer_name");
- start= from= str;
- rep_pos=rep+1;
- for (;;)
+ if (! pa->typelib.count)
{
- /* Loop through states */
- DBUG_PRINT("info", ("Looping through states"));
- while (!rep_pos->found)
- rep_pos= rep_pos->next[(uchar) *from++];
-
- /* Does this state contain a string to be replaced */
- if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string)
+ if (!(pa->typelib.type_names=(const char **)
+ my_malloc(((PC_MALLOC-MALLOC_OVERHEAD)/
+ (sizeof(my_string)+sizeof(*pa->flag))*
+ (sizeof(my_string)+sizeof(*pa->flag))),MYF(MY_WME))))
+ DBUG_RETURN(-1);
+ if (!(pa->str= (byte*) my_malloc((uint) (PS_MALLOC-MALLOC_OVERHEAD),
+ MYF(MY_WME))))
{
- /* No match found */
- dynstr_append_mem(ds, start, from - start - 1);
- DBUG_PRINT("exit", ("Found no more string to replace, appended: %s", start));
- DBUG_VOID_RETURN;
+ my_free((gptr) pa->typelib.type_names,MYF(0));
+ DBUG_RETURN (-1);
}
-
- /* Found a string that needs to be replaced */
- DBUG_PRINT("info", ("found: %d, to_offset: %d, from_offset: %d, string: %s",
- rep_str->found, rep_str->to_offset,
- rep_str->from_offset, rep_str->replace_string));
-
- /* Append part of original string before replace string */
- dynstr_append_mem(ds, start, (from - rep_str->to_offset) - start);
-
- /* Append replace string */
- dynstr_append_mem(ds, rep_str->replace_string,
- strlen(rep_str->replace_string));
-
- if (!*(from-=rep_str->from_offset) && rep_pos->found != 2)
+ pa->max_count=(PC_MALLOC-MALLOC_OVERHEAD)/(sizeof(byte*)+
+ sizeof(*pa->flag));
+ pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
+ pa->length=0;
+ pa->max_length=PS_MALLOC-MALLOC_OVERHEAD;
+ pa->array_allocs=1;
+ }
+ length=(uint) strlen(name)+1;
+ if (pa->length+length >= pa->max_length)
+ {
+ if (!(new_pos= (byte*) my_realloc((gptr) pa->str,
+ (uint) (pa->max_length+PS_MALLOC),
+ MYF(MY_WME))))
+ DBUG_RETURN(1);
+ if (new_pos != pa->str)
{
- /* End of from string */
- DBUG_PRINT("exit", ("Found end of from string"));
- DBUG_VOID_RETURN;
+ my_ptrdiff_t diff=PTR_BYTE_DIFF(new_pos,pa->str);
+ for (i=0 ; i < pa->typelib.count ; i++)
+ pa->typelib.type_names[i]= ADD_TO_PTR(pa->typelib.type_names[i],diff,
+ char*);
+ pa->str=new_pos;
}
- DBUG_ASSERT(from <= str+len);
- start= from;
- rep_pos=rep;
+ pa->max_length+=PS_MALLOC;
}
-}
+ if (pa->typelib.count >= pa->max_count-1)
+ {
+ int len;
+ pa->array_allocs++;
+ len=(PC_MALLOC*pa->array_allocs - MALLOC_OVERHEAD);
+ if (!(new_array=(const char **) my_realloc((gptr) pa->typelib.type_names,
+ (uint) len/
+ (sizeof(byte*)+sizeof(*pa->flag))*
+ (sizeof(byte*)+sizeof(*pa->flag)),
+ MYF(MY_WME))))
+ DBUG_RETURN(1);
+ pa->typelib.type_names=new_array;
+ old_count=pa->max_count;
+ pa->max_count=len/(sizeof(byte*) + sizeof(*pa->flag));
+ pa->flag= (int7*) (pa->typelib.type_names+pa->max_count);
+ memcpy((byte*) pa->flag,(my_string) (pa->typelib.type_names+old_count),
+ old_count*sizeof(*pa->flag));
+ }
+ pa->flag[pa->typelib.count]=0; /* Reset flag */
+ pa->typelib.type_names[pa->typelib.count++]= pa->str+pa->length;
+ pa->typelib.type_names[pa->typelib.count]= NullS; /* Put end-mark */
+ VOID(strmov(pa->str+pa->length,name));
+ pa->length+=length;
+ DBUG_RETURN(0);
+} /* insert_pointer_name */
-/****************************************************************************
- Replace results for a column
-*****************************************************************************/
+/* free pointer array */
-static void free_replace_column()
+void free_pointer_array(POINTER_ARRAY *pa)
{
- uint i;
- for (i=0 ; i < max_replace_column ; i++)
+ if (pa->typelib.count)
{
- if (replace_column[i])
- {
- my_free(replace_column[i], 0);
- replace_column[i]= 0;
- }
+ pa->typelib.count=0;
+ my_free((gptr) pa->typelib.type_names,MYF(0));
+ pa->typelib.type_names=0;
+ my_free((gptr) pa->str,MYF(0));
}
- max_replace_column= 0;
-}
+} /* free_pointer_array */
-/*
- Get arguments for replace_columns. The syntax is:
- replace-column column_number to_string [column_number to_string ...]
- Where each argument may be quoted with ' or "
- A argument may also be a variable, in which case the value of the
- variable is replaced.
-*/
-static void get_replace_column(struct st_query *q)
-{
- char *from=q->first_argument;
- char *buff,*start;
- DBUG_ENTER("get_replace_columns");
+/* Functions that uses replace and replace_regex */
- free_replace_column();
- if (!*from)
- die("Missing argument in %s", q->query);
+/* Append the string to ds, with optional replace */
+void replace_dynstr_append_mem(DYNAMIC_STRING *ds,
+ const char *val, int len)
+{
+#ifdef __WIN__
+ fix_win_paths(val, len);
+#endif
- /* Allocate a buffer for results */
- start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
- while (*from)
+ if (glob_replace_regex)
{
- char *to;
- uint column_number;
+ /* Regex replace */
+ if (!multi_reg_replace(glob_replace_regex, (char*)val))
+ {
+ val= glob_replace_regex->buf;
+ len= strlen(val);
+ }
+ }
- to= get_string(&buff, &from, q);
- if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS)
- die("Wrong column number to replace_column in '%s'", q->query);
- if (!*from)
- die("Wrong number of arguments to replace_column in '%s'", q->query);
- to= get_string(&buff, &from, q);
- my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
- replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE));
- set_if_bigger(max_replace_column, column_number);
+ if (glob_replace)
+ {
+ /* Normal replace */
+ replace_strings_append(glob_replace, ds, val, len);
}
- my_free(start, MYF(0));
- q->last_argument= q->end;
+ else
+ dynstr_append_mem(ds, val, len);
}
+/* Append zero-terminated string to ds, with optional replace */
+void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
+{
+ replace_dynstr_append_mem(ds, val, strlen(val));
+}
-
+/* Append uint to ds, with optional replace */
+void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val)
+{
+ char buff[22]; /* This should be enough for any int */
+ char *end= longlong10_to_str(val, buff, 10);
+ replace_dynstr_append_mem(ds, buff, end - buff);
+}
diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c
index 17f61d1df08..568c3e8776a 100644
--- a/cmd-line-utils/readline/bind.c
+++ b/cmd-line-utils/readline/bind.c
@@ -337,6 +337,7 @@ rl_generic_bind (type, keyseq, data, map)
KEYMAP_ENTRY k;
k.function = 0;
+ k.type= 0;
/* If no keys to bind to, exit right away. */
if (!keyseq || !*keyseq)
@@ -434,7 +435,7 @@ rl_translate_keyseq (seq, array, len)
{
register int i, c, l, temp;
- for (i = l = 0; c = seq[i]; i++)
+ for (i = l = 0; (c = seq[i]); i++)
{
if (c == '\\')
{
@@ -735,7 +736,8 @@ _rl_read_file (filename, sizep)
file_size = (size_t)finfo.st_size;
/* check for overflow on very large files */
- if (file_size != finfo.st_size || file_size + 1 < file_size)
+ if ((long long) file_size != (long long) finfo.st_size ||
+ file_size + 1 < file_size)
{
if (file >= 0)
close (file);
@@ -765,8 +767,8 @@ _rl_read_file (filename, sizep)
/* Re-read the current keybindings file. */
int
-rl_re_read_init_file (count, ignore)
- int count, ignore;
+rl_re_read_init_file (int count __attribute__((unused)),
+ int ignore __attribute__((unused)))
{
int r;
r = rl_read_init_file ((const char *)NULL);
@@ -987,8 +989,7 @@ parser_if (args)
/* Invert the current parser state if there is anything on the stack. */
static int
-parser_else (args)
- char *args;
+parser_else (char *args __attribute__((unused)))
{
register int i;
@@ -1018,8 +1019,7 @@ parser_else (args)
/* Terminate a conditional, popping the value of
_rl_parsing_conditionalized_out from the stack. */
static int
-parser_endif (args)
- char *args;
+parser_endif (char *args __attribute__((unused)))
{
if (if_stack_depth)
_rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
@@ -1142,7 +1142,7 @@ rl_parse_and_bind (string)
{
int passc = 0;
- for (i = 1; c = string[i]; i++)
+ for (i = 1; (c = string[i]); i++)
{
if (passc)
{
@@ -1218,7 +1218,7 @@ rl_parse_and_bind (string)
{
int delimiter = string[i++], passc;
- for (passc = 0; c = string[i]; i++)
+ for (passc = 0; (c = string[i]); i++)
{
if (passc)
{
@@ -1377,7 +1377,7 @@ static struct {
#if defined (VISIBLE_STATS)
{ "visible-stats", &rl_visible_stats, 0 },
#endif /* VISIBLE_STATS */
- { (char *)NULL, (int *)NULL }
+ { (char *)NULL, (int *)NULL, 0 }
};
static int
@@ -1446,7 +1446,7 @@ static struct {
{ "editing-mode", V_STRING, sv_editmode },
{ "isearch-terminators", V_STRING, sv_isrchterm },
{ "keymap", V_STRING, sv_keymap },
- { (char *)NULL, 0 }
+ { (char *)NULL, 0, 0 }
};
static int
@@ -1466,7 +1466,7 @@ find_string_var (name)
values result in 0 (false). */
static int
bool_to_int (value)
- char *value;
+const char *value;
{
return (value == 0 || *value == '\0' ||
(_rl_stricmp (value, "on") == 0) ||
@@ -1725,13 +1725,13 @@ char *
rl_get_keymap_name_from_edit_mode ()
{
if (rl_editing_mode == emacs_mode)
- return "emacs";
+ return (char*) "emacs";
#if defined (VI_MODE)
else if (rl_editing_mode == vi_mode)
- return "vi";
+ return (char*) "vi";
#endif /* VI_MODE */
else
- return "none";
+ return (char*) "none";
}
/* **************************************************************** */
@@ -1966,7 +1966,7 @@ rl_function_dumper (print_readably)
fprintf (rl_outstream, "\n");
- for (i = 0; name = names[i]; i++)
+ for (i = 0; (name = names[i]); i++)
{
rl_command_func_t *function;
char **invokers;
@@ -2025,8 +2025,8 @@ rl_function_dumper (print_readably)
rl_outstream. If an explicit argument is given, then print
the output in such a way that it can be read back in. */
int
-rl_dump_functions (count, key)
- int count, key;
+rl_dump_functions (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
@@ -2105,8 +2105,7 @@ rl_macro_dumper (print_readably)
}
int
-rl_dump_macros (count, key)
- int count, key;
+rl_dump_macros(int count __attribute__((unused)), int key __attribute__((unused)))
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
@@ -2195,8 +2194,7 @@ rl_variable_dumper (print_readably)
rl_outstream. If an explicit argument is given, then print
the output in such a way that it can be read back in. */
int
-rl_dump_variables (count, key)
- int count, key;
+rl_dump_variables(int count __attribute__((unused)), int key __attribute__((unused)))
{
if (rl_dispatching)
fprintf (rl_outstream, "\r\n");
diff --git a/cmd-line-utils/readline/chardefs.h b/cmd-line-utils/readline/chardefs.h
index cb04c982343..04a3b7a8e9c 100644
--- a/cmd-line-utils/readline/chardefs.h
+++ b/cmd-line-utils/readline/chardefs.h
@@ -59,7 +59,11 @@
#define largest_char 255 /* Largest character value. */
#define CTRL_CHAR(c) ((c) < control_character_threshold && (((c) & 0x80) == 0))
+#if largest_char >= 255
+#define META_CHAR(c) ((c) > meta_character_threshold)
+#else
#define META_CHAR(c) ((c) > meta_character_threshold && (c) <= largest_char)
+#endif
#define CTRL(c) ((c) & control_character_mask)
#define META(c) ((c) | meta_character_bit)
diff --git a/cmd-line-utils/readline/complete.c b/cmd-line-utils/readline/complete.c
index df0a698b81f..f4c361789b7 100644
--- a/cmd-line-utils/readline/complete.c
+++ b/cmd-line-utils/readline/complete.c
@@ -360,15 +360,15 @@ rl_complete (ignore, invoking_key)
/* List the possible completions. See description of rl_complete (). */
int
-rl_possible_completions (ignore, invoking_key)
- int ignore, invoking_key;
+rl_possible_completions (int ignore __attribute__((unused)),
+ int invoking_key __attribute__((unused)))
{
return (rl_complete_internal ('?'));
}
int
-rl_insert_completions (ignore, invoking_key)
- int ignore, invoking_key;
+rl_insert_completions (int ignore __attribute__((unused)),
+ int invoking_key __attribute__((unused)))
{
return (rl_complete_internal ('*'));
}
@@ -760,10 +760,7 @@ print_filename (to_print, full_pathname)
}
static char *
-rl_quote_filename (s, rtype, qcp)
- char *s;
- int rtype;
- char *qcp;
+rl_quote_filename (char *s, int rtype __attribute__((unused)), char *qcp)
{
char *r;
@@ -871,7 +868,7 @@ _rl_find_completion_word (fp, dp)
completion, so use the word break characters to find the
substring on which to complete. */
#if defined (HANDLE_MULTIBYTE)
- while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY))
+ while ((rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY)))
#else
while (--rl_point)
#endif
@@ -1805,7 +1802,7 @@ rl_completion_matches (text, entry_function)
match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
match_list[1] = (char *)NULL;
- while (string = (*entry_function) (text, matches))
+ while ((string = (*entry_function) (text, matches)))
{
if (matches + 1 == match_list_size)
match_list = (char **)xrealloc
@@ -1855,7 +1852,7 @@ rl_username_completion_function (text, state)
setpwent ();
}
- while (entry = getpwent ())
+ while ((entry = getpwent ()))
{
/* Null usernames should result in all users as possible completions. */
if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
@@ -2091,8 +2088,7 @@ rl_filename_completion_function (text, state)
hit the end of the match list, we restore the original unmatched text,
ring the bell, and reset the counter to zero. */
int
-rl_menu_complete (count, ignore)
- int count, ignore;
+rl_menu_complete (int count, int ignore __attribute__((unused)))
{
rl_compentry_func_t *our_func;
int matching_filenames, found_quote;
diff --git a/cmd-line-utils/readline/display.c b/cmd-line-utils/readline/display.c
index 06eaa5e4be2..46b57325e33 100644
--- a/cmd-line-utils/readline/display.c
+++ b/cmd-line-utils/readline/display.c
@@ -218,7 +218,7 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
if (niflp)
*niflp = 0;
if (vlp)
- *vlp = lp ? *lp : strlen (r);
+ *vlp = lp ? *lp : (int) strlen (r);
return r;
}
@@ -435,7 +435,7 @@ rl_redisplay ()
return;
if (!rl_display_prompt)
- rl_display_prompt = "";
+ rl_display_prompt = (char*) "";
if (invisible_line == 0)
{
@@ -757,7 +757,7 @@ rl_redisplay ()
c_pos = out;
lb_linenum = newlines;
}
- for (i = in; i < in+wc_bytes; i++)
+ for (i = in; i < (int) (in+wc_bytes); i++)
line[out++] = rl_line_buffer[i];
for (i = 0; i < wc_width; i++)
CHECK_LPOS();
@@ -835,7 +835,7 @@ rl_redisplay ()
#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
-#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
+#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? (char*) "" : VIS_CHARS(line)
#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
/* For each line in the buffer, do the updating display. */
@@ -876,7 +876,7 @@ rl_redisplay ()
_rl_move_vert (linenum);
_rl_move_cursor_relative (0, tt);
_rl_clear_to_eol
- ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
+ ((linenum == _rl_vis_botlin) ? (int) strlen (tt) : _rl_screenwidth);
}
}
_rl_vis_botlin = inv_botlin;
@@ -1086,7 +1086,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
int col_lendiff, col_temp;
#if defined (HANDLE_MULTIBYTE)
mbstate_t ps_new, ps_old;
- int new_offset, old_offset, tmp;
+ int new_offset, old_offset;
#endif
/* If we're at the right edge of a terminal that supports xn, we're
@@ -1837,7 +1837,7 @@ rl_reset_line_state ()
{
rl_on_new_line ();
- rl_display_prompt = rl_prompt ? rl_prompt : "";
+ rl_display_prompt = rl_prompt ? rl_prompt : (char*) "";
forced_display = 1;
return 0;
}
@@ -2212,7 +2212,7 @@ _rl_col_width (str, start, end)
int start, end;
{
wchar_t wc;
- mbstate_t ps = {0};
+ mbstate_t ps;
int tmp, point, width, max;
if (end <= start)
@@ -2221,6 +2221,7 @@ _rl_col_width (str, start, end)
point = 0;
max = end;
+ memset (&ps, 0, sizeof(ps));
while (point < start)
{
tmp = mbrlen (str + point, max, &ps);
diff --git a/cmd-line-utils/readline/histexpand.c b/cmd-line-utils/readline/histexpand.c
index 47f97e9a6f7..a09be00a859 100644
--- a/cmd-line-utils/readline/histexpand.c
+++ b/cmd-line-utils/readline/histexpand.c
@@ -87,14 +87,14 @@ char history_comment_char = '\0';
/* The list of characters which inhibit the expansion of text if found
immediately following history_expansion_char. */
-char *history_no_expand_chars = " \t\n\r=";
+char *history_no_expand_chars = (char*) " \t\n\r=";
/* If set to a non-zero value, single quotes inhibit history expansion.
The default is 0. */
int history_quotes_inhibit_expansion = 0;
/* Used to split words by history_tokenize_internal. */
-char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
+char *history_word_delimiters = (char*) HISTORY_WORD_DELIMITERS;
/* If set, this points to a function that is called to verify that a
particular history expansion should be performed. */
@@ -203,7 +203,7 @@ get_history_event (string, caller_index, delimiting_quote)
}
/* Only a closing `?' or a newline delimit a substring search string. */
- for (local_index = i; c = string[i]; i++)
+ for (local_index = i; (c = string[i]); i++)
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c
index 7d340b346d4..a7d6a68098e 100644
--- a/cmd-line-utils/readline/histfile.c
+++ b/cmd-line-utils/readline/histfile.c
@@ -184,7 +184,8 @@ read_history_range (filename, from, to)
file_size = (size_t)finfo.st_size;
/* check for overflow on very large files */
- if (file_size != finfo.st_size || file_size + 1 < file_size)
+ if ((long long) file_size != (long long) finfo.st_size ||
+ file_size + 1 < file_size)
{
errno = overflow_errno;
goto error_and_exit;
diff --git a/cmd-line-utils/readline/input.c b/cmd-line-utils/readline/input.c
index 1981061eac6..b2f8016050d 100644
--- a/cmd-line-utils/readline/input.c
+++ b/cmd-line-utils/readline/input.c
@@ -405,7 +405,7 @@ rl_read_key ()
else
{
/* If input is coming from a macro, then use that. */
- if (c = _rl_next_macro_key ())
+ if ((c= _rl_next_macro_key ()))
return (c);
/* If the user has an event function, then call it periodically. */
diff --git a/cmd-line-utils/readline/isearch.c b/cmd-line-utils/readline/isearch.c
index f7b0f1404e9..9071695dda8 100644
--- a/cmd-line-utils/readline/isearch.c
+++ b/cmd-line-utils/readline/isearch.c
@@ -68,7 +68,7 @@ static char *prev_line_found;
static char *last_isearch_string;
static int last_isearch_string_len;
-static char *default_isearch_terminators = "\033\012";
+static char *default_isearch_terminators = (char*) "\033\012";
/* Search backwards through the history looking for a string which is typed
interactively. Start with the current line. */
@@ -94,9 +94,8 @@ rl_forward_search_history (sign, key)
WHERE is the history list number of the current line. If it is
-1, then this line is the starting one. */
static void
-rl_display_search (search_string, reverse_p, where)
- char *search_string;
- int reverse_p, where;
+rl_display_search (char *search_string, int reverse_p,
+ int where __attribute__((unused)))
{
char *message;
int msglen, searchlen;
@@ -143,8 +142,7 @@ rl_display_search (search_string, reverse_p, where)
DIRECTION is which direction to search; >= 0 means forward, < 0 means
backwards. */
static int
-rl_search_history (direction, invoking_key)
- int direction, invoking_key;
+rl_search_history (int direction, int invoking_key __attribute__((unused)))
{
/* The string that the user types in to search for. */
char *search_string;
diff --git a/cmd-line-utils/readline/kill.c b/cmd-line-utils/readline/kill.c
index 061bdafcf9a..4d31a8ff170 100644
--- a/cmd-line-utils/readline/kill.c
+++ b/cmd-line-utils/readline/kill.c
@@ -76,8 +76,7 @@ static int rl_yank_nth_arg_internal PARAMS((int, int, int));
/* How to say that you only want to save a certain amount
of kill material. */
int
-rl_set_retained_kills (num)
- int num;
+rl_set_retained_kills (int num __attribute__((unused)))
{
return 0;
}
@@ -293,8 +292,8 @@ rl_backward_kill_line (direction, ignore)
/* Kill the whole line, no matter where point is. */
int
-rl_kill_full_line (count, ignore)
- int count, ignore;
+rl_kill_full_line (int count __attribute__((unused)),
+ int ignore __attribute__((unused)))
{
rl_begin_undo_group ();
rl_point = 0;
@@ -311,8 +310,7 @@ rl_kill_full_line (count, ignore)
/* This does what C-w does in Unix. We can't prevent people from
using behaviour that they expect. */
int
-rl_unix_word_rubout (count, key)
- int count, key;
+rl_unix_word_rubout (int count, int key __attribute__((unused)))
{
int orig_point;
@@ -344,8 +342,7 @@ rl_unix_word_rubout (count, key)
/* This deletes one filename component in a Unix pathname. That is, it
deletes backward to directory separator (`/') or whitespace. */
int
-rl_unix_filename_rubout (count, key)
- int count, key;
+rl_unix_filename_rubout (int count, int key __attribute__((unused)))
{
int orig_point, c;
@@ -388,8 +385,8 @@ rl_unix_filename_rubout (count, key)
into the line at all, and if you aren't, then you know what you are
doing. */
int
-rl_unix_line_discard (count, key)
- int count, key;
+rl_unix_line_discard (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (rl_point == 0)
rl_ding ();
@@ -425,16 +422,16 @@ region_kill_internal (delete)
/* Copy the text in the region to the kill ring. */
int
-rl_copy_region_to_kill (count, ignore)
- int count, ignore;
+rl_copy_region_to_kill (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
return (region_kill_internal (0));
}
/* Kill the text between the point and mark. */
int
-rl_kill_region (count, ignore)
- int count, ignore;
+rl_kill_region (int count __attribute__((unused)),
+ int ignore __attribute__((unused)))
{
int r, npoint;
@@ -498,8 +495,7 @@ rl_copy_backward_word (count, key)
/* Yank back the last killed text. This ignores arguments. */
int
-rl_yank (count, ignore)
- int count, ignore;
+rl_yank (int count __attribute__((unused)), int ignore __attribute__((unused)))
{
if (rl_kill_ring == 0)
{
@@ -517,8 +513,7 @@ rl_yank (count, ignore)
delete that text from the line, rotate the index down, and
yank back some other text. */
int
-rl_yank_pop (count, key)
- int count, key;
+rl_yank_pop (int count __attribute__((unused)), int key __attribute__((unused)))
{
int l, n;
diff --git a/cmd-line-utils/readline/macro.c b/cmd-line-utils/readline/macro.c
index f7b77a831b8..8727285e181 100644
--- a/cmd-line-utils/readline/macro.c
+++ b/cmd-line-utils/readline/macro.c
@@ -189,8 +189,8 @@ _rl_kill_kbd_macro ()
definition to the end of the existing macro, and start by
re-executing the existing macro. */
int
-rl_start_kbd_macro (ignore1, ignore2)
- int ignore1, ignore2;
+rl_start_kbd_macro (int ignore1 __attribute__((unused)),
+ int ignore2 __attribute__((unused)))
{
if (RL_ISSTATE (RL_STATE_MACRODEF))
{
@@ -214,8 +214,7 @@ rl_start_kbd_macro (ignore1, ignore2)
A numeric argument says to execute the macro right now,
that many times, counting the definition as the first time. */
int
-rl_end_kbd_macro (count, ignore)
- int count, ignore;
+rl_end_kbd_macro (int count, int ignore __attribute__((unused)))
{
if (RL_ISSTATE (RL_STATE_MACRODEF) == 0)
{
@@ -234,8 +233,7 @@ rl_end_kbd_macro (count, ignore)
/* Execute the most recently defined keyboard macro.
COUNT says how many times to execute it. */
int
-rl_call_last_kbd_macro (count, ignore)
- int count, ignore;
+rl_call_last_kbd_macro (int count, int ignore __attribute__((unused)))
{
if (current_macro == 0)
_rl_abort_internal ();
diff --git a/cmd-line-utils/readline/misc.c b/cmd-line-utils/readline/misc.c
index 810b940edab..c8739d0d750 100644
--- a/cmd-line-utils/readline/misc.c
+++ b/cmd-line-utils/readline/misc.c
@@ -154,8 +154,7 @@ rl_digit_loop ()
/* Add the current digit to the argument in progress. */
int
-rl_digit_argument (ignore, key)
- int ignore, key;
+rl_digit_argument (int ignore __attribute__((unused)), int key)
{
rl_execute_next (key);
return (rl_digit_loop ());
@@ -184,8 +183,8 @@ _rl_init_argument ()
Read a key. If the key has nothing to do with arguments, then
dispatch on it. If the key is the abort character then abort. */
int
-rl_universal_argument (count, key)
- int count, key;
+rl_universal_argument (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
rl_numeric_arg *= 4;
return (rl_digit_loop ());
@@ -314,9 +313,7 @@ _rl_history_set_point ()
}
void
-rl_replace_from_history (entry, flags)
- HIST_ENTRY *entry;
- int flags; /* currently unused */
+rl_replace_from_history (HIST_ENTRY *entry, int flags __attribute__((unused)))
{
/* Can't call with `1' because rl_undo_list might point to an undo list
from a history entry, just like we're setting up here. */
@@ -342,16 +339,15 @@ rl_replace_from_history (entry, flags)
/* Meta-< goes to the start of the history. */
int
-rl_beginning_of_history (count, key)
- int count, key;
+rl_beginning_of_history (int count __attribute__((unused)), int key)
{
return (rl_get_previous_history (1 + where_history (), key));
}
/* Meta-> goes to the end of the history. (The current line). */
int
-rl_end_of_history (count, key)
- int count, key;
+rl_end_of_history (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
rl_maybe_replace_line ();
using_history ();
@@ -455,8 +451,7 @@ rl_get_previous_history (count, key)
/* **************************************************************** */
/* How to toggle back and forth between editing modes. */
int
-rl_vi_editing_mode (count, key)
- int count, key;
+rl_vi_editing_mode (int count __attribute__((unused)), int key)
{
#if defined (VI_MODE)
_rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
@@ -468,8 +463,8 @@ rl_vi_editing_mode (count, key)
}
int
-rl_emacs_editing_mode (count, key)
- int count, key;
+rl_emacs_editing_mode (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
rl_editing_mode = emacs_mode;
_rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
@@ -479,8 +474,7 @@ rl_emacs_editing_mode (count, key)
/* Function for the rest of the library to use to set insert/overwrite mode. */
void
-_rl_set_insert_mode (im, force)
- int im, force;
+_rl_set_insert_mode (int im, int force __attribute__((unused)))
{
#ifdef CURSOR_MODE
_rl_set_cursor (im, force);
@@ -492,8 +486,7 @@ _rl_set_insert_mode (im, force)
/* Toggle overwrite mode. A positive explicit argument selects overwrite
mode. A negative or zero explicit argument selects insert mode. */
int
-rl_overwrite_mode (count, key)
- int count, key;
+rl_overwrite_mode (int count, int key __attribute__((unused)))
{
if (rl_explicit_arg == 0)
_rl_set_insert_mode (rl_insert_mode ^ 1, 0);
diff --git a/cmd-line-utils/readline/nls.c b/cmd-line-utils/readline/nls.c
index 4f28152f316..73ad0227195 100644
--- a/cmd-line-utils/readline/nls.c
+++ b/cmd-line-utils/readline/nls.c
@@ -111,7 +111,7 @@ _rl_init_eightbit ()
if (lspec == 0 || *lspec == 0)
lspec = setlocale (LC_CTYPE, (char *)NULL);
if (lspec == 0)
- lspec = "";
+ lspec = (char*) "";
t = setlocale (LC_CTYPE, lspec);
if (t && *t && (t[0] != 'C' || t[1]) && (STREQ (t, "POSIX") == 0))
diff --git a/cmd-line-utils/readline/readline.c b/cmd-line-utils/readline/readline.c
index e82db84c9dc..dd3724a86d7 100644
--- a/cmd-line-utils/readline/readline.c
+++ b/cmd-line-utils/readline/readline.c
@@ -83,7 +83,9 @@ static void bind_arrow_keys_internal PARAMS((Keymap));
static void bind_arrow_keys PARAMS((void));
static void readline_default_bindings PARAMS((void));
+#ifdef NOT_USED
static void reset_default_bindings PARAMS((void));
+#endif
/* **************************************************************** */
/* */
@@ -866,12 +868,14 @@ readline_default_bindings ()
/* Reset the default bindings for the terminal special characters we're
interested in back to rl_insert and read the new ones. */
+#ifdef NOT_USED
static void
reset_default_bindings ()
{
rl_tty_unset_default_bindings (_rl_keymap);
rl_tty_set_default_bindings (_rl_keymap);
}
+#endif
/* Bind some common arrow key sequences in MAP. */
static void
diff --git a/cmd-line-utils/readline/rltty.c b/cmd-line-utils/readline/rltty.c
index 3e9c71c8df1..ffbae1e08af 100644
--- a/cmd-line-utils/readline/rltty.c
+++ b/cmd-line-utils/readline/rltty.c
@@ -716,8 +716,7 @@ rl_deprep_terminal ()
/* **************************************************************** */
int
-rl_restart_output (count, key)
- int count, key;
+rl_restart_output(int count __attribute__((unused)), int key __attribute__((unused)))
{
int fildes = fileno (rl_outstream);
#if defined (TIOCSTART)
@@ -749,8 +748,7 @@ rl_restart_output (count, key)
}
int
-rl_stop_output (count, key)
- int count, key;
+rl_stop_output(int count __attribute__((unused)), int key __attribute__((unused)))
{
int fildes = fileno (rl_instream);
@@ -867,7 +865,6 @@ rltty_set_default_bindings (kmap)
{
TIOTYPE ttybuff;
int tty;
- static int called = 0;
tty = fileno (rl_instream);
diff --git a/cmd-line-utils/readline/search.c b/cmd-line-utils/readline/search.c
index 1878d2bf031..6479427be2f 100644
--- a/cmd-line-utils/readline/search.c
+++ b/cmd-line-utils/readline/search.c
@@ -303,8 +303,7 @@ noninc_search (dir, pchar)
/* Search forward through the history list for a string. If the vi-mode
code calls this, KEY will be `?'. */
int
-rl_noninc_forward_search (count, key)
- int count, key;
+rl_noninc_forward_search (int count __attribute__((unused)), int key)
{
noninc_search (1, (key == '?') ? '?' : 0);
return 0;
@@ -313,8 +312,7 @@ rl_noninc_forward_search (count, key)
/* Reverse search the history list for a string. If the vi-mode code
calls this, KEY will be `/'. */
int
-rl_noninc_reverse_search (count, key)
- int count, key;
+rl_noninc_reverse_search (int count __attribute__((unused)), int key)
{
noninc_search (-1, (key == '/') ? '/' : 0);
return 0;
@@ -323,8 +321,8 @@ rl_noninc_reverse_search (count, key)
/* Search forward through the history list for the last string searched
for. If there is no saved search string, abort. */
int
-rl_noninc_forward_search_again (count, key)
- int count, key;
+rl_noninc_forward_search_again (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (!noninc_search_string)
{
@@ -338,8 +336,8 @@ rl_noninc_forward_search_again (count, key)
/* Reverse search in the history list for the last string searched
for. If there is no saved search string, abort. */
int
-rl_noninc_reverse_search_again (count, key)
- int count, key;
+rl_noninc_reverse_search_again (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (!noninc_search_string)
{
diff --git a/cmd-line-utils/readline/terminal.c b/cmd-line-utils/readline/terminal.c
index 3545fce5b85..4b900c5d860 100644
--- a/cmd-line-utils/readline/terminal.c
+++ b/cmd-line-utils/readline/terminal.c
@@ -344,7 +344,7 @@ get_term_capabilities (bp)
#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
register int i;
- for (i = 0; i < NUM_TC_STRINGS; i++)
+ for (i = 0; i < (int) NUM_TC_STRINGS; i++)
*(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
#endif
tcap_initialized = 1;
@@ -410,7 +410,7 @@ _rl_init_terminal_io (terminal_name)
/* Everything below here is used by the redisplay code (tputs). */
_rl_screenchars = _rl_screenwidth * _rl_screenheight;
- _rl_term_cr = "\r";
+ _rl_term_cr = (char*) "\r";
_rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
_rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
_rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
@@ -427,7 +427,7 @@ _rl_init_terminal_io (terminal_name)
tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
change that later... */
PC = '\0';
- BC = _rl_term_backspace = "\b";
+ BC = _rl_term_backspace = (char*) "\b";
UP = _rl_term_up;
return 0;
@@ -442,7 +442,7 @@ _rl_init_terminal_io (terminal_name)
UP = _rl_term_up;
if (!_rl_term_cr)
- _rl_term_cr = "\r";
+ _rl_term_cr = (char*) "\r";
_rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
@@ -502,7 +502,7 @@ rl_get_termcap (cap)
if (tcap_initialized == 0)
return ((char *)NULL);
- for (i = 0; i < NUM_TC_STRINGS; i++)
+ for (i = 0; i < (int) NUM_TC_STRINGS; i++)
{
if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
return *(tc_strings[i].tc_value);
diff --git a/cmd-line-utils/readline/text.c b/cmd-line-utils/readline/text.c
index ad7b53ec422..89457be37cd 100644
--- a/cmd-line-utils/readline/text.c
+++ b/cmd-line-utils/readline/text.c
@@ -402,8 +402,7 @@ rl_backward (count, key)
/* Move to the beginning of the line. */
int
-rl_beg_of_line (count, key)
- int count, key;
+rl_beg_of_line (int count __attribute__((unused)), int key __attribute__((unused)))
{
rl_point = 0;
return 0;
@@ -411,8 +410,7 @@ rl_beg_of_line (count, key)
/* Move to the end of the line. */
int
-rl_end_of_line (count, key)
- int count, key;
+rl_end_of_line (int count __attribute__((unused)), int key __attribute__((unused)))
{
rl_point = rl_end;
return 0;
@@ -508,8 +506,7 @@ rl_backward_word (count, key)
/* Clear the current line. Numeric argument to C-l does this. */
int
-rl_refresh_line (ignore1, ignore2)
- int ignore1, ignore2;
+rl_refresh_line (int count __attribute__((unused)), int key __attribute__((unused)))
{
int curr_line;
@@ -547,8 +544,7 @@ rl_clear_screen (count, key)
}
int
-rl_arrow_keys (count, c)
- int count, c;
+rl_arrow_keys (int count, int c __attribute__((unused)))
{
int ch;
@@ -596,7 +592,7 @@ rl_arrow_keys (count, c)
#ifdef HANDLE_MULTIBYTE
static char pending_bytes[MB_LEN_MAX];
static int pending_bytes_length = 0;
-static mbstate_t ps = {0};
+static mbstate_t ps;
#endif
/* Insert the character C at the current location, moving point forward.
@@ -832,8 +828,7 @@ rl_insert (count, c)
/* Insert the next typed character verbatim. */
int
-rl_quoted_insert (count, key)
- int count, key;
+rl_quoted_insert (int count, int key __attribute__((unused)))
{
int c;
@@ -854,8 +849,7 @@ rl_quoted_insert (count, key)
/* Insert a tab character. */
int
-rl_tab_insert (count, key)
- int count, key;
+rl_tab_insert (int count, int key __attribute__((unused)))
{
return (_rl_insert_char (count, '\t'));
}
@@ -864,8 +858,7 @@ rl_tab_insert (count, key)
KEY is the key that invoked this command. I guess it could have
meaning in the future. */
int
-rl_newline (count, key)
- int count, key;
+rl_newline (int count __attribute__((unused)), int key __attribute__((unused)))
{
rl_done = 1;
@@ -898,8 +891,8 @@ rl_newline (count, key)
is just a stub, you bind keys to it and the code in _rl_dispatch ()
is special cased. */
int
-rl_do_lowercase_version (ignore1, ignore2)
- int ignore1, ignore2;
+rl_do_lowercase_version (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
return 0;
}
@@ -1093,8 +1086,8 @@ rl_rubout_or_delete (count, key)
/* Delete all spaces and tabs around point. */
int
-rl_delete_horizontal_space (count, ignore)
- int count, ignore;
+rl_delete_horizontal_space (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
int start = rl_point;
@@ -1134,14 +1127,13 @@ rl_delete_or_show_completions (count, key)
/* Turn the current line into a comment in shell history.
A K*rn shell style function. */
int
-rl_insert_comment (count, key)
- int count, key;
+rl_insert_comment (int count __attribute__((unused)), int key)
{
char *rl_comment_text;
int rl_comment_len;
rl_beg_of_line (1, key);
- rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
+ rl_comment_text = _rl_comment_begin ? _rl_comment_begin : (char*) RL_COMMENT_BEGIN_DEFAULT;
if (rl_explicit_arg == 0)
rl_insert_text (rl_comment_text);
@@ -1173,24 +1165,21 @@ rl_insert_comment (count, key)
/* Uppercase the word at point. */
int
-rl_upcase_word (count, key)
- int count, key;
+rl_upcase_word (int count, int key __attribute__((unused)))
{
return (rl_change_case (count, UpCase));
}
/* Lowercase the word at point. */
int
-rl_downcase_word (count, key)
- int count, key;
+rl_downcase_word (int count, int key __attribute__((unused)))
{
return (rl_change_case (count, DownCase));
}
/* Upcase the first letter, downcase the rest. */
int
-rl_capitalize_word (count, key)
- int count, key;
+rl_capitalize_word (int count, int key __attribute__((unused)))
{
return (rl_change_case (count, CapCase));
}
@@ -1314,8 +1303,7 @@ rl_transpose_words (count, key)
/* Transpose the characters at point. If point is at the end of the line,
then transpose the characters before point. */
int
-rl_transpose_chars (count, key)
- int count, key;
+rl_transpose_chars (int count, int key __attribute__((unused)))
{
#if defined (HANDLE_MULTIBYTE)
char *dummy;
@@ -1486,15 +1474,13 @@ _rl_char_search (count, fdir, bdir)
#endif /* !HANDLE_MULTIBYTE */
int
-rl_char_search (count, key)
- int count, key;
+rl_char_search (int count, int key __attribute__((unused)))
{
return (_rl_char_search (count, FFIND, BFIND));
}
int
-rl_backward_char_search (count, key)
- int count, key;
+rl_backward_char_search (int count, int key __attribute__((unused)))
{
return (_rl_char_search (count, BFIND, FFIND));
}
@@ -1519,16 +1505,15 @@ _rl_set_mark_at_pos (position)
/* A bindable command to set the mark. */
int
-rl_set_mark (count, key)
- int count, key;
+rl_set_mark (int count, int key __attribute__((unused)))
{
return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
}
/* Exchange the position of mark and point. */
int
-rl_exchange_point_and_mark (count, key)
- int count, key;
+rl_exchange_point_and_mark (int count __attribute__((unused)),
+ int key __attribute__((unused)))
{
if (rl_mark > rl_end)
rl_mark = -1;
diff --git a/cmd-line-utils/readline/tilde.c b/cmd-line-utils/readline/tilde.c
index c44357ffbea..91eead0d9e2 100644
--- a/cmd-line-utils/readline/tilde.c
+++ b/cmd-line-utils/readline/tilde.c
@@ -190,7 +190,7 @@ tilde_expand (string)
int result_size, result_index;
result_index = result_size = 0;
- if (result = strchr (string, '~'))
+ if ((result = strchr (string, '~')))
result = (char *)xmalloc (result_size = (strlen (string) + 16));
else
result = (char *)xmalloc (result_size = (strlen (string) + 1));
diff --git a/cmd-line-utils/readline/undo.c b/cmd-line-utils/readline/undo.c
index 48baded332a..b4b5a6511ba 100644
--- a/cmd-line-utils/readline/undo.c
+++ b/cmd-line-utils/readline/undo.c
@@ -175,7 +175,7 @@ _rl_fix_last_undo_of_type (type, start, end)
for (rl = rl_undo_list; rl; rl = rl->next)
{
- if (rl->what == type)
+ if (rl->what == (uint) type)
{
rl->start = start;
rl->end = end;
@@ -226,8 +226,7 @@ rl_modifying (start, end)
/* Revert the current line to its previous state. */
int
-rl_revert_line (count, key)
- int count, key;
+rl_revert_line (int count __attribute__((unused)), int key __attribute__((unused)))
{
if (!rl_undo_list)
rl_ding ();
@@ -241,8 +240,7 @@ rl_revert_line (count, key)
/* Do some undoing of things that were done. */
int
-rl_undo_command (count, key)
- int count, key;
+rl_undo_command (int count, int key __attribute__((unused)))
{
if (count < 0)
return 0; /* Nothing to do. */
diff --git a/cmd-line-utils/readline/util.c b/cmd-line-utils/readline/util.c
index 43478aaf1ac..d5fe51a7bf2 100644
--- a/cmd-line-utils/readline/util.c
+++ b/cmd-line-utils/readline/util.c
@@ -95,15 +95,13 @@ _rl_abort_internal ()
}
int
-rl_abort (count, key)
- int count, key;
+rl_abort (int count __attribute__((unused)), int key __attribute__((unused)))
{
return (_rl_abort_internal ());
}
int
-rl_tty_status (count, key)
- int count, key;
+rl_tty_status (int count __attribute__((unused)), int key __attribute__((unused)))
{
#if defined (TIOCSTAT)
ioctl (1, TIOCSTAT, (char *)0);
@@ -152,8 +150,7 @@ rl_extend_line_buffer (len)
/* A function for simple tilde expansion. */
int
-rl_tilde_expand (ignore, key)
- int ignore, key;
+rl_tilde_expand (int ignore __attribute__((unused)), int key __attribute__((unused)))
{
register int start, end;
char *homedir, *temp;
diff --git a/cmd-line-utils/readline/vi_mode.c b/cmd-line-utils/readline/vi_mode.c
index 9a8cfdd7200..4d1cc56117d 100644
--- a/cmd-line-utils/readline/vi_mode.c
+++ b/cmd-line-utils/readline/vi_mode.c
@@ -112,7 +112,7 @@ _rl_vi_initialize_line ()
{
register int i;
- for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
+ for (i = 0; i < (int) (sizeof (vi_mark_chars) / sizeof (int)); i++)
vi_mark_chars[i] = -1;
}
@@ -166,8 +166,7 @@ _rl_vi_stuff_insert (count)
redo a text modification command. The default for _rl_vi_last_command
puts you back into insert mode. */
int
-rl_vi_redo (count, c)
- int count, c;
+rl_vi_redo (int count, int c __attribute__((unused)))
{
int r;
@@ -205,8 +204,7 @@ rl_vi_undo (count, key)
/* Yank the nth arg from the previous line into this line at point. */
int
-rl_vi_yank_arg (count, key)
- int count, key;
+rl_vi_yank_arg (int count, int key __attribute__((unused)))
{
/* Readline thinks that the first word on a line is the 0th, while vi
thinks the first word on a line is the 1st. Compensate. */
@@ -286,8 +284,7 @@ rl_vi_search (count, key)
/* Completion, from vi's point of view. */
int
-rl_vi_complete (ignore, key)
- int ignore, key;
+rl_vi_complete (int ignore __attribute__((unused)), int key)
{
if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
{
@@ -313,8 +310,7 @@ rl_vi_complete (ignore, key)
/* Tilde expansion for vi mode. */
int
-rl_vi_tilde_expand (ignore, key)
- int ignore, key;
+rl_vi_tilde_expand (int ignore __attribute__((unused)), int key)
{
rl_tilde_expand (0, key);
rl_vi_start_inserting (key, 1, rl_arg_sign);
@@ -384,8 +380,7 @@ rl_vi_end_word (count, key)
/* Move forward a word the way that 'W' does. */
int
-rl_vi_fWord (count, ignore)
- int count, ignore;
+rl_vi_fWord (int count, int ignore __attribute__((unused)))
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -401,8 +396,7 @@ rl_vi_fWord (count, ignore)
}
int
-rl_vi_bWord (count, ignore)
- int count, ignore;
+rl_vi_bWord (int count, int ignore __attribute__((unused)))
{
while (count-- && rl_point > 0)
{
@@ -425,8 +419,7 @@ rl_vi_bWord (count, ignore)
}
int
-rl_vi_eWord (count, ignore)
- int count, ignore;
+rl_vi_eWord(int count, int ignore __attribute__((unused)))
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -456,8 +449,7 @@ rl_vi_eWord (count, ignore)
}
int
-rl_vi_fword (count, ignore)
- int count, ignore;
+rl_vi_fword (int count, int ignore __attribute__((unused)))
{
while (count-- && rl_point < (rl_end - 1))
{
@@ -482,8 +474,7 @@ rl_vi_fword (count, ignore)
}
int
-rl_vi_bword (count, ignore)
- int count, ignore;
+rl_vi_bword (int count, int ignore __attribute__((unused)))
{
while (count-- && rl_point > 0)
{
@@ -521,8 +512,7 @@ rl_vi_bword (count, ignore)
}
int
-rl_vi_eword (count, ignore)
- int count, ignore;
+rl_vi_eword (int count, int ignore __attribute__((unused)))
{
while (count-- && rl_point < rl_end - 1)
{
@@ -546,8 +536,7 @@ rl_vi_eword (count, ignore)
}
int
-rl_vi_insert_beg (count, key)
- int count, key;
+rl_vi_insert_beg (int count __attribute__((unused)), int key)
{
rl_beg_of_line (1, key);
rl_vi_insertion_mode (1, key);
@@ -555,8 +544,7 @@ rl_vi_insert_beg (count, key)
}
int
-rl_vi_append_mode (count, key)
- int count, key;
+rl_vi_append_mode (int count __attribute__((unused)), int key)
{
if (rl_point < rl_end)
{
@@ -575,8 +563,7 @@ rl_vi_append_mode (count, key)
}
int
-rl_vi_append_eol (count, key)
- int count, key;
+rl_vi_append_eol (int count __attribute__((unused)), int key)
{
rl_end_of_line (1, key);
rl_vi_append_mode (1, key);
@@ -585,8 +572,7 @@ rl_vi_append_eol (count, key)
/* What to do in the case of C-d. */
int
-rl_vi_eof_maybe (count, c)
- int count, c;
+rl_vi_eof_maybe (int count __attribute__((unused)), int c __attribute__((unused)))
{
return (rl_newline (1, '\n'));
}
@@ -596,8 +582,7 @@ rl_vi_eof_maybe (count, c)
/* Switching from one mode to the other really just involves
switching keymaps. */
int
-rl_vi_insertion_mode (count, key)
- int count, key;
+rl_vi_insertion_mode (int count __attribute__((unused)), int key)
{
_rl_keymap = vi_insertion_keymap;
_rl_vi_last_key_before_insert = key;
@@ -659,8 +644,7 @@ _rl_vi_done_inserting ()
}
int
-rl_vi_movement_mode (count, key)
- int count, key;
+rl_vi_movement_mode (int count __attribute__((unused)), int key)
{
if (rl_point > 0)
rl_backward_char (1, key);
@@ -729,8 +713,7 @@ _rl_vi_change_mbchar_case (count)
#endif
int
-rl_vi_change_case (count, ignore)
- int count, ignore;
+rl_vi_change_case (int count, int ignore __attribute__((unused)))
{
int c, p;
@@ -959,8 +942,7 @@ rl_digit_loop1 ()
}
int
-rl_vi_delete_to (count, key)
- int count, key;
+rl_vi_delete_to (int count __attribute__((unused)), int key)
{
int c;
@@ -985,8 +967,7 @@ rl_vi_delete_to (count, key)
}
int
-rl_vi_change_to (count, key)
- int count, key;
+rl_vi_change_to (int count __attribute__((unused)), int key)
{
int c, start_pos;
@@ -1038,8 +1019,7 @@ rl_vi_change_to (count, key)
}
int
-rl_vi_yank_to (count, key)
- int count, key;
+rl_vi_yank_to (int count __attribute__((unused)), int key)
{
int c, save = rl_point;
@@ -1094,8 +1074,7 @@ rl_vi_delete (count, key)
}
int
-rl_vi_back_to_indent (count, key)
- int count, key;
+rl_vi_back_to_indent (int count __attribute__((unused)), int key)
{
rl_beg_of_line (1, key);
while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
@@ -1104,8 +1083,7 @@ rl_vi_back_to_indent (count, key)
}
int
-rl_vi_first_print (count, key)
- int count, key;
+rl_vi_first_print (int count __attribute__((unused)), int key)
{
return (rl_vi_back_to_indent (1, key));
}
@@ -1173,8 +1151,7 @@ rl_vi_char_search (count, key)
/* Match brackets */
int
-rl_vi_match (ignore, key)
- int ignore, key;
+rl_vi_match (int ignore __attribute__((unused)), int key)
{
int count = 1, brack, pos, tmp, pre;
@@ -1284,8 +1261,7 @@ rl_vi_bracktype (c)
for test against 033 or ^C. Make sure that _rl_read_mbchar does
this right. */
int
-rl_vi_change_char (count, key)
- int count, key;
+rl_vi_change_char (int count, int key __attribute__((unused)))
{
int c, p;
@@ -1389,8 +1365,7 @@ rl_vi_overstrike_delete (count, key)
}
int
-rl_vi_replace (count, key)
- int count, key;
+rl_vi_replace (int count __attribute__((unused)), int key __attribute__((unused)))
{
int i;
@@ -1450,8 +1425,7 @@ rl_vi_possible_completions()
/* Functions to save and restore marks. */
int
-rl_vi_set_mark (count, key)
- int count, key;
+rl_vi_set_mark (int count __attribute__((unused)), int key __attribute__((unused)))
{
int ch;
@@ -1470,8 +1444,7 @@ rl_vi_set_mark (count, key)
}
int
-rl_vi_goto_mark (count, key)
- int count, key;
+rl_vi_goto_mark (int count __attribute__((unused)), int key __attribute__((unused)))
{
int ch;
diff --git a/config/ac-macros/ha_berkeley.m4 b/config/ac-macros/ha_berkeley.m4
index 732c7730816..82786436720 100644
--- a/config/ac-macros/ha_berkeley.m4
+++ b/config/ac-macros/ha_berkeley.m4
@@ -243,20 +243,20 @@ bdb_version_ok=yes
])
AC_DEFUN([MYSQL_TOP_BUILDDIR], [
+ # Remove trailing "./" if any
+ [$1]=`echo $[$1] | sed -e 's,^\./,,'`
case "$[$1]" in
- /* ) ;; # don't do anything with an absolute path
- "$srcdir"/* )
+ "bdb" | "$srcdir/bdb" | "$top_srcdir/bdb" | "$abs_top_srcdir/bdb" )
# If BDB is under the source directory, we need to look under the
# build directory for bdb/build_unix.
- # NOTE: I'm being lazy, and assuming the user did not specify
- # something like --with-berkeley-db=bdb (it would be missing "./").
- [$1]="\$(top_builddir)/"`echo "$[$1]" | sed -e "s,^$srcdir/,,"`
+ [$1]="\$(top_builddir)/bdb"
;;
+ /* ) ;; # Other absolute path is assume to be external BDB directory
* )
AC_MSG_ERROR([The BDB directory must be directly under the MySQL source directory, or be specified using the full path. ('$srcdir'; '$[$1]')])
;;
esac
- if test X"$[$1]" != "/"
+ if test X"$[$1]" != X"/"
then
[$1]=`echo $[$1] | sed -e 's,/$,,'`
fi
diff --git a/config/ac-macros/ha_innodb.m4 b/config/ac-macros/ha_innodb.m4
index 17f0fab3e90..f670eeb9751 100644
--- a/config/ac-macros/ha_innodb.m4
+++ b/config/ac-macros/ha_innodb.m4
@@ -20,7 +20,7 @@ AC_DEFUN([MYSQL_CHECK_INNODB], [
AC_MSG_RESULT([Using Innodb])
AC_DEFINE([HAVE_INNOBASE_DB], [1], [Using Innobase DB])
have_innodb="yes"
- innodb_includes="-I../innobase/include"
+ innodb_includes="-I\$(top_builddir)/innobase/include -I\$(top_srcdir)/innobase/include"
innodb_system_libs=""
dnl Some libs are listed several times, in order for gcc to sort out
dnl circular references.
diff --git a/config/ac-macros/ha_ndbcluster.m4 b/config/ac-macros/ha_ndbcluster.m4
index 2ff598242e4..8e953544df9 100644
--- a/config/ac-macros/ha_ndbcluster.m4
+++ b/config/ac-macros/ha_ndbcluster.m4
@@ -140,7 +140,7 @@ AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
AC_MSG_RESULT([Using NDB Cluster])
AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB])
have_ndbcluster="yes"
- ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi -I../ndb/include/mgmapi"
+ ndbcluster_includes="-I\$(top_builddir)/ndb/include -I\$(top_srcdir)/ndb/include -I\$(top_srcdir)/ndb/include/ndbapi -I\$(top_srcdir)/ndb/include/mgmapi"
ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a"
ndbcluster_system_libs=""
ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la"
diff --git a/configure.in b/configure.in
index 55da1dfb241..f6a6eedac70 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line!
# remember to also change ndb version below and update version.c in ndb
-AM_INIT_AUTOMAKE(mysql, 5.0.27)
+AM_INIT_AUTOMAKE(mysql, 5.0.32)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
@@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0
# ndb version
NDB_VERSION_MAJOR=5
NDB_VERSION_MINOR=0
-NDB_VERSION_BUILD=27
+NDB_VERSION_BUILD=32
NDB_VERSION_STATUS=""
# Set all version vars based on $VERSION. How do we do this more elegant ?
@@ -449,6 +449,10 @@ AC_SUBST(DOXYGEN)
AC_SUBST(PDFLATEX)
AC_SUBST(MAKEINDEX)
+# icheck, used for ABI check
+AC_PATH_PROG(ICHECK, icheck, no)
+AC_SUBST(ICHECK)
+
# Lock for PS
AC_PATH_PROG(PS, ps, ps)
AC_MSG_CHECKING("how to check if pid exists")
@@ -1176,12 +1180,16 @@ EOF
cat > $filesed << EOF
s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
s,\(: conf_to_src\),\1.linux,
+s,libyassl.la,.libs/libyassl.a,
+s,libtaocrypt.la,.libs/libtaocrypt.a,
EOF
;;
libmysql_r/Makefile.in)
cat > $filesed << EOF
s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
s,\(: conf_to_src\),\1.linux,
+s,libyassl.la,.libs/libyassl.a,
+s,libtaocrypt.la,.libs/libtaocrypt.a,
EOF
;;
strings/Makefile.in)
@@ -1773,6 +1781,13 @@ then
AC_MSG_ERROR("MySQL needs a off_t type.")
fi
+dnl
+dnl check if time_t is unsigned
+dnl
+
+MYSQL_CHECK_TIME_T
+
+
# do we need #pragma interface/#pragma implementation ?
# yes if it's gcc 2.x, and not icc pretending to be gcc, and not cygwin
AC_MSG_CHECKING(the need for @%:@pragma interface/implementation)
diff --git a/dbug/dbug_analyze.c b/dbug/dbug_analyze.c
index 1db056d549c..f1caeea2be4 100644
--- a/dbug/dbug_analyze.c
+++ b/dbug/dbug_analyze.c
@@ -169,7 +169,7 @@ register unsigned long *child_time;
*name_pos = temp->pos;
*time_entered = temp->time;
*child_time = temp->children;
- DBUG_PRINT ("pop", ("%d %d %d",*name_pos,*time_entered,*child_time));
+ DBUG_PRINT ("pop", ("%d %lu %lu",*name_pos,*time_entered,*child_time));
rtnval = stacktop--;
}
DBUG_RETURN (rtnval);
@@ -334,12 +334,12 @@ FILE *inf;
* function is found on the stack.
*/
while (pop (&oldpos, &oldtime, &oldchild)) {
- DBUG_PRINT ("popped", ("%d %d", oldtime, oldchild));
+ DBUG_PRINT ("popped", ("%lu %lu", oldtime, oldchild));
time = fn_time - oldtime;
t = top ();
t -> children += time;
DBUG_PRINT ("update", ("%s", modules[t -> pos].name));
- DBUG_PRINT ("update", ("%d", t -> children));
+ DBUG_PRINT ("update", ("%lu", t -> children));
time -= oldchild;
modules[oldpos].m_time += time;
modules[oldpos].m_calls++;
@@ -520,19 +520,19 @@ register unsigned long int *s_calls, *s_time;
unsigned long int calls, time;
DBUG_ENTER ("out_body");
- DBUG_PRINT ("out_body", ("%d,%d",*s_calls,*s_time));
+ DBUG_PRINT ("out_body", ("%lu,%lu",*s_calls,*s_time));
if (root == MAXPROCS) {
- DBUG_PRINT ("out_body", ("%d,%d",*s_calls,*s_time));
+ DBUG_PRINT ("out_body", ("%lu,%lu",*s_calls,*s_time));
} else {
while (root != MAXPROCS) {
out_body (outf, s_table[root].lchild,s_calls,s_time);
out_item (outf, &modules[s_table[root].pos],&calls,&time);
- DBUG_PRINT ("out_body", ("-- %d -- %d --", calls, time));
+ DBUG_PRINT ("out_body", ("-- %lu -- %lu --", calls, time));
*s_calls += calls;
*s_time += time;
root = s_table[root].rchild;
}
- DBUG_PRINT ("out_body", ("%d,%d", *s_calls, *s_time));
+ DBUG_PRINT ("out_body", ("%lu,%lu", *s_calls, *s_time));
}
DBUG_VOID_RETURN;
}
diff --git a/extra/replace.c b/extra/replace.c
index 9acf1620d49..cad3589819b 100644
--- a/extra/replace.c
+++ b/extra/replace.c
@@ -1052,8 +1052,10 @@ static int convert_file(REPLACE *rep, my_string name)
{
int error;
FILE *in,*out;
- char dir_buff[FN_REFLEN], tempname[FN_REFLEN];
- char link_name[FN_REFLEN], *org_name = name;
+ char dir_buff[FN_REFLEN], tempname[FN_REFLEN], *org_name = name;
+#ifdef HAVE_READLINK
+ char link_name[FN_REFLEN];
+#endif
File temp_file;
DBUG_ENTER("convert_file");
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
index 28e9d237622..0edff289b61 100644
--- a/extra/yassl/include/yassl_int.hpp
+++ b/extra/yassl/include/yassl_int.hpp
@@ -40,6 +40,13 @@
#include "lock.hpp"
#include "openssl/ssl.h" // ASN1_STRING and DH
+// Check if _POSIX_THREADS should be forced
+#if !defined(_POSIX_THREADS) && (defined(__NETWARE__) || defined(__hpux))
+// HPUX does not define _POSIX_THREADS as it's not _fully_ implemented
+// Netware supports pthreads but does not announce it
+#define _POSIX_THREADS
+#endif
+
#ifdef _POSIX_THREADS
#include <pthread.h>
#endif
diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am
index 910bbbdd13f..bc57e7d05ba 100644
--- a/extra/yassl/src/Makefile.am
+++ b/extra/yassl/src/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = -I../include -I../taocrypt/include -I../taocrypt/mySTL
+INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../taocrypt/include -I$(srcdir)/../taocrypt/mySTL
noinst_LTLIBRARIES = libyassl.la
libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
index a008ea7228b..fe4661b5946 100644
--- a/extra/yassl/src/ssl.cpp
+++ b/extra/yassl/src/ssl.cpp
@@ -918,7 +918,7 @@ void ERR_print_errors_fp(FILE* /*fp*/)
char* ERR_error_string(unsigned long errNumber, char* buffer)
{
- static char* msg = "Please supply a buffer for error string";
+ static char* msg = (char*) "Please supply a buffer for error string";
if (buffer) {
SetErrorString(YasslError(errNumber), buffer);
diff --git a/extra/yassl/taocrypt/benchmark/Makefile.am b/extra/yassl/taocrypt/benchmark/Makefile.am
index a5b1713427c..674406d8ad6 100644
--- a/extra/yassl/taocrypt/benchmark/Makefile.am
+++ b/extra/yassl/taocrypt/benchmark/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = -I../include -I../mySTL
+INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../mySTL
bin_PROGRAMS = benchmark
benchmark_SOURCES = benchmark.cpp
benchmark_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la
diff --git a/extra/yassl/taocrypt/benchmark/benchmark.dsp b/extra/yassl/taocrypt/benchmark/benchmark.dsp
index ed8fef316bb..878dc2b2783 100644
--- a/extra/yassl/taocrypt/benchmark/benchmark.dsp
+++ b/extra/yassl/taocrypt/benchmark/benchmark.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\include" /I "..\..\mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\include" /I "..\mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -65,7 +65,7 @@ LINK32=link.exe
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\..\mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
diff --git a/extra/yassl/taocrypt/include/algebra.hpp b/extra/yassl/taocrypt/include/algebra.hpp
index 07fc405f093..535ce2599c4 100644
--- a/extra/yassl/taocrypt/include/algebra.hpp
+++ b/extra/yassl/taocrypt/include/algebra.hpp
@@ -75,7 +75,7 @@ public:
typedef Integer Element;
AbstractRing() : AbstractGroup() {m_mg.m_pRing = this;}
- AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
+ AbstractRing(const AbstractRing &source) :AbstractGroup() {m_mg.m_pRing = this;}
AbstractRing& operator=(const AbstractRing &source) {return *this;}
virtual bool IsUnit(const Element &a) const =0;
diff --git a/extra/yassl/taocrypt/include/hmac.hpp b/extra/yassl/taocrypt/include/hmac.hpp
index d46a6d4e7c3..b710c3aa499 100644
--- a/extra/yassl/taocrypt/include/hmac.hpp
+++ b/extra/yassl/taocrypt/include/hmac.hpp
@@ -60,12 +60,12 @@ private:
T mac_;
// MSVC 6 HACK, gives compiler error if calculated in array
- enum { BSIZE = T::BLOCK_SIZE / sizeof(word32),
- DSIZE = T::DIGEST_SIZE / sizeof(word32) };
+ enum { HMAC_BSIZE = T::BLOCK_SIZE / sizeof(word32),
+ HMAC_DSIZE = T::DIGEST_SIZE / sizeof(word32) };
- word32 ip_[BSIZE]; // align ipad_ on word32
- word32 op_[BSIZE]; // align opad_ on word32
- word32 innerH_[DSIZE]; // align innerHash_ on word32
+ word32 ip_[HMAC_BSIZE]; // align ipad_ on word32
+ word32 op_[HMAC_BSIZE]; // align opad_ on word32
+ word32 innerH_[HMAC_DSIZE]; // align innerHash_ on word32
void KeyInnerHash();
diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am
index 6d02a625275..61032d4c381 100644
--- a/extra/yassl/taocrypt/src/Makefile.am
+++ b/extra/yassl/taocrypt/src/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = -I../include -I../mySTL
+INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../mySTL
noinst_LTLIBRARIES = libtaocrypt.la
diff --git a/extra/yassl/taocrypt/taocrypt.dsp b/extra/yassl/taocrypt/taocrypt.dsp
index 19edf7b2f22..3f1b47990ad 100644
--- a/extra/yassl/taocrypt/taocrypt.dsp
+++ b/extra/yassl/taocrypt/taocrypt.dsp
@@ -41,7 +41,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "include" /I "..\mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -64,7 +64,7 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "..\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# SUBTRACT CPP /Fr
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
diff --git a/extra/yassl/taocrypt/taocrypt.vcproj b/extra/yassl/taocrypt/taocrypt.vcproj
index 7eef7b82db7..7ffcb664346 100755
--- a/extra/yassl/taocrypt/taocrypt.vcproj
+++ b/extra/yassl/taocrypt/taocrypt.vcproj
@@ -21,7 +21,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="include,..\mySTL"
+ AdditionalIncludeDirectories="include,mySTL"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
ExceptionHandling="FALSE"
BasicRuntimeChecks="3"
@@ -75,7 +75,7 @@
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="include,..\mySTL"
+ AdditionalIncludeDirectories="include,mySTL"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
StringPooling="TRUE"
ExceptionHandling="FALSE"
diff --git a/extra/yassl/taocrypt/test.dsp b/extra/yassl/taocrypt/test.dsp
index a5e05ed0ac0..1084f8e06e3 100644
--- a/extra/yassl/taocrypt/test.dsp
+++ b/extra/yassl/taocrypt/test.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "../mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "../mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
diff --git a/extra/yassl/taocrypt/test/Makefile.am b/extra/yassl/taocrypt/test/Makefile.am
index 988d00c7bef..25e1a98fc94 100644
--- a/extra/yassl/taocrypt/test/Makefile.am
+++ b/extra/yassl/taocrypt/test/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = -I../include -I../mySTL
+INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../mySTL
bin_PROGRAMS = test
test_SOURCES = test.cpp
test_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la
diff --git a/extra/yassl/testsuite/Makefile.am b/extra/yassl/testsuite/Makefile.am
index e8abffd6bb0..138077300f9 100644
--- a/extra/yassl/testsuite/Makefile.am
+++ b/extra/yassl/testsuite/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = -I../include -I../taocrypt/include -I../taocrypt/mySTL
+INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../taocrypt/include -I$(srcdir)/../taocrypt/mySTL
bin_PROGRAMS = testsuite
testsuite_SOURCES = testsuite.cpp ../taocrypt/test/test.cpp \
../examples/client/client.cpp ../examples/server/server.cpp \
diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp
index 0266c802657..b23b36f0ba2 100644
--- a/extra/yassl/testsuite/test.hpp
+++ b/extra/yassl/testsuite/test.hpp
@@ -27,9 +27,12 @@
#endif /* _WIN32 */
-#if !defined(_SOCKLEN_T) && (defined(_WIN32) || defined(__NETWARE__))
+#if !defined(_SOCKLEN_T) && defined(_WIN32)
typedef int socklen_t;
#endif
+#if !defined(_SOCKLEN_T) && defined(__NETWARE__)
+ typedef size_t socklen_t;
+#endif
// Check type of third arg to accept
diff --git a/extra/yassl/testsuite/testsuite.cpp b/extra/yassl/testsuite/testsuite.cpp
index 1cf6a78ebe7..49113a552cd 100644
--- a/extra/yassl/testsuite/testsuite.cpp
+++ b/extra/yassl/testsuite/testsuite.cpp
@@ -86,8 +86,8 @@ int main(int argc, char** argv)
// input output compare
byte input[TaoCrypt::MD5::DIGEST_SIZE];
byte output[TaoCrypt::MD5::DIGEST_SIZE];
- file_test("input", input);
- file_test("output", output);
+ file_test((char*) "input", input);
+ file_test((char*) "output", output);
assert(memcmp(input, output, sizeof(input)) == 0);
printf("\nAll tests passed!\n");
diff --git a/extra/yassl/testsuite/testsuite.dsp b/extra/yassl/testsuite/testsuite.dsp
index 24c325fa878..2a7f5a77433 100644
--- a/extra/yassl/testsuite/testsuite.dsp
+++ b/extra/yassl/testsuite/testsuite.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /O2 /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "../taocrypt/include" /I "../include" /I "../taocrypt/mySTL" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -67,7 +67,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "../taocrypt/include" /I "../include" /I "../mySTL" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "../taocrypt/include" /I "../include" /I "../taocrypt/mySTL" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "NO_MAIN_DRIVER" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
diff --git a/extra/yassl/yassl.dsp b/extra/yassl/yassl.dsp
index 58c016da448..f9b1699e667 100644
--- a/extra/yassl/yassl.dsp
+++ b/extra/yassl/yassl.dsp
@@ -41,7 +41,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "include" /I "taocrypt\include" /I "taocrypt\mySTL" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -64,7 +64,7 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "taocrypt\include" /I "mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "include" /I "taocrypt\include" /I "taocrypt\mySTL" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "YASSL_PREFIX" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
diff --git a/extra/yassl/yassl.vcproj b/extra/yassl/yassl.vcproj
index a7688ac4583..ec7dceb5096 100755
--- a/extra/yassl/yassl.vcproj
+++ b/extra/yassl/yassl.vcproj
@@ -21,7 +21,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
- AdditionalIncludeDirectories="include,taocrypt\include,mySTL"
+ AdditionalIncludeDirectories="include,taocrypt\include,taocrypt\mySTL"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;YASSL_PREFIX"
ExceptionHandling="FALSE"
BasicRuntimeChecks="3"
@@ -75,7 +75,7 @@
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
- AdditionalIncludeDirectories="include,taocrypt\include,mySTL"
+ AdditionalIncludeDirectories="include,taocrypt\include,taocrypt\mySTL"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;YASSL_PREFIX"
StringPooling="TRUE"
ExceptionHandling="FALSE"
diff --git a/heap/_check.c b/heap/_check.c
index cc832f8ed5b..c861fdb582f 100644
--- a/heap/_check.c
+++ b/heap/_check.c
@@ -88,7 +88,8 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
if (records != share->records || deleted != share->deleted)
{
DBUG_PRINT("error",("Found rows: %lu (%lu) deleted %lu (%lu)",
- records, share->records, deleted, share->deleted));
+ records, (ulong) share->records,
+ deleted, (ulong) share->deleted));
error= 1;
}
*info= save_info;
@@ -100,9 +101,9 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
ulong blength, my_bool print_status)
{
int error;
- uint i,found,max_links,seek,links;
- uint rec_link; /* Only used with debugging */
- uint hash_buckets_found;
+ ulong i,found,max_links,seek,links;
+ ulong rec_link; /* Only used with debugging */
+ ulong hash_buckets_found;
HASH_INFO *hash_info;
error=0;
@@ -123,7 +124,9 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
blength, records))
!= i)
{
- DBUG_PRINT("error",("Record in wrong link: Link %d Record: 0x%lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
+ DBUG_PRINT("error",
+ ("Record in wrong link: Link %lu Record: 0x%lx Record-link %lu",
+ i, (long) hash_info->ptr_to_rec, rec_link));
error=1;
}
else
@@ -141,18 +144,18 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
if (keydef->hash_buckets != hash_buckets_found)
{
DBUG_PRINT("error",("Found %ld buckets, stats shows %ld buckets",
- hash_buckets_found, keydef->hash_buckets));
+ hash_buckets_found, (long) keydef->hash_buckets));
error=1;
}
DBUG_PRINT("info",
- ("records: %ld seeks: %d max links: %d hitrate: %.2f "
- "buckets: %d",
+ ("records: %ld seeks: %lu max links: %lu hitrate: %.2f "
+ "buckets: %lu",
records,seek,max_links,
(float) seek / (float) (records ? records : 1),
hash_buckets_found));
if (print_status)
- printf("Key: %d records: %ld seeks: %d max links: %d "
- "hitrate: %.2f buckets: %d\n",
+ printf("Key: %d records: %ld seeks: %lu max links: %lu "
+ "hitrate: %.2f buckets: %lu\n",
keynr, records, seek, max_links,
(float) seek / (float) (records ? records : 1),
hash_buckets_found);
@@ -180,8 +183,8 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
key_length, SEARCH_FIND | SEARCH_SAME, not_used))
{
error= 1;
- DBUG_PRINT("error",("Record in wrong link: key: %d Record: 0x%lx\n",
- keynr, recpos));
+ DBUG_PRINT("error",("Record in wrong link: key: %u Record: 0x%lx\n",
+ keynr, (long) recpos));
}
else
found++;
diff --git a/heap/hp_clear.c b/heap/hp_clear.c
index 596d71ebe9c..b491f8eba15 100644
--- a/heap/hp_clear.c
+++ b/heap/hp_clear.c
@@ -36,7 +36,8 @@ void hp_clear(HP_SHARE *info)
(byte*) 0));
info->block.levels=0;
hp_clear_keys(info);
- info->records=info->deleted=info->data_length=0;
+ info->records= info->deleted= 0;
+ info->data_length= 0;
info->blength=1;
info->changed=0;
info->del_link=0;
diff --git a/heap/hp_delete.c b/heap/hp_delete.c
index f18c5e7054c..2ef57624e77 100644
--- a/heap/hp_delete.c
+++ b/heap/hp_delete.c
@@ -24,7 +24,7 @@ int heap_delete(HP_INFO *info, const byte *record)
HP_SHARE *share=info->s;
HP_KEYDEF *keydef, *end, *p_lastinx;
DBUG_ENTER("heap_delete");
- DBUG_PRINT("enter",("info: %lx record: 0x%lx",info,record));
+ DBUG_PRINT("enter",("info: 0x%lx record: 0x%lx", (long) info, (long) record));
test_active(info);
@@ -144,7 +144,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
info->current_hash_ptr=last_ptr;
info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
DBUG_PRINT("info",("Corrected current_ptr to point at: 0x%lx",
- info->current_ptr));
+ (long) info->current_ptr));
}
empty=pos;
if (gpos)
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index 77f3cf6d80b..6a537906929 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -120,7 +120,7 @@ byte *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
{
switch (nextflag) {
case 0: /* Search after key */
- DBUG_PRINT("exit",("found key at %d",pos->ptr_to_rec));
+ DBUG_PRINT("exit", ("found key at 0x%lx", (long) pos->ptr_to_rec));
info->current_hash_ptr=pos;
DBUG_RETURN(info->current_ptr= pos->ptr_to_rec);
case 1: /* Search next */
diff --git a/heap/hp_open.c b/heap/hp_open.c
index fd937229b0d..f50478c8b3d 100644
--- a/heap/hp_open.c
+++ b/heap/hp_open.c
@@ -64,7 +64,8 @@ HP_INFO *heap_open(const char *name, int mode)
info->opt_flag= READ_CHECK_USED; /* Check when changing */
#endif
DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %d",
- info,share->reclength,share->block.records_in_block));
+ (long) info, share->reclength,
+ share->block.records_in_block));
DBUG_RETURN(info);
}
@@ -82,7 +83,7 @@ HP_SHARE *hp_find_named_heap(const char *name)
info= (HP_SHARE*) pos->data;
if (!strcmp(name, info->name))
{
- DBUG_PRINT("exit", ("Old heap_database: 0x%lx",info));
+ DBUG_PRINT("exit", ("Old heap_database: 0x%lx", (long) info));
DBUG_RETURN(info);
}
}
diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c
index f5f22a877a1..f02d44cc456 100644
--- a/heap/hp_rkey.c
+++ b/heap/hp_rkey.c
@@ -23,7 +23,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
HP_SHARE *share= info->s;
HP_KEYDEF *keyinfo= share->keydef + inx;
DBUG_ENTER("heap_rkey");
- DBUG_PRINT("enter",("base: 0x%lx inx: %d",info,inx));
+ DBUG_PRINT("enter",("info: 0x%lx inx: %d", (long) info, inx));
if ((uint) inx >= share->keys)
{
diff --git a/heap/hp_rrnd.c b/heap/hp_rrnd.c
index 4daa3a06377..2f8556484a4 100644
--- a/heap/hp_rrnd.c
+++ b/heap/hp_rrnd.c
@@ -29,7 +29,7 @@ int heap_rrnd(register HP_INFO *info, byte *record, byte *pos)
{
HP_SHARE *share=info->s;
DBUG_ENTER("heap_rrnd");
- DBUG_PRINT("enter",("info: 0x%lx pos: %lx",info,pos));
+ DBUG_PRINT("enter",("info: 0x%lx pos: %lx",(long) info, (long) pos));
info->lastinx= -1;
if (!(info->current_ptr= pos))
@@ -44,7 +44,7 @@ int heap_rrnd(register HP_INFO *info, byte *record, byte *pos)
}
info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
memcpy(record,info->current_ptr,(size_t) share->reclength);
- DBUG_PRINT("exit",("found record at 0x%lx",info->current_ptr));
+ DBUG_PRINT("exit", ("found record at 0x%lx", (long) info->current_ptr));
info->current_hash_ptr=0; /* Can't use rnext */
DBUG_RETURN(0);
} /* heap_rrnd */
diff --git a/heap/hp_write.c b/heap/hp_write.c
index bc94e3bfae4..c83ae65c966 100644
--- a/heap/hp_write.c
+++ b/heap/hp_write.c
@@ -68,7 +68,7 @@ int heap_write(HP_INFO *info, const byte *record)
DBUG_RETURN(0);
err:
- DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
+ DBUG_PRINT("info",("Duplicate key: %d", (int) (keydef - share->keydef)));
info->errkey= keydef - share->keydef;
if (keydef->algorithm == HA_KEY_ALG_BTREE)
{
@@ -138,7 +138,7 @@ static byte *next_free_record_pos(HP_SHARE *info)
pos=info->del_link;
info->del_link= *((byte**) pos);
info->deleted--;
- DBUG_PRINT("exit",("Used old position: 0x%lx",pos));
+ DBUG_PRINT("exit",("Used old position: 0x%lx",(long) pos));
DBUG_RETURN(pos);
}
if (!(block_pos=(info->records % info->block.records_in_block)))
@@ -153,9 +153,9 @@ static byte *next_free_record_pos(HP_SHARE *info)
DBUG_RETURN(NULL);
info->data_length+=length;
}
- DBUG_PRINT("exit",("Used new position: %lx",
- (byte*) info->block.level_info[0].last_blocks+block_pos*
- info->block.recbuffer));
+ DBUG_PRINT("exit",("Used new position: 0x%lx",
+ (long) ((byte*) info->block.level_info[0].last_blocks+
+ block_pos * info->block.recbuffer)));
DBUG_RETURN((byte*) info->block.level_info[0].last_blocks+
block_pos*info->block.recbuffer);
}
diff --git a/include/Makefile.am b/include/Makefile.am
index 2dbea3fe07f..8a4799149d0 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -15,14 +15,17 @@
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
-BUILT_SOURCES = mysql_version.h m_ctype.h my_config.h
-pkginclude_HEADERS = my_dbug.h m_string.h my_sys.h my_list.h my_xml.h \
- mysql.h mysql_com.h mysql_embed.h \
- my_semaphore.h my_pthread.h my_no_pthread.h raid.h \
- errmsg.h my_global.h my_net.h my_alloc.h \
- my_getopt.h sslopt-longopts.h my_dir.h typelib.h \
+BUILT_SOURCES = $(HEADERS_GEN) abi_check
+HEADERS_GEN = mysql_version.h my_config.h
+HEADERS_ABI = mysql.h mysql_com.h mysql_time.h \
+ my_list.h my_alloc.h typelib.h
+pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \
+ my_xml.h mysql_embed.h \
+ my_semaphore.h my_pthread.h my_no_pthread.h raid.h \
+ errmsg.h my_global.h my_net.h \
+ my_getopt.h sslopt-longopts.h my_dir.h \
sslopt-vars.h sslopt-case.h sql_common.h keycache.h \
- mysql_time.h $(BUILT_SOURCES)
+ m_ctype.h $(HEADERS_GEN)
noinst_HEADERS = config-win.h config-os2.h config-netware.h \
heap.h my_bitmap.h\
myisam.h myisampack.h myisammrg.h ft_global.h\
@@ -33,8 +36,10 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \
mysql_version.h.in my_handler.h my_time.h decimal.h \
my_user.h my_libwrap.h
-# mysql_version.h are generated
-CLEANFILES = mysql_version.h my_config.h readline openssl
+# Remove built files and the symlinked directories
+CLEANFILES = $(BUILT_SOURCES) readline openssl
+
+EXTRA_DIST = mysql_h.ic
# Some include files that may be moved and patched by configure
DISTCLEANFILES = sched.h $(CLEANFILES)
@@ -52,5 +57,18 @@ my_config.h: ../config.h
dist-hook:
$(RM) -f $(distdir)/mysql_version.h $(distdir)/my_config.h
+#
+# Rules for checking that ABI has not changed
+#
+
+# Create a icheck file and compare it to the reference
+abi_check: $(HEADERS_ABI) mysql_version.h mysql_h.ic
+ @set -ex; \
+ if [ @ICHECK@ != no ] ; then \
+ @ICHECK@ --canonify --skip-from-re /usr/ -o $@.ic mysql.h; \
+ @ICHECK@ --compare mysql_h.ic $@.ic; \
+ fi; \
+ touch abi_check;
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/include/abi_check b/include/abi_check
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/include/abi_check
diff --git a/include/abi_check.ic b/include/abi_check.ic
new file mode 100644
index 00000000000..30ef44a1ccb
--- /dev/null
+++ b/include/abi_check.ic
@@ -0,0 +1,914 @@
+struct rand_struct;
+struct st_list;
+struct st_mem_root;
+struct st_mysql;
+struct st_mysql_bind;
+struct st_mysql_data;
+struct st_mysql_field;
+struct st_mysql_manager;
+struct st_mysql_methods;
+struct st_mysql_options;
+struct st_mysql_parameters;
+struct st_mysql_res;
+struct st_mysql_rows;
+struct st_mysql_stmt;
+struct st_mysql_time;
+struct st_net;
+struct st_typelib;
+struct st_udf_args;
+struct st_udf_init;
+struct st_used_mem;
+enum Item_result;
+enum enum_field_types;
+enum enum_mysql_set_option;
+enum enum_mysql_stmt_state;
+enum enum_mysql_timestamp_type;
+enum enum_server_command;
+enum enum_stmt_attr_type;
+enum mysql_enum_shutdown_level;
+enum mysql_option;
+enum mysql_protocol_type;
+enum mysql_rpl_type;
+enum mysql_status;
+# 131 "mysql.h"
+typedef struct st_mysql_rows MYSQL_ROWS;
+# 24 "my_list.h"
+typedef struct st_list LIST;
+# 232 "mysql.h"
+typedef struct st_mysql MYSQL;
+# 571 "mysql.h"
+typedef struct st_mysql_bind MYSQL_BIND;
+# 93 "mysql.h"
+typedef struct st_mysql_field MYSQL_FIELD;
+# 117 "mysql.h"
+typedef unsigned int MYSQL_FIELD_OFFSET;
+# 323 "mysql.h"
+typedef struct st_mysql_manager MYSQL_MANAGER;
+# 337 "mysql.h"
+typedef struct st_mysql_parameters MYSQL_PARAMETERS;
+# 292 "mysql.h"
+typedef struct st_mysql_res MYSQL_RES;
+# 116 "mysql.h"
+typedef char * * MYSQL_ROW;
+# 137 "mysql.h"
+typedef MYSQL_ROWS * MYSQL_ROW_OFFSET;
+# 596 "mysql.h"
+typedef struct st_mysql_stmt MYSQL_STMT;
+# 151 "mysql_com.h"
+typedef struct st_net NET;
+# 21 "typelib.h"
+typedef struct st_typelib TYPELIB;
+# 141 "mysql_com.h"
+typedef struct st_vio Vio;
+# 57 "mysql.h"
+typedef char * gptr;
+# 29 "my_list.h"
+typedef int (* list_walk_action)(void *, void *);
+# 48 "mysql.h"
+typedef char my_bool;
+# 63 "mysql.h"
+typedef int my_socket;
+# 125 "mysql.h"
+typedef unsigned long long int my_ulonglong;
+# 35 "my_alloc.h"
+typedef struct st_mem_root MEM_ROOT;
+# 141 "mysql.h"
+typedef struct st_mysql_data MYSQL_DATA;
+# 648 "mysql.h"
+typedef struct st_mysql_methods MYSQL_METHODS;
+# 48 "mysql_time.h"
+typedef struct st_mysql_time MYSQL_TIME;
+# 315 "mysql_com.h"
+typedef struct st_udf_args UDF_ARGS;
+# 326 "mysql_com.h"
+typedef struct st_udf_init UDF_INIT;
+# 27 "my_alloc.h"
+typedef struct st_used_mem USED_MEM;
+# 302 "mysql_com.h"
+struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(double)))) rand_struct
+ {
+ unsigned long int seed1;
+ unsigned long int seed2;
+ unsigned long int max_value;
+ double max_value_dbl;
+ };
+# 24 "my_list.h"
+struct __attribute__((aligned(__alignof__(void *)))) st_list
+ {
+ struct st_list * prev;
+ struct st_list * next;
+ void * data;
+ };
+# 35 "my_alloc.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned int)))) st_mem_root
+ {
+ USED_MEM * free;
+ USED_MEM * used;
+ USED_MEM * pre_alloc;
+ unsigned int min_malloc;
+ unsigned int block_size;
+ unsigned int block_num;
+ unsigned int first_block_usage;
+ void (* error_handler)(void);
+ };
+# 232 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long long int)))) st_mysql
+ {
+ NET net;
+ gptr connector_fd;
+ char * host;
+ char * user;
+ char * passwd;
+ char * unix_socket;
+ char * server_version;
+ char * host_info;
+ char * info;
+ char * db;
+ struct charset_info_st * charset;
+ MYSQL_FIELD * fields;
+ MEM_ROOT field_alloc;
+ my_ulonglong affected_rows;
+ my_ulonglong insert_id;
+ my_ulonglong extra_info;
+ unsigned long int thread_id;
+ unsigned long int packet_length;
+ unsigned int port;
+ unsigned long int client_flag;
+ unsigned long int server_capabilities;
+ unsigned int protocol_version;
+ unsigned int field_count;
+ unsigned int server_status;
+ unsigned int server_language;
+ unsigned int warning_count;
+ struct st_mysql_options options;
+ enum mysql_status status;
+ my_bool free_me;
+ my_bool reconnect;
+ char scramble[(20 + 1)];
+ my_bool rpl_pivot;
+ struct st_mysql * master;
+ struct st_mysql * next_slave;
+ struct st_mysql * last_used_slave;
+ struct st_mysql * last_used_con;
+ LIST * stmts;
+ struct st_mysql_methods const * methods;
+ void * thd;
+ my_bool * unbuffered_fetch_owner;
+ struct st_mysql_stmt * current_stmt;
+ };
+# 571 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_bind
+ {
+ unsigned long int * length;
+ my_bool * is_null;
+ void * buffer;
+ enum enum_field_types buffer_type;
+ unsigned long int buffer_length;
+ unsigned char * inter_buffer;
+ unsigned long int offset;
+ unsigned long int internal_length;
+ unsigned int param_number;
+ unsigned int pack_length;
+ my_bool is_unsigned;
+ my_bool long_data_used;
+ my_bool internal_is_null;
+ void (* store_param_func)(NET * net, struct st_mysql_bind * param);
+ void (* fetch_result)(struct st_mysql_bind *, unsigned char * * row);
+ void (* skip_result)(struct st_mysql_bind *, MYSQL_FIELD *, unsigned char * * row);
+ };
+# 141 "mysql.h"
+struct __attribute__((aligned(__alignof__(unsigned long long int)), aligned(__alignof__(void *)))) st_mysql_data
+ {
+ my_ulonglong rows;
+ unsigned int fields;
+ MYSQL_ROWS * data;
+ MEM_ROOT alloc;
+ MYSQL_ROWS * * prev_ptr;
+ };
+# 93 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_field
+ {
+ char * name;
+ char * org_name;
+ char * table;
+ char * org_table;
+ char * db;
+ char * catalog;
+ char * def;
+ unsigned long int length;
+ unsigned long int max_length;
+ unsigned int name_length;
+ unsigned int org_name_length;
+ unsigned int table_length;
+ unsigned int org_table_length;
+ unsigned int db_length;
+ unsigned int catalog_length;
+ unsigned int def_length;
+ unsigned int flags;
+ unsigned int decimals;
+ unsigned int charsetnr;
+ enum enum_field_types type;
+ };
+# 323 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_manager
+ {
+ NET net;
+ char * host;
+ char * user;
+ char * passwd;
+ unsigned int port;
+ my_bool free_me;
+ my_bool eof;
+ int cmd_status;
+ int last_errno;
+ char * net_buf;
+ char * net_buf_pos;
+ char * net_data_end;
+ int net_buf_size;
+ char last_error[256];
+ };
+# 648 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)))) st_mysql_methods
+ {
+ my_bool (* read_query_result)(MYSQL * mysql);
+ my_bool (* advanced_command)(MYSQL * mysql, enum enum_server_command, char const * header, unsigned long int, char const * arg, unsigned long int, my_bool, MYSQL_STMT * stmt);
+ MYSQL_DATA * (* read_rows)(MYSQL * mysql, MYSQL_FIELD * mysql_fields, unsigned int);
+ MYSQL_RES * (* use_result)(MYSQL * mysql);
+ void (* fetch_lengths)(unsigned long int * to, MYSQL_ROW, unsigned int);
+ void (* flush_use_result)(MYSQL * mysql);
+ MYSQL_FIELD * (* list_fields)(MYSQL * mysql);
+ my_bool (* read_prepare_result)(MYSQL * mysql, MYSQL_STMT * stmt);
+ int (* stmt_execute)(MYSQL_STMT * stmt);
+ int (* read_binary_rows)(MYSQL_STMT * stmt);
+ int (* unbuffered_fetch)(MYSQL * mysql, char * * row);
+ void (* free_embedded_thd)(MYSQL * mysql);
+ char const * (* read_statistics)(MYSQL * mysql);
+ my_bool (* next_result)(MYSQL * mysql);
+ int (* read_change_user_result)(MYSQL * mysql, char * buff, char const * passwd);
+ };
+# 162 "mysql.h"
+struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(void *)))) st_mysql_options
+ {
+ unsigned int connect_timeout;
+ unsigned int read_timeout;
+ unsigned int write_timeout;
+ unsigned int port;
+ unsigned int protocol;
+ unsigned long int client_flag;
+ char * host;
+ char * user;
+ char * password;
+ char * unix_socket;
+ char * db;
+ struct st_dynamic_array * init_commands;
+ char * my_cnf_file;
+ char * my_cnf_group;
+ char * charset_dir;
+ char * charset_name;
+ char * ssl_key;
+ char * ssl_cert;
+ char * ssl_ca;
+ char * ssl_capath;
+ char * ssl_cipher;
+ char * shared_memory_base_name;
+ unsigned long int max_allowed_packet;
+ my_bool use_ssl;
+ my_bool compress;
+ my_bool named_pipe;
+ my_bool rpl_probe;
+ my_bool rpl_parse;
+ my_bool no_master_reads;
+ my_bool separate_thread;
+ enum mysql_option methods_to_use;
+ char * client_ip;
+ my_bool secure_auth;
+ int (* local_infile_init)(void * *, char const *, void *);
+ int (* local_infile_read)(void *, char *, unsigned int);
+ void (* local_infile_end)(void);
+ int (* local_infile_error)(void *, char *, unsigned int);
+ void * local_infile_userdata;
+ };
+# 337 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)))) st_mysql_parameters
+ {
+ unsigned long int * p_max_allowed_packet;
+ unsigned long int * p_net_buffer_length;
+ };
+# 292 "mysql.h"
+struct __attribute__((aligned(__alignof__(unsigned long long int)), aligned(__alignof__(void *)))) st_mysql_res
+ {
+ my_ulonglong row_count;
+ MYSQL_FIELD * fields;
+ MYSQL_DATA * data;
+ MYSQL_ROWS * data_cursor;
+ unsigned long int * lengths;
+ MYSQL * handle;
+ MEM_ROOT field_alloc;
+ unsigned int field_count;
+ unsigned int current_field;
+ MYSQL_ROW row;
+ MYSQL_ROW current_row;
+ my_bool eof;
+ my_bool unbuffered_fetch_cancelled;
+ struct st_mysql_methods const * methods;
+ };
+# 131 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_rows
+ {
+ struct st_mysql_rows * next;
+ MYSQL_ROW data;
+ unsigned long int length;
+ };
+# 596 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long long int)))) st_mysql_stmt
+ {
+ MEM_ROOT mem_root;
+ LIST list;
+ MYSQL * mysql;
+ MYSQL_BIND * params;
+ MYSQL_BIND * bind;
+ MYSQL_FIELD * fields;
+ MYSQL_DATA result;
+ MYSQL_ROWS * data_cursor;
+ my_ulonglong affected_rows;
+ my_ulonglong insert_id;
+ int (* read_row_func)(struct st_mysql_stmt * stmt, unsigned char * * row);
+ unsigned long int stmt_id;
+ unsigned int last_errno;
+ unsigned int param_count;
+ unsigned int field_count;
+ enum enum_mysql_stmt_state state;
+ char last_error[512];
+ char sqlstate[(5 + 1)];
+ my_bool send_types_to_server;
+ my_bool bind_param_done;
+ my_bool bind_result_done;
+ my_bool unbuffered_fetch_cancelled;
+ my_bool update_max_length;
+ };
+# 48 "mysql_time.h"
+struct __attribute__((aligned(__alignof__(unsigned long int)))) st_mysql_time
+ {
+ unsigned int year;
+ unsigned int month;
+ unsigned int day;
+ unsigned int hour;
+ unsigned int minute;
+ unsigned int second;
+ unsigned long int second_part;
+ my_bool neg;
+ enum enum_mysql_timestamp_type time_type;
+ };
+# 151 "mysql_com.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_net
+ {
+ Vio * vio;
+ unsigned char * buff;
+ unsigned char * buff_end;
+ unsigned char * write_pos;
+ unsigned char * read_pos;
+ my_socket fd;
+ unsigned long int max_packet;
+ unsigned long int max_packet_size;
+ unsigned int pkt_nr;
+ unsigned int compress_pkt_nr;
+ unsigned int write_timeout;
+ unsigned int read_timeout;
+ unsigned int retry_count;
+ int fcntl;
+ my_bool compress;
+ unsigned long int remain_in_buf;
+ unsigned long int length;
+ unsigned long int buf_length;
+ unsigned long int where_b;
+ unsigned int * return_status;
+ unsigned char reading_or_writing;
+ char save_char;
+ my_bool no_send_ok;
+ char last_error[512];
+ char sqlstate[(5 + 1)];
+ unsigned int last_errno;
+ unsigned char error;
+ gptr query_cache_query;
+ my_bool report_error;
+ my_bool return_errno;
+ };
+# 21 "typelib.h"
+struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) st_typelib
+ {
+ unsigned int count;
+ char const * name;
+ char const * * type_names;
+ unsigned int * type_lengths;
+ };
+# 315 "mysql_com.h"
+struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) st_udf_args
+ {
+ unsigned int arg_count;
+ enum Item_result * arg_type;
+ char * * args;
+ unsigned long int * lengths;
+ char * maybe_null;
+ };
+# 326 "mysql_com.h"
+struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(void *)))) st_udf_init
+ {
+ my_bool maybe_null;
+ unsigned int decimals;
+ unsigned long int max_length;
+ char * ptr;
+ my_bool const_item;
+ };
+# 27 "my_alloc.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned int)))) st_used_mem
+ {
+ struct st_used_mem * next;
+ unsigned int left;
+ unsigned int size;
+ };
+# 313 "mysql_com.h"
+enum Item_result
+ {
+ STRING_RESULT = 0,
+ REAL_RESULT = 1,
+ INT_RESULT = 2,
+ ROW_RESULT = 3,
+ };
+# 186 "mysql_com.h"
+enum enum_field_types
+ {
+ MYSQL_TYPE_DECIMAL = 0,
+ MYSQL_TYPE_TINY = 1,
+ MYSQL_TYPE_SHORT = 2,
+ MYSQL_TYPE_LONG = 3,
+ MYSQL_TYPE_FLOAT = 4,
+ MYSQL_TYPE_DOUBLE = 5,
+ MYSQL_TYPE_NULL = 6,
+ MYSQL_TYPE_TIMESTAMP = 7,
+ MYSQL_TYPE_LONGLONG = 8,
+ MYSQL_TYPE_INT24 = 9,
+ MYSQL_TYPE_DATE = 10,
+ MYSQL_TYPE_TIME = 11,
+ MYSQL_TYPE_DATETIME = 12,
+ MYSQL_TYPE_YEAR = 13,
+ MYSQL_TYPE_NEWDATE = 14,
+ MYSQL_TYPE_ENUM = 247,
+ MYSQL_TYPE_SET = 248,
+ MYSQL_TYPE_TINY_BLOB = 249,
+ MYSQL_TYPE_MEDIUM_BLOB = 250,
+ MYSQL_TYPE_LONG_BLOB = 251,
+ MYSQL_TYPE_BLOB = 252,
+ MYSQL_TYPE_VAR_STRING = 253,
+ MYSQL_TYPE_STRING = 254,
+ MYSQL_TYPE_GEOMETRY = 255,
+ };
+# 269 "mysql_com.h"
+enum enum_mysql_set_option
+ {
+ MYSQL_OPTION_MULTI_STATEMENTS_ON = 0,
+ MYSQL_OPTION_MULTI_STATEMENTS_OFF = 1,
+ };
+# 563 "mysql.h"
+enum enum_mysql_stmt_state
+ {
+ MYSQL_STMT_INIT_DONE = 1,
+ MYSQL_STMT_PREPARE_DONE = 2,
+ MYSQL_STMT_EXECUTE_DONE = 3,
+ MYSQL_STMT_FETCH_DONE = 4,
+ };
+# 29 "mysql_time.h"
+enum enum_mysql_timestamp_type
+ {
+ MYSQL_TIMESTAMP_NONE = -(2),
+ MYSQL_TIMESTAMP_ERROR = -(1),
+ MYSQL_TIMESTAMP_DATE = 0,
+ MYSQL_TIMESTAMP_DATETIME = 1,
+ MYSQL_TIMESTAMP_TIME = 2,
+ };
+# 39 "mysql_com.h"
+enum enum_server_command
+ {
+ COM_SLEEP = 0,
+ COM_QUIT = 1,
+ COM_INIT_DB = 2,
+ COM_QUERY = 3,
+ COM_FIELD_LIST = 4,
+ COM_CREATE_DB = 5,
+ COM_DROP_DB = 6,
+ COM_REFRESH = 7,
+ COM_SHUTDOWN = 8,
+ COM_STATISTICS = 9,
+ COM_PROCESS_INFO = 10,
+ COM_CONNECT = 11,
+ COM_PROCESS_KILL = 12,
+ COM_DEBUG = 13,
+ COM_PING = 14,
+ COM_TIME = 15,
+ COM_DELAYED_INSERT = 16,
+ COM_CHANGE_USER = 17,
+ COM_BINLOG_DUMP = 18,
+ COM_TABLE_DUMP = 19,
+ COM_CONNECT_OUT = 20,
+ COM_REGISTER_SLAVE = 21,
+ COM_PREPARE = 22,
+ COM_EXECUTE = 23,
+ COM_LONG_DATA = 24,
+ COM_CLOSE_STMT = 25,
+ COM_RESET_STMT = 26,
+ COM_SET_OPTION = 27,
+ COM_END = 28,
+ };
+# 635 "mysql.h"
+enum enum_stmt_attr_type
+ {
+ STMT_ATTR_UPDATE_MAX_LENGTH = 0,
+ };
+# 244 "mysql_com.h"
+enum mysql_enum_shutdown_level
+ {
+ SHUTDOWN_DEFAULT = 0,
+ SHUTDOWN_WAIT_CONNECTIONS = (unsigned char)((1 << 0)),
+ SHUTDOWN_WAIT_TRANSACTIONS = (unsigned char)((1 << 1)),
+ SHUTDOWN_WAIT_UPDATES = (unsigned char)((1 << 3)),
+ SHUTDOWN_WAIT_ALL_BUFFERS = ((unsigned char)((1 << 3)) << 1),
+ SHUTDOWN_WAIT_CRITICAL_BUFFERS = (((unsigned char)((1 << 3)) << 1) + 1),
+ KILL_CONNECTION = 255,
+ };
+# 151 "mysql.h"
+enum mysql_option
+ {
+ MYSQL_OPT_CONNECT_TIMEOUT = 0,
+ MYSQL_OPT_COMPRESS = 1,
+ MYSQL_OPT_NAMED_PIPE = 2,
+ MYSQL_INIT_COMMAND = 3,
+ MYSQL_READ_DEFAULT_FILE = 4,
+ MYSQL_READ_DEFAULT_GROUP = 5,
+ MYSQL_SET_CHARSET_DIR = 6,
+ MYSQL_SET_CHARSET_NAME = 7,
+ MYSQL_OPT_LOCAL_INFILE = 8,
+ MYSQL_OPT_PROTOCOL = 9,
+ MYSQL_SHARED_MEMORY_BASE_NAME = 10,
+ MYSQL_OPT_READ_TIMEOUT = 11,
+ MYSQL_OPT_WRITE_TIMEOUT = 12,
+ MYSQL_OPT_USE_RESULT = 13,
+ MYSQL_OPT_USE_REMOTE_CONNECTION = 14,
+ MYSQL_OPT_USE_EMBEDDED_CONNECTION = 15,
+ MYSQL_OPT_GUESS_CONNECTION = 16,
+ MYSQL_SET_CLIENT_IP = 17,
+ MYSQL_SECURE_AUTH = 18,
+ };
+# 214 "mysql.h"
+enum mysql_protocol_type
+ {
+ MYSQL_PROTOCOL_DEFAULT = 0,
+ MYSQL_PROTOCOL_TCP = 1,
+ MYSQL_PROTOCOL_SOCKET = 2,
+ MYSQL_PROTOCOL_PIPE = 3,
+ MYSQL_PROTOCOL_MEMORY = 4,
+ };
+# 224 "mysql.h"
+enum mysql_rpl_type
+ {
+ MYSQL_RPL_MASTER = 0,
+ MYSQL_RPL_SLAVE = 1,
+ MYSQL_RPL_ADMIN = 2,
+ };
+# 209 "mysql.h"
+enum mysql_status
+ {
+ MYSQL_STATUS_READY = 0,
+ MYSQL_STATUS_GET_RESULT = 1,
+ MYSQL_STATUS_USE_RESULT = 2,
+ };
+# 365 "mysql_com.h"
+extern my_bool check_scramble(char const * reply, char const * message, unsigned char const * hash_stage2);
+# 358 "mysql_com.h"
+extern my_bool check_scramble_323(char const *, char const * message, unsigned long int * salt);
+# 353 "mysql_com.h"
+extern void create_random_string(char * to, unsigned int, struct rand_struct * rand_st);
+# 28 "typelib.h"
+extern int find_type(char * x, TYPELIB * typelib, unsigned int);
+# 367 "mysql_com.h"
+extern void get_salt_from_password(unsigned char * res, char const * password);
+# 360 "mysql_com.h"
+extern void get_salt_from_password_323(unsigned long int * res, char const * password);
+# 372 "mysql_com.h"
+extern char * get_tty_password(char * opt_message);
+# 30 "typelib.h"
+extern char const * get_type(TYPELIB * typelib, unsigned int);
+# 355 "mysql_com.h"
+extern void hash_password(unsigned long int * to, char const * password, unsigned int);
+# 31 "my_list.h"
+extern LIST * list_add(LIST * root, LIST * element);
+# 33 "my_list.h"
+extern LIST * list_cons(void * data, LIST * root);
+# 32 "my_list.h"
+extern LIST * list_delete(LIST * root, LIST * element);
+# 35 "my_list.h"
+extern void list_free(LIST * root, unsigned int);
+# 36 "my_list.h"
+extern unsigned int list_length(LIST *);
+# 34 "my_list.h"
+extern LIST * list_reverse(LIST * root);
+# 37 "my_list.h"
+extern int list_walk(LIST *, list_walk_action, gptr);
+# 378 "mysql_com.h"
+extern int load_defaults(char const * conf_file, char const * * groups, int * argc, char * * * argv);
+# 368 "mysql_com.h"
+extern void make_password_from_salt(char * to, unsigned char const * hash_stage2);
+# 361 "mysql_com.h"
+extern void make_password_from_salt_323(char * to, unsigned long int const * salt);
+# 363 "mysql_com.h"
+extern void make_scrambled_password(char * to, char const * password);
+# 356 "mysql_com.h"
+extern void make_scrambled_password_323(char * to, char const * password);
+# 29 "typelib.h"
+extern void make_type(char * to, unsigned int, TYPELIB * typelib);
+# 299 "mysql_com.h"
+extern int my_connect(my_socket, struct sockaddr const * name, unsigned int, unsigned int);
+# 377 "mysql_com.h"
+extern my_bool my_init(void);
+# 281 "mysql_com.h"
+extern my_bool my_net_init(NET * net, Vio * vio);
+# 282 "mysql_com.h"
+extern void my_net_local_init(NET * net);
+# 292 "mysql_com.h"
+extern unsigned long int my_net_read(NET * net);
+# 287 "mysql_com.h"
+extern my_bool my_net_write(NET * net, char const * packet, unsigned long int);
+# 352 "mysql_com.h"
+extern double my_rnd(struct rand_struct *);
+# 381 "mysql_com.h"
+extern void my_thread_end(void);
+# 380 "mysql_com.h"
+extern my_bool my_thread_init(void);
+# 539 "mysql.h"
+extern void myodbc_remove_escape(MYSQL * mysql, char * name);
+# 481 "mysql.h"
+extern int mysql_add_slave(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd);
+# 393 "mysql.h"
+extern my_ulonglong mysql_affected_rows(MYSQL * mysql);
+# 720 "mysql.h"
+extern my_bool mysql_autocommit(MYSQL * mysql, my_bool);
+# 408 "mysql.h"
+extern my_bool mysql_change_user(MYSQL * mysql, char const * user, char const * passwd, char const * db);
+# 401 "mysql.h"
+extern char const * mysql_character_set_name(MYSQL * mysql);
+# 723 "mysql.h"
+extern void mysql_close(MYSQL * sock);
+# 718 "mysql.h"
+extern my_bool mysql_commit(MYSQL * mysql);
+# 510 "mysql.h"
+extern void mysql_data_seek(MYSQL_RES * result, my_ulonglong);
+# 528 "mysql.h"
+extern void mysql_debug(char const * debug);
+# 467 "mysql.h"
+extern void mysql_disable_reads_from_master(MYSQL * mysql);
+# 461 "mysql.h"
+extern void mysql_disable_rpl_parse(MYSQL * mysql);
+# 489 "mysql.h"
+extern int mysql_dump_debug_info(MYSQL * mysql);
+# 541 "mysql.h"
+extern my_bool mysql_embedded(void);
+# 466 "mysql.h"
+extern void mysql_enable_reads_from_master(MYSQL * mysql);
+# 460 "mysql.h"
+extern void mysql_enable_rpl_parse(MYSQL * mysql);
+# 385 "mysql.h"
+extern my_bool mysql_eof(MYSQL_RES * res);
+# 395 "mysql.h"
+extern unsigned int mysql_errno(MYSQL * mysql);
+# 373 "mysql_com.h"
+extern char const * mysql_errno_to_sqlstate(unsigned int);
+# 396 "mysql.h"
+extern char const * mysql_error(MYSQL * mysql);
+# 521 "mysql.h"
+extern unsigned long int mysql_escape_string(char * to, char const * from, unsigned long int);
+# 518 "mysql.h"
+extern MYSQL_FIELD * mysql_fetch_field(MYSQL_RES * result);
+# 386 "mysql.h"
+extern MYSQL_FIELD * mysql_fetch_field_direct(MYSQL_RES * res, unsigned int);
+# 388 "mysql.h"
+extern MYSQL_FIELD * mysql_fetch_fields(MYSQL_RES * res);
+# 517 "mysql.h"
+extern unsigned long int * mysql_fetch_lengths(MYSQL_RES * result);
+# 516 "mysql.h"
+extern MYSQL_ROW mysql_fetch_row(MYSQL_RES * result);
+# 392 "mysql.h"
+extern unsigned int mysql_field_count(MYSQL * mysql);
+# 514 "mysql.h"
+extern MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES * result, MYSQL_FIELD_OFFSET);
+# 390 "mysql.h"
+extern MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES * res);
+# 509 "mysql.h"
+extern void mysql_free_result(MYSQL_RES * result);
+# 499 "mysql.h"
+extern char const * mysql_get_client_info(void);
+# 500 "mysql.h"
+extern unsigned long int mysql_get_client_version(void);
+# 501 "mysql.h"
+extern char const * mysql_get_host_info(MYSQL * mysql);
+# 367 "mysql.h"
+extern MYSQL_PARAMETERS * mysql_get_parameters(void);
+# 503 "mysql.h"
+extern unsigned int mysql_get_proto_info(MYSQL * mysql);
+# 498 "mysql.h"
+extern char const * mysql_get_server_info(MYSQL * mysql);
+# 502 "mysql.h"
+extern unsigned long int mysql_get_server_version(MYSQL * mysql);
+# 523 "mysql.h"
+extern unsigned long int mysql_hex_string(char * to, char const * from, unsigned long int);
+# 399 "mysql.h"
+extern char const * mysql_info(MYSQL * mysql);
+# 404 "mysql.h"
+extern MYSQL * mysql_init(MYSQL * mysql);
+# 394 "mysql.h"
+extern my_ulonglong mysql_insert_id(MYSQL * mysql);
+# 492 "mysql.h"
+extern int mysql_kill(MYSQL * mysql, unsigned long int);
+# 504 "mysql.h"
+extern MYSQL_RES * mysql_list_dbs(MYSQL * mysql, char const * wild);
+# 519 "mysql.h"
+extern MYSQL_RES * mysql_list_fields(MYSQL * mysql, char const * table, char const * wild);
+# 506 "mysql.h"
+extern MYSQL_RES * mysql_list_processes(MYSQL * mysql);
+# 505 "mysql.h"
+extern MYSQL_RES * mysql_list_tables(MYSQL * mysql, char const * wild);
+# 548 "mysql.h"
+extern void mysql_manager_close(MYSQL_MANAGER * con);
+# 549 "mysql.h"
+extern int mysql_manager_command(MYSQL_MANAGER * con, char const * cmd, int);
+# 543 "mysql.h"
+extern MYSQL_MANAGER * mysql_manager_connect(MYSQL_MANAGER * con, char const * host, char const * user, char const * passwd, unsigned int);
+# 551 "mysql.h"
+extern int mysql_manager_fetch_line(MYSQL_MANAGER * con, char * res_buf, int);
+# 542 "mysql.h"
+extern MYSQL_MANAGER * mysql_manager_init(MYSQL_MANAGER * con);
+# 427 "mysql.h"
+extern my_bool mysql_master_query(MYSQL * mysql, char const * q, unsigned long int);
+# 429 "mysql.h"
+extern my_bool mysql_master_send_query(MYSQL * mysql, char const * q, unsigned long int);
+# 721 "mysql.h"
+extern my_bool mysql_more_results(MYSQL * mysql);
+# 722 "mysql.h"
+extern int mysql_next_result(MYSQL * mysql);
+# 384 "mysql.h"
+extern unsigned int mysql_num_fields(MYSQL_RES * res);
+# 383 "mysql.h"
+extern my_ulonglong mysql_num_rows(MYSQL_RES * res);
+# 529 "mysql.h"
+extern char * mysql_odbc_escape_string(MYSQL * mysql, char * to, unsigned long int, char const * from, unsigned long int, void * param, char * (* extend_buffer)(void *, char * to, unsigned long int * length));
+# 507 "mysql.h"
+extern int mysql_options(MYSQL * mysql, enum mysql_option, char const * arg);
+# 496 "mysql.h"
+extern int mysql_ping(MYSQL * mysql);
+# 75 "mysql.h"
+extern unsigned int mysql_port;
+# 418 "mysql.h"
+extern int mysql_query(MYSQL * mysql, char const * q);
+# 554 "mysql.h"
+extern my_bool mysql_read_query_result(MYSQL * mysql);
+# 469 "mysql.h"
+extern my_bool mysql_reads_from_master_enabled(MYSQL * mysql);
+# 410 "mysql.h"
+extern MYSQL * mysql_real_connect(MYSQL * mysql, char const * host, char const * user, char const * passwd, char const * db, unsigned int, char const * unix_socket, unsigned long int);
+# 525 "mysql.h"
+extern unsigned long int mysql_real_escape_string(MYSQL * mysql, char * to, char const * from, unsigned long int);
+# 421 "mysql.h"
+extern int mysql_real_query(MYSQL * mysql, char const * q, unsigned long int);
+# 490 "mysql.h"
+extern int mysql_refresh(MYSQL * mysql, unsigned int);
+# 719 "mysql.h"
+extern my_bool mysql_rollback(MYSQL * mysql);
+# 512 "mysql.h"
+extern MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES * result, MYSQL_ROW_OFFSET);
+# 389 "mysql.h"
+extern MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES * res);
+# 463 "mysql.h"
+extern int mysql_rpl_parse_enabled(MYSQL * mysql);
+# 474 "mysql.h"
+extern my_bool mysql_rpl_probe(MYSQL * mysql);
+# 471 "mysql.h"
+extern enum mysql_rpl_type mysql_rpl_query_type(char const * q, int);
+# 417 "mysql.h"
+extern int mysql_select_db(MYSQL * mysql, char const * db);
+# 419 "mysql.h"
+extern int mysql_send_query(MYSQL * mysql, char const * q, unsigned long int);
+# 354 "mysql.h"
+extern void mysql_server_end(void);
+# 353 "mysql.h"
+extern int mysql_server_init(int, char * * argv, char * * groups);
+# 402 "mysql.h"
+extern int mysql_set_character_set(MYSQL * mysql, char const * csname);
+# 452 "mysql.h"
+extern void mysql_set_local_infile_default(MYSQL * mysql);
+# 441 "mysql.h"
+extern void mysql_set_local_infile_handler(MYSQL * mysql, int (* local_infile_init)(void * *, char const *, void *), int (* local_infile_read)(void *, char *, unsigned int), void (* local_infile_end)(void), int (* local_infile_error)(void *, char *, unsigned int), void *);
+# 477 "mysql.h"
+extern int mysql_set_master(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd);
+# 493 "mysql.h"
+extern int mysql_set_server_option(MYSQL * mysql, enum enum_mysql_set_option);
+# 486 "mysql.h"
+extern int mysql_shutdown(MYSQL * mysql, enum mysql_enum_shutdown_level);
+# 432 "mysql.h"
+extern my_bool mysql_slave_query(MYSQL * mysql, char const * q, unsigned long int);
+# 434 "mysql.h"
+extern my_bool mysql_slave_send_query(MYSQL * mysql, char const * q, unsigned long int);
+# 397 "mysql.h"
+extern char const * mysql_sqlstate(MYSQL * mysql);
+# 405 "mysql.h"
+extern my_bool mysql_ssl_set(MYSQL * mysql, char const * key, char const * cert, char const * ca, char const * capath, char const * cipher);
+# 497 "mysql.h"
+extern char const * mysql_stat(MYSQL * mysql);
+# 714 "mysql.h"
+extern my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt);
+# 692 "mysql.h"
+extern my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void * attr);
+# 689 "mysql.h"
+extern my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void const * attr);
+# 695 "mysql.h"
+extern my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+# 696 "mysql.h"
+extern my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+# 697 "mysql.h"
+extern my_bool mysql_stmt_close(MYSQL_STMT * stmt);
+# 712 "mysql.h"
+extern void mysql_stmt_data_seek(MYSQL_STMT * stmt, my_ulonglong);
+# 706 "mysql.h"
+extern unsigned int mysql_stmt_errno(MYSQL_STMT * stmt);
+# 707 "mysql.h"
+extern char const * mysql_stmt_error(MYSQL_STMT * stmt);
+# 682 "mysql.h"
+extern int mysql_stmt_execute(MYSQL_STMT * stmt);
+# 683 "mysql.h"
+extern int mysql_stmt_fetch(MYSQL_STMT * stmt);
+# 684 "mysql.h"
+extern int mysql_stmt_fetch_column(MYSQL_STMT * stmt, MYSQL_BIND * bind, unsigned int, unsigned long int);
+# 716 "mysql.h"
+extern unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt);
+# 699 "mysql.h"
+extern my_bool mysql_stmt_free_result(MYSQL_STMT * stmt);
+# 679 "mysql.h"
+extern MYSQL_STMT * mysql_stmt_init(MYSQL * mysql);
+# 715 "mysql.h"
+extern my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt);
+# 713 "mysql.h"
+extern my_ulonglong mysql_stmt_num_rows(MYSQL_STMT * stmt);
+# 688 "mysql.h"
+extern unsigned long int mysql_stmt_param_count(MYSQL_STMT * stmt);
+# 705 "mysql.h"
+extern MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt);
+# 680 "mysql.h"
+extern int mysql_stmt_prepare(MYSQL_STMT * stmt, char const * query, unsigned long int);
+# 698 "mysql.h"
+extern my_bool mysql_stmt_reset(MYSQL_STMT * stmt);
+# 704 "mysql.h"
+extern MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt);
+# 709 "mysql.h"
+extern MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt, MYSQL_ROW_OFFSET);
+# 711 "mysql.h"
+extern MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt);
+# 700 "mysql.h"
+extern my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt, unsigned int, char const * data, unsigned long int);
+# 708 "mysql.h"
+extern char const * mysql_stmt_sqlstate(MYSQL_STMT * stmt);
+# 687 "mysql.h"
+extern int mysql_stmt_store_result(MYSQL_STMT * stmt);
+# 423 "mysql.h"
+extern MYSQL_RES * mysql_store_result(MYSQL * mysql);
+# 376 "mysql.h"
+extern void mysql_thread_end(void);
+# 400 "mysql.h"
+extern unsigned long int mysql_thread_id(MYSQL * mysql);
+# 375 "mysql.h"
+extern my_bool mysql_thread_init(void);
+# 540 "mysql.h"
+extern unsigned int mysql_thread_safe(void);
+# 76 "mysql.h"
+extern char * mysql_unix_port;
+# 424 "mysql.h"
+extern MYSQL_RES * mysql_use_result(MYSQL * mysql);
+# 398 "mysql.h"
+extern unsigned int mysql_warning_count(MYSQL * mysql);
+# 284 "mysql_com.h"
+extern void net_clear(NET * net);
+# 283 "mysql_com.h"
+extern void net_end(NET * net);
+# 286 "mysql_com.h"
+extern my_bool net_flush(NET * net);
+# 291 "mysql_com.h"
+extern int net_real_write(NET * net, char const * packet, unsigned long int);
+# 285 "mysql_com.h"
+extern my_bool net_realloc(NET * net, unsigned long int);
+# 751 "mysql.h"
+extern unsigned long int net_safe_read(MYSQL * mysql);
+# 288 "mysql_com.h"
+extern my_bool net_write_command(NET * net, unsigned char, char const * header, unsigned long int, char const * packet, unsigned long int);
+# 350 "mysql_com.h"
+extern void randominit(struct rand_struct *, unsigned long int, unsigned long int);
+# 364 "mysql_com.h"
+extern void scramble(char * to, char const * message, char const * password);
+# 357 "mysql_com.h"
+extern void scramble_323(char * to, char const * message, char const * password);
+# 32 "typelib.h"
+extern TYPELIB sql_protocol_typelib;
diff --git a/include/errmsg.h b/include/errmsg.h
index 1dd5759c104..aca7c4b6a1f 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -97,6 +97,7 @@ extern const char *client_errors[]; /* Error messages */
#define CR_NO_STMT_METADATA 2052
#define CR_NO_RESULT_SET 2053
#define CR_NOT_IMPLEMENTED 2054
-#define CR_ERROR_LAST /*Copy last error nr:*/ 2054
+#define CR_SERVER_LOST_EXTENDED 2055
+#define CR_ERROR_LAST /*Copy last error nr:*/ 2055
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
diff --git a/include/hash.h b/include/hash.h
index 8f5ff21ae5e..4d6ee77fa0c 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -65,6 +65,8 @@ my_bool hash_check(HASH *hash); /* Only in debug library */
#define hash_clear(H) bzero((char*) (H),sizeof(*(H)))
#define hash_inited(H) ((H)->array.buffer != 0)
+#define hash_init_opt(A,B,C,D,E,F,G,H) \
+ (!hash_inited(A) && _hash_init(A,B,C,D,E,F,G, H CALLER_INFO))
#ifdef __cplusplus
}
diff --git a/include/heap.h b/include/heap.h
index cfbb6113f86..4255ee52b18 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -46,8 +46,8 @@ typedef struct st_heapinfo /* Struct from heap_info */
ulong records; /* Records in database */
ulong deleted; /* Deleted records in database */
ulong max_records;
- ulong data_length;
- ulong index_length;
+ ulonglong data_length;
+ ulonglong index_length;
uint reclength; /* Length of one record */
int errkey;
ulonglong auto_increment;
@@ -135,7 +135,7 @@ typedef struct st_heap_share
HP_BLOCK block;
HP_KEYDEF *keydef;
ulong min_records,max_records; /* Params to open */
- ulong data_length,index_length,max_table_size;
+ ulonglong data_length,index_length,max_table_size;
uint key_stat_version; /* version to indicate insert/delete */
uint records; /* records */
uint blength; /* records rounded up to 2^n */
@@ -187,7 +187,7 @@ typedef struct st_heap_create_info
{
uint auto_key; /* keynr [1 - maxkey] for auto key */
uint auto_key_type;
- ulong max_table_size;
+ ulonglong max_table_size;
ulonglong auto_increment;
my_bool with_auto_increment;
} HP_CREATE_INFO;
diff --git a/include/m_ctype.h b/include/m_ctype.h
index 35d2889bdd5..ffecadd9836 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -178,8 +178,8 @@ typedef struct my_charset_handler_st
unsigned char *s,unsigned char *e);
/* Functions for case and sort convertion */
- void (*caseup_str)(struct charset_info_st *, char *);
- void (*casedn_str)(struct charset_info_st *, char *);
+ uint (*caseup_str)(struct charset_info_st *, char *);
+ uint (*casedn_str)(struct charset_info_st *, char *);
uint (*caseup)(struct charset_info_st *, char *src, uint srclen,
char *dst, uint dstlen);
uint (*casedn)(struct charset_info_st *, char *src, uint srclen,
@@ -311,8 +311,8 @@ extern uint my_instr_simple(struct charset_info_st *,
/* Functions for 8bit */
-extern void my_caseup_str_8bit(CHARSET_INFO *, char *);
-extern void my_casedn_str_8bit(CHARSET_INFO *, char *);
+extern uint my_caseup_str_8bit(CHARSET_INFO *, char *);
+extern uint my_casedn_str_8bit(CHARSET_INFO *, char *);
extern uint my_caseup_8bit(CHARSET_INFO *, char *src, uint srclen,
char *dst, uint dstlen);
extern uint my_casedn_8bit(CHARSET_INFO *, char *src, uint srclen,
@@ -399,8 +399,8 @@ int my_mbcharlen_8bit(CHARSET_INFO *, uint c);
/* Functions for multibyte charsets */
-extern void my_caseup_str_mb(CHARSET_INFO *, char *);
-extern void my_casedn_str_mb(CHARSET_INFO *, char *);
+extern uint my_caseup_str_mb(CHARSET_INFO *, char *);
+extern uint my_casedn_str_mb(CHARSET_INFO *, char *);
extern uint my_caseup_mb(CHARSET_INFO *, char *src, uint srclen,
char *dst, uint dstlen);
extern uint my_casedn_mb(CHARSET_INFO *, char *src, uint srclen,
diff --git a/include/my_dbug.h b/include/my_dbug.h
index bf2e8d9969b..8a8d622e2a3 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -36,7 +36,8 @@ extern void _db_enter_(const char *_func_,const char *_file_,uint _line_,
extern void _db_return_(uint _line_,const char **_sfunc_,const char **_sfile_,
uint *_slevel_);
extern void _db_pargs_(uint _line_,const char *keyword);
-extern void _db_doprnt_ _VARARGS((const char *format,...));
+extern void _db_doprnt_ _VARARGS((const char *format,...))
+ ATTRIBUTE_FORMAT(printf, 1, 2);
extern void _db_dump_(uint _line_,const char *keyword,const char *memory,
uint length);
extern void _db_output_(uint flag);
diff --git a/include/my_global.h b/include/my_global.h
index f94cedbc91a..7c072b2fc5c 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -1040,8 +1040,8 @@ typedef char bool; /* Ordinary boolean values 0 1 */
#define set_timespec_nsec(ABSTIME,NSEC) \
{\
ulonglong now= my_getsystime() + (NSEC/100); \
- (ABSTIME).tv_sec= (now / ULL(10000000)); \
- (ABSTIME).tv_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
+ (ABSTIME).tv_sec= (time_t) (now / ULL(10000000)); \
+ (ABSTIME).tv_nsec= (long) (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
}
#endif /* !set_timespec_nsec */
#endif /* HAVE_TIMESPEC_TS_SEC */
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 3e4388413e0..300291610d3 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -677,14 +677,13 @@ struct st_my_thread_var
};
extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
+extern uint my_thread_end_wait_time;
#define my_thread_var (_my_thread_var())
#define my_errno my_thread_var->thr_errno
/*
Keep track of shutdown,signal, and main threads so that my_end() will not
report errors with them
*/
-extern pthread_t shutdown_th, main_th, signal_th;
-
/* statistics_xxx functions are for not essential statistic */
#ifndef thread_safe_increment
diff --git a/include/my_sys.h b/include/my_sys.h
index ebb518314b2..65bfb0b7e6a 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -863,7 +863,12 @@ my_bool my_gethwaddr(uchar *to);
#define HAVE_MMAP
#endif
+#ifndef __NETWARE__
int my_getpagesize(void);
+#else
+#define my_getpagesize() 8192
+#endif
+
void *my_mmap(void *, size_t, int, int, int, my_off_t);
int my_munmap(void *, size_t);
#endif
diff --git a/include/my_time.h b/include/my_time.h
index 17cc10a0221..5361c47d57f 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -38,6 +38,14 @@ typedef long my_time_t;
#define MY_TIME_T_MAX LONG_MAX
#define MY_TIME_T_MIN LONG_MIN
+
+/* Time handling defaults */
+#define TIMESTAMP_MAX_YEAR 2038
+#define YY_PART_YEAR 70
+#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1)
+#define TIMESTAMP_MAX_VALUE INT_MAX32
+#define TIMESTAMP_MIN_VALUE 1
+
#define YY_PART_YEAR 70
/* Flags to str_to_datetime */
@@ -49,6 +57,16 @@ typedef long my_time_t;
#define TIME_NO_ZERO_DATE (TIME_NO_ZERO_IN_DATE*2)
#define TIME_INVALID_DATES (TIME_NO_ZERO_DATE*2)
+#define MYSQL_TIME_WARN_TRUNCATED 1
+#define MYSQL_TIME_WARN_OUT_OF_RANGE 2
+
+/* Limits for the TIME data type */
+#define TIME_MAX_HOUR 838
+#define TIME_MAX_MINUTE 59
+#define TIME_MAX_SECOND 59
+#define TIME_MAX_VALUE (TIME_MAX_HOUR*10000 + TIME_MAX_MINUTE*100 + \
+ TIME_MAX_SECOND)
+
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
ulong flags, int *was_cut);
enum enum_mysql_timestamp_type
@@ -63,13 +81,39 @@ ulonglong TIME_to_ulonglong(const MYSQL_TIME *time);
my_bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
- int *was_cut);
+ int *warning);
+
+int check_time_range(struct st_mysql_time *time, int *warning);
long calc_daynr(uint year,uint month,uint day);
uint calc_days_in_year(uint year);
void init_time(void);
+
+/*
+ Function to check sanity of a TIMESTAMP value
+
+ DESCRIPTION
+ Check if a given MYSQL_TIME value fits in TIMESTAMP range.
+ This function doesn't make precise check, but rather a rough
+ estimate.
+
+ RETURN VALUES
+ FALSE The value seems sane
+ TRUE The MYSQL_TIME value is definitely out of range
+*/
+
+static inline bool validate_timestamp_range(const MYSQL_TIME *t)
+{
+ if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) ||
+ (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) ||
+ (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31)))
+ return FALSE;
+
+ return TRUE;
+}
+
my_time_t
my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone,
my_bool *in_dst_time_gap);
diff --git a/include/my_tree.h b/include/my_tree.h
index 03dc9d5c829..a047f914e55 100644
--- a/include/my_tree.h
+++ b/include/my_tree.h
@@ -59,7 +59,8 @@ typedef struct st_tree_element {
typedef struct st_tree {
TREE_ELEMENT *root,null_element;
TREE_ELEMENT **parents[MAX_TREE_HEIGHT];
- uint offset_to_key,elements_in_tree,size_of_element,memory_limit,allocated;
+ uint offset_to_key,elements_in_tree,size_of_element;
+ ulong memory_limit, allocated;
qsort_cmp2 compare;
void *custom_arg;
MEM_ROOT mem_root;
@@ -69,7 +70,7 @@ typedef struct st_tree {
} TREE;
/* Functions on whole tree */
-void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
+void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit,
int size, qsort_cmp2 compare, my_bool with_delete,
tree_element_free free_element, void *custom_arg);
void delete_tree(TREE*);
diff --git a/include/mysql.h b/include/mysql.h
index 8ef3f1273ec..f2a82c99fc3 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -14,6 +14,17 @@
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 defines the client API to MySQL and also the ABI of the
+ dynamically linked libmysqlclient.
+
+ The ABI should never be changed in a released product of MySQL
+ thus you need to take great care when changing the file. In case
+ the file is changed so the ABI is broken, you must also
+ update the SHAREDLIB_MAJOR_VERSION in configure.in .
+
+*/
+
#ifndef _mysql_h
#define _mysql_h
diff --git a/include/mysql_h.ic b/include/mysql_h.ic
new file mode 100644
index 00000000000..0e546acef92
--- /dev/null
+++ b/include/mysql_h.ic
@@ -0,0 +1,966 @@
+struct character_set;
+struct rand_struct;
+struct st_list;
+struct st_mem_root;
+struct st_mysql;
+struct st_mysql_bind;
+struct st_mysql_data;
+struct st_mysql_field;
+struct st_mysql_manager;
+struct st_mysql_methods;
+struct st_mysql_options;
+struct st_mysql_parameters;
+struct st_mysql_res;
+struct st_mysql_rows;
+struct st_mysql_stmt;
+struct st_mysql_time;
+struct st_net;
+struct st_typelib;
+struct st_udf_args;
+struct st_udf_init;
+struct st_used_mem;
+enum Item_result;
+enum enum_cursor_type;
+enum enum_field_types;
+enum enum_mysql_set_option;
+enum enum_mysql_stmt_state;
+enum enum_mysql_timestamp_type;
+enum enum_server_command;
+enum enum_stmt_attr_type;
+enum mysql_enum_shutdown_level;
+enum mysql_option;
+enum mysql_protocol_type;
+enum mysql_rpl_type;
+enum mysql_status;
+# 134 "mysql.h"
+typedef struct st_mysql_rows MYSQL_ROWS;
+# 24 "my_list.h"
+typedef struct st_list LIST;
+# 251 "mysql.h"
+typedef struct st_mysql MYSQL;
+# 653 "mysql.h"
+typedef struct st_mysql_bind MYSQL_BIND;
+# 93 "mysql.h"
+typedef struct st_mysql_field MYSQL_FIELD;
+# 117 "mysql.h"
+typedef unsigned int MYSQL_FIELD_OFFSET;
+# 340 "mysql.h"
+typedef struct st_mysql_manager MYSQL_MANAGER;
+# 354 "mysql.h"
+typedef struct st_mysql_parameters MYSQL_PARAMETERS;
+# 309 "mysql.h"
+typedef struct st_mysql_res MYSQL_RES;
+# 116 "mysql.h"
+typedef char * * MYSQL_ROW;
+# 140 "mysql.h"
+typedef MYSQL_ROWS * MYSQL_ROW_OFFSET;
+# 681 "mysql.h"
+typedef struct st_mysql_stmt MYSQL_STMT;
+# 236 "mysql.h"
+typedef struct character_set MY_CHARSET_INFO;
+# 180 "mysql_com.h"
+typedef struct st_net NET;
+# 21 "typelib.h"
+typedef struct st_typelib TYPELIB;
+# 170 "mysql_com.h"
+typedef struct st_vio Vio;
+# 57 "mysql.h"
+typedef char * gptr;
+# 29 "my_list.h"
+typedef int (* list_walk_action)(void *, void *);
+# 48 "mysql.h"
+typedef char my_bool;
+# 63 "mysql.h"
+typedef int my_socket;
+# 125 "mysql.h"
+typedef unsigned long long int my_ulonglong;
+# 144 "mysql.h"
+typedef struct embedded_query_result EMBEDDED_QUERY_RESULT;
+# 35 "my_alloc.h"
+typedef struct st_mem_root MEM_ROOT;
+# 145 "mysql.h"
+typedef struct st_mysql_data MYSQL_DATA;
+# 750 "mysql.h"
+typedef struct st_mysql_methods MYSQL_METHODS;
+# 48 "mysql_time.h"
+typedef struct st_mysql_time MYSQL_TIME;
+# 371 "mysql_com.h"
+typedef struct st_udf_args UDF_ARGS;
+# 384 "mysql_com.h"
+typedef struct st_udf_init UDF_INIT;
+# 27 "my_alloc.h"
+typedef struct st_used_mem USED_MEM;
+# 236 "mysql.h"
+struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) character_set
+ {
+ unsigned int number;
+ unsigned int state;
+ char const * csname;
+ char const * name;
+ char const * comment;
+ char const * dir;
+ unsigned int mbminlen;
+ unsigned int mbmaxlen;
+ };
+# 357 "mysql_com.h"
+struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(double)))) rand_struct
+ {
+ unsigned long int seed1;
+ unsigned long int seed2;
+ unsigned long int max_value;
+ double max_value_dbl;
+ };
+# 24 "my_list.h"
+struct __attribute__((aligned(__alignof__(void *)))) st_list
+ {
+ struct st_list * prev;
+ struct st_list * next;
+ void * data;
+ };
+# 35 "my_alloc.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned int)))) st_mem_root
+ {
+ USED_MEM * free;
+ USED_MEM * used;
+ USED_MEM * pre_alloc;
+ unsigned int min_malloc;
+ unsigned int block_size;
+ unsigned int block_num;
+ unsigned int first_block_usage;
+ void (* error_handler)(void);
+ };
+# 251 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long long int)))) st_mysql
+ {
+ NET net;
+ gptr connector_fd;
+ char * host;
+ char * user;
+ char * passwd;
+ char * unix_socket;
+ char * server_version;
+ char * host_info;
+ char * info;
+ char * db;
+ struct charset_info_st * charset;
+ MYSQL_FIELD * fields;
+ MEM_ROOT field_alloc;
+ my_ulonglong affected_rows;
+ my_ulonglong insert_id;
+ my_ulonglong extra_info;
+ unsigned long int thread_id;
+ unsigned long int packet_length;
+ unsigned int port;
+ unsigned long int client_flag;
+ unsigned long int server_capabilities;
+ unsigned int protocol_version;
+ unsigned int field_count;
+ unsigned int server_status;
+ unsigned int server_language;
+ unsigned int warning_count;
+ struct st_mysql_options options;
+ enum mysql_status status;
+ my_bool free_me;
+ my_bool reconnect;
+ char scramble[(20 + 1)];
+ my_bool rpl_pivot;
+ struct st_mysql * master;
+ struct st_mysql * next_slave;
+ struct st_mysql * last_used_slave;
+ struct st_mysql * last_used_con;
+ LIST * stmts;
+ struct st_mysql_methods const * methods;
+ void * thd;
+ my_bool * unbuffered_fetch_owner;
+ };
+# 653 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_bind
+ {
+ unsigned long int * length;
+ my_bool * is_null;
+ void * buffer;
+ my_bool * error;
+ enum enum_field_types buffer_type;
+ unsigned long int buffer_length;
+ unsigned char * row_ptr;
+ unsigned long int offset;
+ unsigned long int length_value;
+ unsigned int param_number;
+ unsigned int pack_length;
+ my_bool error_value;
+ my_bool is_unsigned;
+ my_bool long_data_used;
+ my_bool is_null_value;
+ void (* store_param_func)(NET * net, struct st_mysql_bind * param);
+ void (* fetch_result)(struct st_mysql_bind *, MYSQL_FIELD *, unsigned char * * row);
+ void (* skip_result)(struct st_mysql_bind *, MYSQL_FIELD *, unsigned char * * row);
+ };
+# 145 "mysql.h"
+struct __attribute__((aligned(__alignof__(unsigned long long int)), aligned(__alignof__(void *)))) st_mysql_data
+ {
+ my_ulonglong rows;
+ unsigned int fields;
+ MYSQL_ROWS * data;
+ MEM_ROOT alloc;
+ struct embedded_query_result * embedded_info;
+ };
+# 93 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_field
+ {
+ char * name;
+ char * org_name;
+ char * table;
+ char * org_table;
+ char * db;
+ char * catalog;
+ char * def;
+ unsigned long int length;
+ unsigned long int max_length;
+ unsigned int name_length;
+ unsigned int org_name_length;
+ unsigned int table_length;
+ unsigned int org_table_length;
+ unsigned int db_length;
+ unsigned int catalog_length;
+ unsigned int def_length;
+ unsigned int flags;
+ unsigned int decimals;
+ unsigned int charsetnr;
+ enum enum_field_types type;
+ };
+# 340 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_manager
+ {
+ NET net;
+ char * host;
+ char * user;
+ char * passwd;
+ unsigned int port;
+ my_bool free_me;
+ my_bool eof;
+ int cmd_status;
+ int last_errno;
+ char * net_buf;
+ char * net_buf_pos;
+ char * net_data_end;
+ int net_buf_size;
+ char last_error[256];
+ };
+# 750 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)))) st_mysql_methods
+ {
+ my_bool (* read_query_result)(MYSQL * mysql);
+ my_bool (* advanced_command)(MYSQL * mysql, enum enum_server_command, char const * header, unsigned long int, char const * arg, unsigned long int, my_bool, MYSQL_STMT * stmt);
+ MYSQL_DATA * (* read_rows)(MYSQL * mysql, MYSQL_FIELD * mysql_fields, unsigned int);
+ MYSQL_RES * (* use_result)(MYSQL * mysql);
+ void (* fetch_lengths)(unsigned long int * to, MYSQL_ROW, unsigned int);
+ void (* flush_use_result)(MYSQL * mysql);
+ MYSQL_FIELD * (* list_fields)(MYSQL * mysql);
+ my_bool (* read_prepare_result)(MYSQL * mysql, MYSQL_STMT * stmt);
+ int (* stmt_execute)(MYSQL_STMT * stmt);
+ int (* read_binary_rows)(MYSQL_STMT * stmt);
+ int (* unbuffered_fetch)(MYSQL * mysql, char * * row);
+ void (* free_embedded_thd)(MYSQL * mysql);
+ char const * (* read_statistics)(MYSQL * mysql);
+ my_bool (* next_result)(MYSQL * mysql);
+ int (* read_change_user_result)(MYSQL * mysql, char * buff, char const * passwd);
+ int (* read_rows_from_cursor)(MYSQL_STMT * stmt);
+ };
+# 167 "mysql.h"
+struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(void *)))) st_mysql_options
+ {
+ unsigned int connect_timeout;
+ unsigned int read_timeout;
+ unsigned int write_timeout;
+ unsigned int port;
+ unsigned int protocol;
+ unsigned long int client_flag;
+ char * host;
+ char * user;
+ char * password;
+ char * unix_socket;
+ char * db;
+ struct st_dynamic_array * init_commands;
+ char * my_cnf_file;
+ char * my_cnf_group;
+ char * charset_dir;
+ char * charset_name;
+ char * ssl_key;
+ char * ssl_cert;
+ char * ssl_ca;
+ char * ssl_capath;
+ char * ssl_cipher;
+ char * shared_memory_base_name;
+ unsigned long int max_allowed_packet;
+ my_bool use_ssl;
+ my_bool compress;
+ my_bool named_pipe;
+ my_bool rpl_probe;
+ my_bool rpl_parse;
+ my_bool no_master_reads;
+ my_bool separate_thread;
+ enum mysql_option methods_to_use;
+ char * client_ip;
+ my_bool secure_auth;
+ my_bool report_data_truncation;
+ int (* local_infile_init)(void * *, char const *, void *);
+ int (* local_infile_read)(void *, char *, unsigned int);
+ void (* local_infile_end)(void);
+ int (* local_infile_error)(void *, char *, unsigned int);
+ void * local_infile_userdata;
+ };
+# 354 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)))) st_mysql_parameters
+ {
+ unsigned long int * p_max_allowed_packet;
+ unsigned long int * p_net_buffer_length;
+ };
+# 309 "mysql.h"
+struct __attribute__((aligned(__alignof__(unsigned long long int)), aligned(__alignof__(void *)))) st_mysql_res
+ {
+ my_ulonglong row_count;
+ MYSQL_FIELD * fields;
+ MYSQL_DATA * data;
+ MYSQL_ROWS * data_cursor;
+ unsigned long int * lengths;
+ MYSQL * handle;
+ MEM_ROOT field_alloc;
+ unsigned int field_count;
+ unsigned int current_field;
+ MYSQL_ROW row;
+ MYSQL_ROW current_row;
+ my_bool eof;
+ my_bool unbuffered_fetch_cancelled;
+ struct st_mysql_methods const * methods;
+ };
+# 134 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_mysql_rows
+ {
+ struct st_mysql_rows * next;
+ MYSQL_ROW data;
+ unsigned long int length;
+ };
+# 681 "mysql.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long long int)))) st_mysql_stmt
+ {
+ MEM_ROOT mem_root;
+ LIST list;
+ MYSQL * mysql;
+ MYSQL_BIND * params;
+ MYSQL_BIND * bind;
+ MYSQL_FIELD * fields;
+ MYSQL_DATA result;
+ MYSQL_ROWS * data_cursor;
+ my_ulonglong affected_rows;
+ my_ulonglong insert_id;
+ int (* read_row_func)(struct st_mysql_stmt * stmt, unsigned char * * row);
+ unsigned long int stmt_id;
+ unsigned long int flags;
+ unsigned long int prefetch_rows;
+ unsigned int server_status;
+ unsigned int last_errno;
+ unsigned int param_count;
+ unsigned int field_count;
+ enum enum_mysql_stmt_state state;
+ char last_error[512];
+ char sqlstate[(5 + 1)];
+ my_bool send_types_to_server;
+ my_bool bind_param_done;
+ unsigned char bind_result_done;
+ my_bool unbuffered_fetch_cancelled;
+ my_bool update_max_length;
+ };
+# 48 "mysql_time.h"
+struct __attribute__((aligned(__alignof__(unsigned long int)))) st_mysql_time
+ {
+ unsigned int year;
+ unsigned int month;
+ unsigned int day;
+ unsigned int hour;
+ unsigned int minute;
+ unsigned int second;
+ unsigned long int second_part;
+ my_bool neg;
+ enum enum_mysql_timestamp_type time_type;
+ };
+# 180 "mysql_com.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned long int)))) st_net
+ {
+ Vio * vio;
+ unsigned char * buff;
+ unsigned char * buff_end;
+ unsigned char * write_pos;
+ unsigned char * read_pos;
+ my_socket fd;
+ unsigned long int max_packet;
+ unsigned long int max_packet_size;
+ unsigned int pkt_nr;
+ unsigned int compress_pkt_nr;
+ unsigned int write_timeout;
+ unsigned int read_timeout;
+ unsigned int retry_count;
+ int fcntl;
+ my_bool compress;
+ unsigned long int remain_in_buf;
+ unsigned long int length;
+ unsigned long int buf_length;
+ unsigned long int where_b;
+ unsigned int * return_status;
+ unsigned char reading_or_writing;
+ char save_char;
+ my_bool no_send_ok;
+ my_bool no_send_eof;
+ my_bool no_send_error;
+ char last_error[512];
+ char sqlstate[(5 + 1)];
+ unsigned int last_errno;
+ unsigned char error;
+ gptr query_cache_query;
+ my_bool report_error;
+ my_bool return_errno;
+ };
+# 21 "typelib.h"
+struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) st_typelib
+ {
+ unsigned int count;
+ char const * name;
+ char const * * type_names;
+ unsigned int * type_lengths;
+ };
+# 371 "mysql_com.h"
+struct __attribute__((aligned(__alignof__(unsigned int)), aligned(__alignof__(void *)))) st_udf_args
+ {
+ unsigned int arg_count;
+ enum Item_result * arg_type;
+ char * * args;
+ unsigned long int * lengths;
+ char * maybe_null;
+ char * * attributes;
+ unsigned long int * attribute_lengths;
+ };
+# 384 "mysql_com.h"
+struct __attribute__((aligned(__alignof__(unsigned long int)), aligned(__alignof__(void *)))) st_udf_init
+ {
+ my_bool maybe_null;
+ unsigned int decimals;
+ unsigned long int max_length;
+ char * ptr;
+ my_bool const_item;
+ };
+# 27 "my_alloc.h"
+struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned int)))) st_used_mem
+ {
+ struct st_used_mem * next;
+ unsigned int left;
+ unsigned int size;
+ };
+# 368 "mysql_com.h"
+enum Item_result
+ {
+ STRING_RESULT = 0,
+ REAL_RESULT = 1,
+ INT_RESULT = 2,
+ ROW_RESULT = 3,
+ DECIMAL_RESULT = 4,
+ };
+# 314 "mysql_com.h"
+enum enum_cursor_type
+ {
+ CURSOR_TYPE_NO_CURSOR = 0,
+ CURSOR_TYPE_READ_ONLY = 1,
+ CURSOR_TYPE_FOR_UPDATE = 2,
+ CURSOR_TYPE_SCROLLABLE = 4,
+ };
+# 227 "mysql_com.h"
+enum enum_field_types
+ {
+ MYSQL_TYPE_DECIMAL = 0,
+ MYSQL_TYPE_TINY = 1,
+ MYSQL_TYPE_SHORT = 2,
+ MYSQL_TYPE_LONG = 3,
+ MYSQL_TYPE_FLOAT = 4,
+ MYSQL_TYPE_DOUBLE = 5,
+ MYSQL_TYPE_NULL = 6,
+ MYSQL_TYPE_TIMESTAMP = 7,
+ MYSQL_TYPE_LONGLONG = 8,
+ MYSQL_TYPE_INT24 = 9,
+ MYSQL_TYPE_DATE = 10,
+ MYSQL_TYPE_TIME = 11,
+ MYSQL_TYPE_DATETIME = 12,
+ MYSQL_TYPE_YEAR = 13,
+ MYSQL_TYPE_NEWDATE = 14,
+ MYSQL_TYPE_VARCHAR = 15,
+ MYSQL_TYPE_BIT = 16,
+ MYSQL_TYPE_NEWDECIMAL = 246,
+ MYSQL_TYPE_ENUM = 247,
+ MYSQL_TYPE_SET = 248,
+ MYSQL_TYPE_TINY_BLOB = 249,
+ MYSQL_TYPE_MEDIUM_BLOB = 250,
+ MYSQL_TYPE_LONG_BLOB = 251,
+ MYSQL_TYPE_BLOB = 252,
+ MYSQL_TYPE_VAR_STRING = 253,
+ MYSQL_TYPE_STRING = 254,
+ MYSQL_TYPE_GEOMETRY = 255,
+ };
+# 324 "mysql_com.h"
+enum enum_mysql_set_option
+ {
+ MYSQL_OPTION_MULTI_STATEMENTS_ON = 0,
+ MYSQL_OPTION_MULTI_STATEMENTS_OFF = 1,
+ };
+# 583 "mysql.h"
+enum enum_mysql_stmt_state
+ {
+ MYSQL_STMT_INIT_DONE = 1,
+ MYSQL_STMT_PREPARE_DONE = 2,
+ MYSQL_STMT_EXECUTE_DONE = 3,
+ MYSQL_STMT_FETCH_DONE = 4,
+ };
+# 29 "mysql_time.h"
+enum enum_mysql_timestamp_type
+ {
+ MYSQL_TIMESTAMP_NONE = -(2),
+ MYSQL_TIMESTAMP_ERROR = -(1),
+ MYSQL_TIMESTAMP_DATE = 0,
+ MYSQL_TIMESTAMP_DATETIME = 1,
+ MYSQL_TIMESTAMP_TIME = 2,
+ };
+# 52 "mysql_com.h"
+enum enum_server_command
+ {
+ COM_SLEEP = 0,
+ COM_QUIT = 1,
+ COM_INIT_DB = 2,
+ COM_QUERY = 3,
+ COM_FIELD_LIST = 4,
+ COM_CREATE_DB = 5,
+ COM_DROP_DB = 6,
+ COM_REFRESH = 7,
+ COM_SHUTDOWN = 8,
+ COM_STATISTICS = 9,
+ COM_PROCESS_INFO = 10,
+ COM_CONNECT = 11,
+ COM_PROCESS_KILL = 12,
+ COM_DEBUG = 13,
+ COM_PING = 14,
+ COM_TIME = 15,
+ COM_DELAYED_INSERT = 16,
+ COM_CHANGE_USER = 17,
+ COM_BINLOG_DUMP = 18,
+ COM_TABLE_DUMP = 19,
+ COM_CONNECT_OUT = 20,
+ COM_REGISTER_SLAVE = 21,
+ COM_STMT_PREPARE = 22,
+ COM_STMT_EXECUTE = 23,
+ COM_STMT_SEND_LONG_DATA = 24,
+ COM_STMT_CLOSE = 25,
+ COM_STMT_RESET = 26,
+ COM_SET_OPTION = 27,
+ COM_STMT_FETCH = 28,
+ COM_END = 29,
+ };
+# 727 "mysql.h"
+enum enum_stmt_attr_type
+ {
+ STMT_ATTR_UPDATE_MAX_LENGTH = 0,
+ STMT_ATTR_CURSOR_TYPE = 1,
+ STMT_ATTR_PREFETCH_ROWS = 2,
+ };
+# 289 "mysql_com.h"
+enum mysql_enum_shutdown_level
+ {
+ SHUTDOWN_DEFAULT = 0,
+ SHUTDOWN_WAIT_CONNECTIONS = (unsigned char)((1 << 0)),
+ SHUTDOWN_WAIT_TRANSACTIONS = (unsigned char)((1 << 1)),
+ SHUTDOWN_WAIT_UPDATES = (unsigned char)((1 << 3)),
+ SHUTDOWN_WAIT_ALL_BUFFERS = ((unsigned char)((1 << 3)) << 1),
+ SHUTDOWN_WAIT_CRITICAL_BUFFERS = (((unsigned char)((1 << 3)) << 1) + 1),
+ KILL_CONNECTION = 255,
+ };
+# 154 "mysql.h"
+enum mysql_option
+ {
+ MYSQL_OPT_CONNECT_TIMEOUT = 0,
+ MYSQL_OPT_COMPRESS = 1,
+ MYSQL_OPT_NAMED_PIPE = 2,
+ MYSQL_INIT_COMMAND = 3,
+ MYSQL_READ_DEFAULT_FILE = 4,
+ MYSQL_READ_DEFAULT_GROUP = 5,
+ MYSQL_SET_CHARSET_DIR = 6,
+ MYSQL_SET_CHARSET_NAME = 7,
+ MYSQL_OPT_LOCAL_INFILE = 8,
+ MYSQL_OPT_PROTOCOL = 9,
+ MYSQL_SHARED_MEMORY_BASE_NAME = 10,
+ MYSQL_OPT_READ_TIMEOUT = 11,
+ MYSQL_OPT_WRITE_TIMEOUT = 12,
+ MYSQL_OPT_USE_RESULT = 13,
+ MYSQL_OPT_USE_REMOTE_CONNECTION = 14,
+ MYSQL_OPT_USE_EMBEDDED_CONNECTION = 15,
+ MYSQL_OPT_GUESS_CONNECTION = 16,
+ MYSQL_SET_CLIENT_IP = 17,
+ MYSQL_SECURE_AUTH = 18,
+ MYSQL_REPORT_DATA_TRUNCATION = 19,
+ MYSQL_OPT_RECONNECT = 20,
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT = 21,
+ };
+# 221 "mysql.h"
+enum mysql_protocol_type
+ {
+ MYSQL_PROTOCOL_DEFAULT = 0,
+ MYSQL_PROTOCOL_TCP = 1,
+ MYSQL_PROTOCOL_SOCKET = 2,
+ MYSQL_PROTOCOL_PIPE = 3,
+ MYSQL_PROTOCOL_MEMORY = 4,
+ };
+# 231 "mysql.h"
+enum mysql_rpl_type
+ {
+ MYSQL_RPL_MASTER = 0,
+ MYSQL_RPL_SLAVE = 1,
+ MYSQL_RPL_ADMIN = 2,
+ };
+# 216 "mysql.h"
+enum mysql_status
+ {
+ MYSQL_STATUS_READY = 0,
+ MYSQL_STATUS_GET_RESULT = 1,
+ MYSQL_STATUS_USE_RESULT = 2,
+ };
+# 423 "mysql_com.h"
+extern my_bool check_scramble(char const * reply, char const * message, unsigned char const * hash_stage2);
+# 416 "mysql_com.h"
+extern my_bool check_scramble_323(char const *, char const * message, unsigned long int * salt);
+# 411 "mysql_com.h"
+extern void create_random_string(char * to, unsigned int, struct rand_struct * rand_st);
+# 28 "typelib.h"
+extern int find_type(char * x, TYPELIB * typelib, unsigned int);
+# 425 "mysql_com.h"
+extern void get_salt_from_password(unsigned char * res, char const * password);
+# 418 "mysql_com.h"
+extern void get_salt_from_password_323(unsigned long int * res, char const * password);
+# 431 "mysql_com.h"
+extern char * get_tty_password(char * opt_message);
+# 30 "typelib.h"
+extern char const * get_type(TYPELIB * typelib, unsigned int);
+# 413 "mysql_com.h"
+extern void hash_password(unsigned long int * to, char const * password, unsigned int);
+# 31 "my_list.h"
+extern LIST * list_add(LIST * root, LIST * element);
+# 33 "my_list.h"
+extern LIST * list_cons(void * data, LIST * root);
+# 32 "my_list.h"
+extern LIST * list_delete(LIST * root, LIST * element);
+# 35 "my_list.h"
+extern void list_free(LIST * root, unsigned int);
+# 36 "my_list.h"
+extern unsigned int list_length(LIST *);
+# 34 "my_list.h"
+extern LIST * list_reverse(LIST * root);
+# 37 "my_list.h"
+extern int list_walk(LIST *, list_walk_action, gptr);
+# 440 "mysql_com.h"
+extern int load_defaults(char const * conf_file, char const * * groups, int * argc, char * * * argv);
+# 426 "mysql_com.h"
+extern void make_password_from_salt(char * to, unsigned char const * hash_stage2);
+# 419 "mysql_com.h"
+extern void make_password_from_salt_323(char * to, unsigned long int const * salt);
+# 421 "mysql_com.h"
+extern void make_scrambled_password(char * to, char const * password);
+# 414 "mysql_com.h"
+extern void make_scrambled_password_323(char * to, char const * password);
+# 29 "typelib.h"
+extern void make_type(char * to, unsigned int, TYPELIB * typelib);
+# 437 "mysql_com.h"
+extern int modify_defaults_file(char const * file_location, char const * option, char const * option_value, char const * section_name, int);
+# 354 "mysql_com.h"
+extern int my_connect(my_socket, struct sockaddr const * name, unsigned int, unsigned int);
+# 436 "mysql_com.h"
+extern my_bool my_init(void);
+# 336 "mysql_com.h"
+extern my_bool my_net_init(NET * net, Vio * vio);
+# 337 "mysql_com.h"
+extern void my_net_local_init(NET * net);
+# 347 "mysql_com.h"
+extern unsigned long int my_net_read(NET * net);
+# 342 "mysql_com.h"
+extern my_bool my_net_write(NET * net, char const * packet, unsigned long int);
+# 410 "mysql_com.h"
+extern double my_rnd(struct rand_struct *);
+# 443 "mysql_com.h"
+extern void my_thread_end(void);
+# 442 "mysql_com.h"
+extern my_bool my_thread_init(void);
+# 559 "mysql.h"
+extern void myodbc_remove_escape(MYSQL * mysql, char * name);
+# 501 "mysql.h"
+extern int mysql_add_slave(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd);
+# 410 "mysql.h"
+extern my_ulonglong mysql_affected_rows(MYSQL * mysql);
+# 823 "mysql.h"
+extern my_bool mysql_autocommit(MYSQL * mysql, my_bool);
+# 426 "mysql.h"
+extern my_bool mysql_change_user(MYSQL * mysql, char const * user, char const * passwd, char const * db);
+# 418 "mysql.h"
+extern char const * mysql_character_set_name(MYSQL * mysql);
+# 826 "mysql.h"
+extern void mysql_close(MYSQL * sock);
+# 821 "mysql.h"
+extern my_bool mysql_commit(MYSQL * mysql);
+# 530 "mysql.h"
+extern void mysql_data_seek(MYSQL_RES * result, my_ulonglong);
+# 548 "mysql.h"
+extern void mysql_debug(char const * debug);
+# 487 "mysql.h"
+extern void mysql_disable_reads_from_master(MYSQL * mysql);
+# 481 "mysql.h"
+extern void mysql_disable_rpl_parse(MYSQL * mysql);
+# 509 "mysql.h"
+extern int mysql_dump_debug_info(MYSQL * mysql);
+# 561 "mysql.h"
+extern my_bool mysql_embedded(void);
+# 486 "mysql.h"
+extern void mysql_enable_reads_from_master(MYSQL * mysql);
+# 480 "mysql.h"
+extern void mysql_enable_rpl_parse(MYSQL * mysql);
+# 402 "mysql.h"
+extern my_bool mysql_eof(MYSQL_RES * res);
+# 412 "mysql.h"
+extern unsigned int mysql_errno(MYSQL * mysql);
+# 432 "mysql_com.h"
+extern char const * mysql_errno_to_sqlstate(unsigned int);
+# 413 "mysql.h"
+extern char const * mysql_error(MYSQL * mysql);
+# 541 "mysql.h"
+extern unsigned long int mysql_escape_string(char * to, char const * from, unsigned long int);
+# 538 "mysql.h"
+extern MYSQL_FIELD * mysql_fetch_field(MYSQL_RES * result);
+# 403 "mysql.h"
+extern MYSQL_FIELD * mysql_fetch_field_direct(MYSQL_RES * res, unsigned int);
+# 405 "mysql.h"
+extern MYSQL_FIELD * mysql_fetch_fields(MYSQL_RES * res);
+# 537 "mysql.h"
+extern unsigned long int * mysql_fetch_lengths(MYSQL_RES * result);
+# 536 "mysql.h"
+extern MYSQL_ROW mysql_fetch_row(MYSQL_RES * result);
+# 409 "mysql.h"
+extern unsigned int mysql_field_count(MYSQL * mysql);
+# 534 "mysql.h"
+extern MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES * result, MYSQL_FIELD_OFFSET);
+# 407 "mysql.h"
+extern MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES * res);
+# 529 "mysql.h"
+extern void mysql_free_result(MYSQL_RES * result);
+# 454 "mysql.h"
+extern void mysql_get_character_set_info(MYSQL * mysql, MY_CHARSET_INFO * charset);
+# 519 "mysql.h"
+extern char const * mysql_get_client_info(void);
+# 520 "mysql.h"
+extern unsigned long int mysql_get_client_version(void);
+# 521 "mysql.h"
+extern char const * mysql_get_host_info(MYSQL * mysql);
+# 384 "mysql.h"
+extern MYSQL_PARAMETERS * mysql_get_parameters(void);
+# 523 "mysql.h"
+extern unsigned int mysql_get_proto_info(MYSQL * mysql);
+# 518 "mysql.h"
+extern char const * mysql_get_server_info(MYSQL * mysql);
+# 522 "mysql.h"
+extern unsigned long int mysql_get_server_version(MYSQL * mysql);
+# 425 "mysql.h"
+extern char const * mysql_get_ssl_cipher(MYSQL * mysql);
+# 543 "mysql.h"
+extern unsigned long int mysql_hex_string(char * to, char const * from, unsigned long int);
+# 416 "mysql.h"
+extern char const * mysql_info(MYSQL * mysql);
+# 421 "mysql.h"
+extern MYSQL * mysql_init(MYSQL * mysql);
+# 411 "mysql.h"
+extern my_ulonglong mysql_insert_id(MYSQL * mysql);
+# 512 "mysql.h"
+extern int mysql_kill(MYSQL * mysql, unsigned long int);
+# 524 "mysql.h"
+extern MYSQL_RES * mysql_list_dbs(MYSQL * mysql, char const * wild);
+# 539 "mysql.h"
+extern MYSQL_RES * mysql_list_fields(MYSQL * mysql, char const * table, char const * wild);
+# 526 "mysql.h"
+extern MYSQL_RES * mysql_list_processes(MYSQL * mysql);
+# 525 "mysql.h"
+extern MYSQL_RES * mysql_list_tables(MYSQL * mysql, char const * wild);
+# 568 "mysql.h"
+extern void mysql_manager_close(MYSQL_MANAGER * con);
+# 569 "mysql.h"
+extern int mysql_manager_command(MYSQL_MANAGER * con, char const * cmd, int);
+# 563 "mysql.h"
+extern MYSQL_MANAGER * mysql_manager_connect(MYSQL_MANAGER * con, char const * host, char const * user, char const * passwd, unsigned int);
+# 571 "mysql.h"
+extern int mysql_manager_fetch_line(MYSQL_MANAGER * con, char * res_buf, int);
+# 562 "mysql.h"
+extern MYSQL_MANAGER * mysql_manager_init(MYSQL_MANAGER * con);
+# 445 "mysql.h"
+extern my_bool mysql_master_query(MYSQL * mysql, char const * q, unsigned long int);
+# 447 "mysql.h"
+extern my_bool mysql_master_send_query(MYSQL * mysql, char const * q, unsigned long int);
+# 824 "mysql.h"
+extern my_bool mysql_more_results(MYSQL * mysql);
+# 825 "mysql.h"
+extern int mysql_next_result(MYSQL * mysql);
+# 401 "mysql.h"
+extern unsigned int mysql_num_fields(MYSQL_RES * res);
+# 400 "mysql.h"
+extern my_ulonglong mysql_num_rows(MYSQL_RES * res);
+# 549 "mysql.h"
+extern char * mysql_odbc_escape_string(MYSQL * mysql, char * to, unsigned long int, char const * from, unsigned long int, void * param, char * (* extend_buffer)(void *, char * to, unsigned long int * length));
+# 527 "mysql.h"
+extern int mysql_options(MYSQL * mysql, enum mysql_option, char const * arg);
+# 516 "mysql.h"
+extern int mysql_ping(MYSQL * mysql);
+# 75 "mysql.h"
+extern unsigned int mysql_port;
+# 436 "mysql.h"
+extern int mysql_query(MYSQL * mysql, char const * q);
+# 574 "mysql.h"
+extern my_bool mysql_read_query_result(MYSQL * mysql);
+# 489 "mysql.h"
+extern my_bool mysql_reads_from_master_enabled(MYSQL * mysql);
+# 428 "mysql.h"
+extern MYSQL * mysql_real_connect(MYSQL * mysql, char const * host, char const * user, char const * passwd, char const * db, unsigned int, char const * unix_socket, unsigned long int);
+# 545 "mysql.h"
+extern unsigned long int mysql_real_escape_string(MYSQL * mysql, char * to, char const * from, unsigned long int);
+# 439 "mysql.h"
+extern int mysql_real_query(MYSQL * mysql, char const * q, unsigned long int);
+# 510 "mysql.h"
+extern int mysql_refresh(MYSQL * mysql, unsigned int);
+# 822 "mysql.h"
+extern my_bool mysql_rollback(MYSQL * mysql);
+# 532 "mysql.h"
+extern MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES * result, MYSQL_ROW_OFFSET);
+# 406 "mysql.h"
+extern MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES * res);
+# 483 "mysql.h"
+extern int mysql_rpl_parse_enabled(MYSQL * mysql);
+# 494 "mysql.h"
+extern my_bool mysql_rpl_probe(MYSQL * mysql);
+# 491 "mysql.h"
+extern enum mysql_rpl_type mysql_rpl_query_type(char const * q, int);
+# 435 "mysql.h"
+extern int mysql_select_db(MYSQL * mysql, char const * db);
+# 437 "mysql.h"
+extern int mysql_send_query(MYSQL * mysql, char const * q, unsigned long int);
+# 371 "mysql.h"
+extern void mysql_server_end(void);
+# 370 "mysql.h"
+extern int mysql_server_init(int, char * * argv, char * * groups);
+# 419 "mysql.h"
+extern int mysql_set_character_set(MYSQL * mysql, char const * csname);
+# 472 "mysql.h"
+extern void mysql_set_local_infile_default(MYSQL * mysql);
+# 461 "mysql.h"
+extern void mysql_set_local_infile_handler(MYSQL * mysql, int (* local_infile_init)(void * *, char const *, void *), int (* local_infile_read)(void *, char *, unsigned int), void (* local_infile_end)(void), int (* local_infile_error)(void *, char *, unsigned int), void *);
+# 497 "mysql.h"
+extern int mysql_set_master(MYSQL * mysql, char const * host, unsigned int, char const * user, char const * passwd);
+# 513 "mysql.h"
+extern int mysql_set_server_option(MYSQL * mysql, enum enum_mysql_set_option);
+# 506 "mysql.h"
+extern int mysql_shutdown(MYSQL * mysql, enum mysql_enum_shutdown_level);
+# 450 "mysql.h"
+extern my_bool mysql_slave_query(MYSQL * mysql, char const * q, unsigned long int);
+# 452 "mysql.h"
+extern my_bool mysql_slave_send_query(MYSQL * mysql, char const * q, unsigned long int);
+# 414 "mysql.h"
+extern char const * mysql_sqlstate(MYSQL * mysql);
+# 422 "mysql.h"
+extern my_bool mysql_ssl_set(MYSQL * mysql, char const * key, char const * cert, char const * ca, char const * capath, char const * cipher);
+# 517 "mysql.h"
+extern char const * mysql_stat(MYSQL * mysql);
+# 817 "mysql.h"
+extern my_ulonglong mysql_stmt_affected_rows(MYSQL_STMT * stmt);
+# 795 "mysql.h"
+extern my_bool mysql_stmt_attr_get(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void * attr);
+# 792 "mysql.h"
+extern my_bool mysql_stmt_attr_set(MYSQL_STMT * stmt, enum enum_stmt_attr_type, void const * attr);
+# 798 "mysql.h"
+extern my_bool mysql_stmt_bind_param(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+# 799 "mysql.h"
+extern my_bool mysql_stmt_bind_result(MYSQL_STMT * stmt, MYSQL_BIND * bnd);
+# 800 "mysql.h"
+extern my_bool mysql_stmt_close(MYSQL_STMT * stmt);
+# 815 "mysql.h"
+extern void mysql_stmt_data_seek(MYSQL_STMT * stmt, my_ulonglong);
+# 809 "mysql.h"
+extern unsigned int mysql_stmt_errno(MYSQL_STMT * stmt);
+# 810 "mysql.h"
+extern char const * mysql_stmt_error(MYSQL_STMT * stmt);
+# 785 "mysql.h"
+extern int mysql_stmt_execute(MYSQL_STMT * stmt);
+# 786 "mysql.h"
+extern int mysql_stmt_fetch(MYSQL_STMT * stmt);
+# 787 "mysql.h"
+extern int mysql_stmt_fetch_column(MYSQL_STMT * stmt, MYSQL_BIND * bind, unsigned int, unsigned long int);
+# 819 "mysql.h"
+extern unsigned int mysql_stmt_field_count(MYSQL_STMT * stmt);
+# 802 "mysql.h"
+extern my_bool mysql_stmt_free_result(MYSQL_STMT * stmt);
+# 782 "mysql.h"
+extern MYSQL_STMT * mysql_stmt_init(MYSQL * mysql);
+# 818 "mysql.h"
+extern my_ulonglong mysql_stmt_insert_id(MYSQL_STMT * stmt);
+# 816 "mysql.h"
+extern my_ulonglong mysql_stmt_num_rows(MYSQL_STMT * stmt);
+# 791 "mysql.h"
+extern unsigned long int mysql_stmt_param_count(MYSQL_STMT * stmt);
+# 808 "mysql.h"
+extern MYSQL_RES * mysql_stmt_param_metadata(MYSQL_STMT * stmt);
+# 783 "mysql.h"
+extern int mysql_stmt_prepare(MYSQL_STMT * stmt, char const * query, unsigned long int);
+# 801 "mysql.h"
+extern my_bool mysql_stmt_reset(MYSQL_STMT * stmt);
+# 807 "mysql.h"
+extern MYSQL_RES * mysql_stmt_result_metadata(MYSQL_STMT * stmt);
+# 812 "mysql.h"
+extern MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT * stmt, MYSQL_ROW_OFFSET);
+# 814 "mysql.h"
+extern MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT * stmt);
+# 803 "mysql.h"
+extern my_bool mysql_stmt_send_long_data(MYSQL_STMT * stmt, unsigned int, char const * data, unsigned long int);
+# 811 "mysql.h"
+extern char const * mysql_stmt_sqlstate(MYSQL_STMT * stmt);
+# 790 "mysql.h"
+extern int mysql_stmt_store_result(MYSQL_STMT * stmt);
+# 441 "mysql.h"
+extern MYSQL_RES * mysql_store_result(MYSQL * mysql);
+# 393 "mysql.h"
+extern void mysql_thread_end(void);
+# 417 "mysql.h"
+extern unsigned long int mysql_thread_id(MYSQL * mysql);
+# 392 "mysql.h"
+extern my_bool mysql_thread_init(void);
+# 560 "mysql.h"
+extern unsigned int mysql_thread_safe(void);
+# 76 "mysql.h"
+extern char * mysql_unix_port;
+# 442 "mysql.h"
+extern MYSQL_RES * mysql_use_result(MYSQL * mysql);
+# 415 "mysql.h"
+extern unsigned int mysql_warning_count(MYSQL * mysql);
+# 339 "mysql_com.h"
+extern void net_clear(NET * net);
+# 338 "mysql_com.h"
+extern void net_end(NET * net);
+# 341 "mysql_com.h"
+extern my_bool net_flush(NET * net);
+# 346 "mysql_com.h"
+extern int net_real_write(NET * net, char const * packet, unsigned long int);
+# 340 "mysql_com.h"
+extern my_bool net_realloc(NET * net, unsigned long int);
+# 343 "mysql_com.h"
+extern my_bool net_write_command(NET * net, unsigned char, char const * header, unsigned long int, char const * packet, unsigned long int);
+# 427 "mysql_com.h"
+extern char * octet2hex(char * to, char const * str, unsigned int);
+# 408 "mysql_com.h"
+extern void randominit(struct rand_struct *, unsigned long int, unsigned long int);
+# 422 "mysql_com.h"
+extern void scramble(char * to, char const * message, char const * password);
+# 415 "mysql_com.h"
+extern void scramble_323(char * to, char const * message, char const * password);
+# 32 "typelib.h"
+extern TYPELIB sql_protocol_typelib;
diff --git a/innobase/CMakeLists.txt b/innobase/CMakeLists.txt
index f9661963d56..c244364a800 100755
--- a/innobase/CMakeLists.txt
+++ b/innobase/CMakeLists.txt
@@ -2,6 +2,43 @@
#SET(CMAKE_C_FLAGS_DEBUG "-DSAFEMALLOC -DSAFE_MUTEX")
ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -DWIN32 -D_LIB)
+# Bug#19424 - InnoDB: Possibly a memory overrun of the buffer being freed (64-bit Visual C)
+# Removing Win64 compiler optimizations for all innodb files.
+IF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64")
+ SET_SOURCE_FILES_PROPERTIES(btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
+ buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
+ data/data0data.c data/data0type.c
+ dict/dict0boot.c dict/dict0crea.c dict/dict0dict.c dict/dict0load.c dict/dict0mem.c
+ dyn/dyn0dyn.c
+ eval/eval0eval.c eval/eval0proc.c
+ fil/fil0fil.c
+ fsp/fsp0fsp.c
+ fut/fut0fut.c fut/fut0lst.c
+ ha/ha0ha.c ha/hash0hash.c
+ ibuf/ibuf0ibuf.c
+ pars/lexyy.c pars/pars0grm.c pars/pars0opt.c pars/pars0pars.c pars/pars0sym.c
+ lock/lock0lock.c
+ log/log0log.c log/log0recv.c
+ mach/mach0data.c
+ mem/mem0mem.c mem/mem0pool.c
+ mtr/mtr0log.c mtr/mtr0mtr.c
+ os/os0file.c os/os0proc.c os/os0sync.c os/os0thread.c
+ page/page0cur.c page/page0page.c
+ que/que0que.c
+ read/read0read.c
+ rem/rem0cmp.c rem/rem0rec.c
+ row/row0ins.c row/row0mysql.c row/row0purge.c row/row0row.c row/row0sel.c row/row0uins.c
+ row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
+ srv/srv0que.c srv/srv0srv.c srv/srv0start.c
+ sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
+ thr/thr0loc.c
+ trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c
+ trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
+ usr/usr0sess.c
+ ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c
+ PROPERTIES COMPILE_FLAGS -Od)
+ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64")
+
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include include)
ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
@@ -33,3 +70,8 @@ ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
usr/usr0sess.c
ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c )
+
+# (Bug#19424) Removing Win64 compiler optimizations innobase project.
+IF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64")
+ SET_TARGET_PROPERTIES(innobase PROPERTIES COMPILE_FLAGS "/Od")
+ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64")
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index db09a931c29..f24f1744363 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -221,6 +221,9 @@ in the free list to the frames.
5) When we have AWE enabled, we disable adaptive hash indexes.
*/
+/* Value in microseconds */
+static const int WAIT_FOR_READ = 20000;
+
buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */
#ifdef UNIV_DEBUG
@@ -488,6 +491,9 @@ buf_block_init(
block->n_pointers = 0;
+ mutex_create(&block->mutex);
+ mutex_set_level(&block->mutex, SYNC_BUF_BLOCK);
+
rw_lock_create(&(block->lock));
ut_ad(rw_lock_validate(&(block->lock)));
@@ -756,8 +762,15 @@ buf_awe_map_page_to_frame(
bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped);
while (bck) {
- if (bck->state == BUF_BLOCK_FILE_PAGE
- && (bck->buf_fix_count != 0 || bck->io_fix != 0)) {
+ ibool skip;
+
+ mutex_enter(&bck->mutex);
+
+ skip = (bck->state == BUF_BLOCK_FILE_PAGE
+ && (bck->buf_fix_count != 0 || bck->io_fix != 0));
+
+ if (skip) {
+ mutex_exit(&bck->mutex);
/* We have to skip this */
bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck);
@@ -790,6 +803,8 @@ buf_awe_map_page_to_frame(
buf_pool->n_pages_awe_remapped++;
+ mutex_exit(&bck->mutex);
+
return;
}
}
@@ -828,13 +843,22 @@ buf_block_make_young(
/*=================*/
buf_block_t* block) /* in: block to make younger */
{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!mutex_own(&(buf_pool->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
+
+ /* Note that we read freed_page_clock's without holding any mutex:
+ this is allowed since the result is used only in heuristics */
+
if (buf_pool->freed_page_clock >= block->freed_page_clock
- + 1 + (buf_pool->curr_size / 1024)) {
+ + 1 + (buf_pool->curr_size / 4)) {
+ mutex_enter(&buf_pool->mutex);
/* There has been freeing activity in the LRU list:
best to move to the head of the LRU list */
buf_LRU_make_block_young(block);
+ mutex_exit(&buf_pool->mutex);
}
}
@@ -869,12 +893,16 @@ buf_block_free(
/*===========*/
buf_block_t* block) /* in, own: block to be freed */
{
- ut_a(block->state != BUF_BLOCK_FILE_PAGE);
-
mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
+
+ ut_a(block->state != BUF_BLOCK_FILE_PAGE);
+
buf_LRU_block_free_non_file_page(block);
+ mutex_exit(&block->mutex);
+
mutex_exit(&(buf_pool->mutex));
}
@@ -1093,9 +1121,8 @@ buf_page_get_gen(
#endif
buf_pool->n_page_gets++;
loop:
- mutex_enter_fast(&(buf_pool->mutex));
-
block = NULL;
+ mutex_enter_fast(&(buf_pool->mutex));
if (guess) {
block = buf_block_align(guess);
@@ -1133,6 +1160,8 @@ loop:
goto loop;
}
+ mutex_enter(&block->mutex);
+
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
must_read = FALSE;
@@ -1142,9 +1171,9 @@ loop:
must_read = TRUE;
if (mode == BUF_GET_IF_IN_POOL) {
-
/* The page is only being read to buffer */
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&buf_pool->mutex);
+ mutex_exit(&block->mutex);
return(NULL);
}
@@ -1168,7 +1197,7 @@ loop:
#else
buf_block_buf_fix_inc(block);
#endif
- buf_block_make_young(block);
+ mutex_exit(&buf_pool->mutex);
/* Check if this is the first access to the page */
@@ -1176,10 +1205,13 @@ loop:
block->accessed = TRUE;
+ mutex_exit(&block->mutex);
+
+ buf_block_make_young(block);
+
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->file_page_was_freed == FALSE);
#endif
- mutex_exit(&(buf_pool->mutex));
#ifdef UNIV_DEBUG
buf_dbg_counter++;
@@ -1204,13 +1236,14 @@ loop:
}
if (!success) {
- mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
block->buf_fix_count--;
+
+ mutex_exit(&block->mutex);
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
#endif
- mutex_exit(&(buf_pool->mutex));
return(NULL);
}
@@ -1221,18 +1254,16 @@ loop:
completes */
for (;;) {
- mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
if (block->io_fix == BUF_IO_READ) {
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&block->mutex);
- /* Sleep 20 milliseconds */
-
- os_thread_sleep(20000);
+ os_thread_sleep(WAIT_FOR_READ);
} else {
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&block->mutex);
break;
}
@@ -1290,15 +1321,15 @@ buf_page_optimistic_get_func(
ut_ad(mtr && block);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-
- mutex_enter(&(buf_pool->mutex));
/* If AWE is used, block may have a different frame now, e.g., NULL */
-
+
+ mutex_enter(&block->mutex);
+
if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE)
- || UNIV_UNLIKELY(block->frame != guess)) {
- exit_func:
- mutex_exit(&(buf_pool->mutex));
+ || UNIV_UNLIKELY(block->frame != guess)) {
+
+ mutex_exit(&block->mutex);
return(FALSE);
}
@@ -1308,15 +1339,14 @@ buf_page_optimistic_get_func(
#else
buf_block_buf_fix_inc(block);
#endif
- buf_block_make_young(block);
-
- /* Check if this is the first access to the page */
-
accessed = block->accessed;
-
block->accessed = TRUE;
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&block->mutex);
+
+ buf_block_make_young(block);
+
+ /* Check if this is the first access to the page */
ut_ad(!ibuf_inside() || ibuf_page(block->space, block->offset));
@@ -1331,13 +1361,16 @@ buf_page_optimistic_get_func(
}
if (UNIV_UNLIKELY(!success)) {
- mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
block->buf_fix_count--;
+
+ mutex_exit(&block->mutex);
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
#endif
- goto exit_func;
+ return(FALSE);
}
if (UNIV_UNLIKELY(!UT_DULINT_EQ(modify_clock, block->modify_clock))) {
@@ -1350,13 +1383,16 @@ buf_page_optimistic_get_func(
rw_lock_x_unlock(&(block->lock));
}
- mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
block->buf_fix_count--;
+
+ mutex_exit(&block->mutex);
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
#endif
- goto exit_func;
+ return(FALSE);
}
mtr_memo_push(mtr, block, fix_type);
@@ -1413,10 +1449,10 @@ buf_page_get_known_nowait(
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
- mutex_enter(&(buf_pool->mutex));
-
block = buf_block_align(guess);
+ mutex_enter(&block->mutex);
+
if (block->state == BUF_BLOCK_REMOVE_HASH) {
/* Another thread is just freeing the block from the LRU list
of the buffer pool: do not try to access this page; this
@@ -1425,7 +1461,7 @@ buf_page_get_known_nowait(
we have already removed it from the page address hash table
of the buffer pool. */
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&block->mutex);
return(FALSE);
}
@@ -1437,12 +1473,12 @@ buf_page_get_known_nowait(
#else
buf_block_buf_fix_inc(block);
#endif
+ mutex_exit(&block->mutex);
+
if (mode == BUF_MAKE_YOUNG) {
buf_block_make_young(block);
}
- mutex_exit(&(buf_pool->mutex));
-
ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
if (rw_latch == RW_S_LATCH) {
@@ -1456,13 +1492,15 @@ buf_page_get_known_nowait(
}
if (!success) {
- mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
block->buf_fix_count--;
+
+ mutex_exit(&block->mutex);
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
#endif
- mutex_exit(&(buf_pool->mutex));
return(FALSE);
}
@@ -1510,8 +1548,7 @@ buf_page_init_for_backup_restore(
block->offset = offset;
block->lock_hash_val = 0;
- block->lock_mutex = NULL;
-
+
block->freed_page_clock = 0;
block->newest_modification = ut_dulint_zero;
@@ -1543,6 +1580,7 @@ buf_page_init(
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+ ut_ad(mutex_own(&(block->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state != BUF_BLOCK_FILE_PAGE);
@@ -1557,8 +1595,7 @@ buf_page_init(
block->index = NULL;
block->lock_hash_val = lock_rec_hash(space, offset);
- block->lock_mutex = NULL;
-
+
/* Insert into the hash table of file pages */
if (buf_page_hash_get(space, offset)) {
@@ -1650,6 +1687,7 @@ buf_page_init_for_read(
ut_a(block);
mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
if (fil_tablespace_deleted_or_being_deleted_in_mem(space,
tablespace_version)) {
@@ -1662,7 +1700,9 @@ buf_page_init_for_read(
/* The page belongs to a space which has been deleted or is
being deleted, or the page is already in buf_pool, return */
+ mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
+
buf_block_free(block);
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
@@ -1682,6 +1722,7 @@ buf_page_init_for_read(
buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */
block->io_fix = BUF_IO_READ;
+
buf_pool->n_pend_reads++;
/* We set a pass-type x-lock on the frame because then the same
@@ -1693,6 +1734,7 @@ buf_page_init_for_read(
rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ);
+ mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
@@ -1757,6 +1799,8 @@ buf_page_create(
block = free_block;
+ mutex_enter(&block->mutex);
+
buf_page_init(space, offset, block);
/* The block must be put to the LRU list */
@@ -1767,13 +1811,15 @@ buf_page_create(
#else
buf_block_buf_fix_inc(block);
#endif
+ buf_pool->n_pages_created++;
+
+ mutex_exit(&(buf_pool->mutex));
+
mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
block->accessed = TRUE;
- buf_pool->n_pages_created++;
-
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&block->mutex);
/* Delete possible entries for the page from the insert buffer:
such can exist if the page belonged to an index which was dropped */
@@ -1822,6 +1868,12 @@ buf_page_io_complete(
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
+ /* We do not need protect block->io_fix here by block->mutex to read
+ it because this is the only function where we can change the value
+ from BUF_IO_READ or BUF_IO_WRITE to some other value, and our code
+ ensures that this is the only thread that handles the i/o for this
+ block. */
+
io_type = block->io_fix;
if (io_type == BUF_IO_READ) {
@@ -1890,11 +1942,12 @@ buf_page_io_complete(
}
}
+ mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
+
#ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(block->space, block->offset) == 0);
#endif
- mutex_enter(&(buf_pool->mutex));
-
/* Because this thread which does the unlocking is not the same that
did the locking, we use a pass value != 0 in unlock, which simply
removes the newest lock debug record, without checking the thread
@@ -1937,6 +1990,7 @@ buf_page_io_complete(
#endif /* UNIV_DEBUG */
}
+ mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
#ifdef UNIV_DEBUG
@@ -1999,6 +2053,8 @@ buf_validate(void)
block = buf_pool_get_nth_block(buf_pool, i);
+ mutex_enter(&block->mutex);
+
if (block->state == BUF_BLOCK_FILE_PAGE) {
ut_a(buf_page_hash_get(block->space,
@@ -2042,6 +2098,8 @@ buf_validate(void)
} else if (block->state == BUF_BLOCK_NOT_USED) {
n_free++;
}
+
+ mutex_exit(&block->mutex);
}
if (n_lru + n_free > buf_pool->curr_size) {
@@ -2185,11 +2243,17 @@ buf_get_latched_pages_number(void)
for (i = 0; i < buf_pool->curr_size; i++) {
- block = buf_pool_get_nth_block(buf_pool, i);
+ block = buf_pool_get_nth_block(buf_pool, i);
+
+ if (block->magic_n == BUF_BLOCK_MAGIC_N) {
+ mutex_enter(&block->mutex);
- if (((block->buf_fix_count != 0) || (block->io_fix != 0)) &&
- block->magic_n == BUF_BLOCK_MAGIC_N )
- fixed_pages_number++;
+ if (block->buf_fix_count != 0 || block->io_fix != 0) {
+ fixed_pages_number++;
+ }
+
+ mutex_exit(&block->mutex);
+ }
}
mutex_exit(&(buf_pool->mutex));
@@ -2354,16 +2418,21 @@ buf_all_freed(void)
block = buf_pool_get_nth_block(buf_pool, i);
+ mutex_enter(&block->mutex);
+
if (block->state == BUF_BLOCK_FILE_PAGE) {
if (!buf_flush_ready_for_replace(block)) {
fprintf(stderr,
"Page %lu %lu still fixed or dirty\n",
- (ulong) block->space, (ulong) block->offset);
+ (ulong) block->space,
+ (ulong) block->offset);
ut_error;
}
}
+
+ mutex_exit(&block->mutex);
}
mutex_exit(&(buf_pool->mutex));
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index e39d1ae0a71..fc7b60bf5fb 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -114,6 +114,7 @@ buf_flush_ready_for_replace(
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+ ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
if (block->state != BUF_BLOCK_FILE_PAGE) {
ut_print_timestamp(stderr);
@@ -148,6 +149,7 @@ buf_flush_ready_for_flush(
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+ ut_ad(mutex_own(&(block->mutex)));
#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
@@ -539,8 +541,15 @@ buf_flush_try_page(
ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);
+ if (!block) {
+ mutex_exit(&(buf_pool->mutex));
+ return(0);
+ }
+
+ mutex_enter(&block->mutex);
+
if (flush_type == BUF_FLUSH_LIST
- && block && buf_flush_ready_for_flush(block, flush_type)) {
+ && buf_flush_ready_for_flush(block, flush_type)) {
block->io_fix = BUF_IO_WRITE;
@@ -578,6 +587,7 @@ buf_flush_try_page(
locked = TRUE;
}
+ mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
if (!locked) {
@@ -598,8 +608,8 @@ buf_flush_try_page(
return(1);
- } else if (flush_type == BUF_FLUSH_LRU && block
- && buf_flush_ready_for_flush(block, flush_type)) {
+ } else if (flush_type == BUF_FLUSH_LRU
+ && buf_flush_ready_for_flush(block, flush_type)) {
/* VERY IMPORTANT:
Because any thread may call the LRU flush, even when owning
@@ -639,14 +649,15 @@ buf_flush_try_page(
buf_pool mutex: this ensures that the latch is acquired
immediately. */
+ mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
buf_flush_write_block_low(block);
return(1);
- } else if (flush_type == BUF_FLUSH_SINGLE_PAGE && block
- && buf_flush_ready_for_flush(block, flush_type)) {
+ } else if (flush_type == BUF_FLUSH_SINGLE_PAGE
+ && buf_flush_ready_for_flush(block, flush_type)) {
block->io_fix = BUF_IO_WRITE;
@@ -672,6 +683,7 @@ buf_flush_try_page(
(buf_pool->n_flush[flush_type])++;
+ mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
@@ -688,11 +700,12 @@ buf_flush_try_page(
buf_flush_write_block_low(block);
return(1);
- } else {
- mutex_exit(&(buf_pool->mutex));
+ }
- return(0);
- }
+ mutex_exit(&block->mutex);
+ mutex_exit(&(buf_pool->mutex));
+
+ return(0);
}
/***************************************************************
@@ -737,34 +750,48 @@ buf_flush_try_neighbors(
block = buf_page_hash_get(space, i);
ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);
- if (block && flush_type == BUF_FLUSH_LRU && i != offset
- && !block->old) {
+ if (!block) {
+
+ continue;
+
+ } else if (flush_type == BUF_FLUSH_LRU && i != offset
+ && !block->old) {
/* We avoid flushing 'non-old' blocks in an LRU flush,
because the flushed blocks are soon freed */
continue;
- }
+ } else {
+
+ mutex_enter(&block->mutex);
+
+ if (buf_flush_ready_for_flush(block, flush_type)
+ && (i == offset || block->buf_fix_count == 0)) {
+ /* We only try to flush those
+ neighbors != offset where the buf fix count is
+ zero, as we then know that we probably can
+ latch the page without a semaphore wait.
+ Semaphore waits are expensive because we must
+ flush the doublewrite buffer before we start
+ waiting. */
- if (block && buf_flush_ready_for_flush(block, flush_type)
- && (i == offset || block->buf_fix_count == 0)) {
- /* We only try to flush those neighbors != offset
- where the buf fix count is zero, as we then know that
- we probably can latch the page without a semaphore
- wait. Semaphore waits are expensive because we must
- flush the doublewrite buffer before we start
- waiting. */
+ mutex_exit(&block->mutex);
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&(buf_pool->mutex));
- /* Note: as we release the buf_pool mutex above, in
- buf_flush_try_page we cannot be sure the page is still
- in a flushable state: therefore we check it again
- inside that function. */
+ /* Note: as we release the buf_pool mutex
+ above, in buf_flush_try_page we cannot be sure
+ the page is still in a flushable state:
+ therefore we check it again inside that
+ function. */
- count += buf_flush_try_page(space, i, flush_type);
+ count += buf_flush_try_page(space, i,
+ flush_type);
- mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&(buf_pool->mutex));
+ } else {
+ mutex_exit(&block->mutex);
+ }
}
}
@@ -858,12 +885,15 @@ buf_flush_batch(
while ((block != NULL) && !found) {
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
+ mutex_enter(&block->mutex);
+
if (buf_flush_ready_for_flush(block, flush_type)) {
found = TRUE;
space = block->space;
offset = block->offset;
+ mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
old_page_count = page_count;
@@ -881,10 +911,14 @@ buf_flush_batch(
} else if (flush_type == BUF_FLUSH_LRU) {
+ mutex_exit(&block->mutex);
+
block = UT_LIST_GET_PREV(LRU, block);
} else {
ut_ad(flush_type == BUF_FLUSH_LIST);
+ mutex_exit(&block->mutex);
+
block = UT_LIST_GET_PREV(flush_list, block);
}
}
@@ -966,10 +1000,14 @@ buf_flush_LRU_recommendation(void)
+ BUF_FLUSH_EXTRA_MARGIN)
&& (distance < BUF_LRU_FREE_SEARCH_LEN)) {
+ mutex_enter(&block->mutex);
+
if (buf_flush_ready_for_replace(block)) {
n_replaceable++;
}
+ mutex_exit(&block->mutex);
+
distance++;
block = UT_LIST_GET_PREV(LRU, block);
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 8b135cc5db3..dfee2add045 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -86,6 +86,9 @@ scan_again:
block = UT_LIST_GET_LAST(buf_pool->LRU);
while (block != NULL) {
+
+ mutex_enter(&block->mutex);
+
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (block->space == id
@@ -112,6 +115,8 @@ scan_again:
if (block->is_hashed) {
page_no = block->offset;
+ mutex_exit(&block->mutex);
+
mutex_exit(&(buf_pool->mutex));
/* Note that the following call will acquire
@@ -138,6 +143,7 @@ scan_again:
buf_LRU_block_free_hashed_page(block);
}
next_page:
+ mutex_exit(&block->mutex);
block = UT_LIST_GET_PREV(LRU, block);
}
@@ -211,6 +217,9 @@ buf_LRU_search_and_free_block(
while (block != NULL) {
ut_a(block->in_LRU_list);
+
+ mutex_enter(&block->mutex);
+
if (buf_flush_ready_for_replace(block)) {
#ifdef UNIV_DEBUG
@@ -225,6 +234,7 @@ buf_LRU_search_and_free_block(
buf_LRU_block_remove_hashed_page(block);
mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&block->mutex);
/* Remove possible adaptive hash index built on the
page; in the case of AWE the block may not have a
@@ -233,15 +243,21 @@ buf_LRU_search_and_free_block(
if (block->frame) {
btr_search_drop_page_hash_index(block->frame);
}
- mutex_enter(&(buf_pool->mutex));
ut_a(block->buf_fix_count == 0);
+ mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&block->mutex);
+
buf_LRU_block_free_hashed_page(block);
freed = TRUE;
+ mutex_exit(&block->mutex);
break;
}
+
+ mutex_exit(&block->mutex);
+
block = UT_LIST_GET_PREV(LRU, block);
distance++;
@@ -415,8 +431,12 @@ loop:
}
}
+ mutex_enter(&block->mutex);
+
block->state = BUF_BLOCK_READY_FOR_USE;
+ mutex_exit(&block->mutex);
+
mutex_exit(&(buf_pool->mutex));
if (started_monitor) {
@@ -818,6 +838,7 @@ buf_LRU_block_free_non_file_page(
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+ ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(block);
@@ -857,6 +878,7 @@ buf_LRU_block_remove_hashed_page(
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+ ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(block);
@@ -914,6 +936,7 @@ buf_LRU_block_free_hashed_page(
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
+ ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_a(block->state == BUF_BLOCK_REMOVE_HASH);
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index c7d6ffd2c22..e20d8b6e83a 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -724,8 +724,10 @@ dict_truncate_index_tree(
/* out: new root page number, or
FIL_NULL on failure */
dict_table_t* table, /* in: the table the index belongs to */
- rec_t* rec, /* in: record in the clustered index of
- SYS_INDEXES table */
+ btr_pcur_t* pcur, /* in/out: persistent cursor pointing to
+ record in the clustered index of
+ SYS_INDEXES table. The cursor may be
+ repositioned in this call. */
mtr_t* mtr) /* in: mtr having the latch
on the record page. The mtr may be
committed and restarted in this call. */
@@ -734,6 +736,7 @@ dict_truncate_index_tree(
ulint space;
ulint type;
dulint index_id;
+ rec_t* rec;
byte* ptr;
ulint len;
ulint comp;
@@ -744,6 +747,7 @@ dict_truncate_index_tree(
#endif /* UNIV_SYNC_DEBUG */
ut_a(!dict_sys->sys_indexes->comp);
+ rec = btr_pcur_get_rec(pcur);
ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
ut_ad(len == 4);
@@ -809,10 +813,11 @@ dict_truncate_index_tree(
/* We will need to commit the mini-transaction in order to avoid
deadlocks in the btr_create() call, because otherwise we would
be freeing and allocating pages in the same mini-transaction. */
+ btr_pcur_store_position(pcur, mtr);
mtr_commit(mtr);
- /* mtr_commit() will invalidate rec. */
- rec = NULL;
+
mtr_start(mtr);
+ btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
/* Find the index corresponding to this SYS_INDEXES record. */
for (index = UT_LIST_GET_FIRST(table->indexes);
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index 64987294654..65320b57183 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -4285,29 +4285,47 @@ fil_flush_file_spaces(
{
fil_system_t* system = fil_system;
fil_space_t* space;
+ ulint* space_ids;
+ ulint n_space_ids;
+ ulint i;
mutex_enter(&(system->mutex));
- space = UT_LIST_GET_FIRST(system->unflushed_spaces);
+ n_space_ids = UT_LIST_GET_LEN(system->unflushed_spaces);
+ if (n_space_ids == 0) {
- while (space) {
- if (space->purpose == purpose && !space->is_being_deleted) {
+ mutex_exit(&system->mutex);
+ return;
+ }
- space->n_pending_flushes++; /* prevent dropping of the
- space while we are
- flushing */
- mutex_exit(&(system->mutex));
+ /* Assemble a list of space ids to flush. Previously, we
+ traversed system->unflushed_spaces and called UT_LIST_GET_NEXT()
+ on a space that was just removed from the list by fil_flush().
+ Thus, the space could be dropped and the memory overwritten. */
+ space_ids = mem_alloc(n_space_ids * sizeof *space_ids);
- fil_flush(space->id);
+ n_space_ids = 0;
- mutex_enter(&(system->mutex));
+ for (space = UT_LIST_GET_FIRST(system->unflushed_spaces);
+ space;
+ space = UT_LIST_GET_NEXT(unflushed_spaces, space)) {
+
+ if (space->purpose == purpose && !space->is_being_deleted) {
- space->n_pending_flushes--;
+ space_ids[n_space_ids++] = space->id;
}
- space = UT_LIST_GET_NEXT(unflushed_spaces, space);
}
-
- mutex_exit(&(system->mutex));
+
+ mutex_exit(&system->mutex);
+
+ /* Flush the spaces. It will not hurt to call fil_flush() on
+ a non-existing space id. */
+ for (i = 0; i < n_space_ids; i++) {
+
+ fil_flush(space_ids[i]);
+ }
+
+ mem_free(space_ids);
}
/**********************************************************************
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index fc1d9a64c7f..11e5bb39e63 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -461,8 +461,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock
table. */
UNIV_INLINE
mutex_t*
-buf_frame_get_lock_mutex(
-/*=====================*/
+buf_frame_get_mutex(
+/*================*/
/* out: mutex */
byte* ptr); /* in: pointer to within a buffer frame */
/***********************************************************************
@@ -713,7 +713,10 @@ struct buf_block_struct{
ulint magic_n; /* magic number to check */
ulint state; /* state of the control block:
- BUF_BLOCK_NOT_USED, ... */
+ BUF_BLOCK_NOT_USED, ...; changing
+ this is only allowed when a thread
+ has BOTH the buffer pool mutex AND
+ block->mutex locked */
byte* frame; /* pointer to buffer frame which
is of size UNIV_PAGE_SIZE, and
aligned to an address divisible by
@@ -731,8 +734,12 @@ struct buf_block_struct{
ulint offset; /* page number within the space */
ulint lock_hash_val; /* hashed value of the page address
in the record lock hash table */
- mutex_t* lock_mutex; /* mutex protecting the chain in the
- record lock hash table */
+ mutex_t mutex; /* mutex protecting this block:
+ state (also protected by the buffer
+ pool mutex), io_fix, buf_fix_count,
+ and accessed; we introduce this new
+ mutex in InnoDB-5.1 to relieve
+ contention on the buffer pool mutex */
rw_lock_t lock; /* read-write lock of the buffer
frame */
buf_block_t* hash; /* node used in chaining to the page
@@ -788,20 +795,27 @@ struct buf_block_struct{
in heuristic algorithms, because of
the possibility of a wrap-around! */
ulint freed_page_clock;/* the value of freed_page_clock
- buffer pool when this block was
- last time put to the head of the
- LRU list */
+ of the buffer pool when this block was
+ the last time put to the head of the
+ LRU list; a thread is allowed to
+ read this for heuristic purposes
+ without holding any mutex or latch */
ibool old; /* TRUE if the block is in the old
blocks in the LRU list */
ibool accessed; /* TRUE if the page has been accessed
while in the buffer pool: read-ahead
may read in pages which have not been
- accessed yet */
+ accessed yet; this is protected by
+ block->mutex; a thread is allowed to
+ read this for heuristic purposes
+ without holding any mutex or latch */
ulint buf_fix_count; /* count of how manyfold this block
- is currently bufferfixed */
+ is currently bufferfixed; this is
+ protected by block->mutex */
ulint io_fix; /* if a read is pending to the frame,
io_fix is BUF_IO_READ, in the case
- of a write BUF_IO_WRITE, otherwise 0 */
+ of a write BUF_IO_WRITE, otherwise 0;
+ this is protected by block->mutex */
/* 4. Optimistic search field */
dulint modify_clock; /* this clock is incremented every
@@ -962,7 +976,9 @@ struct buf_pool_struct{
number of buffer blocks removed from
the end of the LRU list; NOTE that
this counter may wrap around at 4
- billion! */
+ billion! A thread is allowed to
+ read this for heuristic purposes
+ without holding any mutex or latch */
ulint LRU_flush_ended;/* when an LRU flush ends for a page,
this is incremented by one; this is
set to zero when a buffer block is
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index af32db10b5f..ddc91b8d66c 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -330,8 +330,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock
table. */
UNIV_INLINE
mutex_t*
-buf_frame_get_lock_mutex(
-/*=====================*/
+buf_frame_get_mutex(
+/*================*/
/* out: mutex */
byte* ptr) /* in: pointer to within a buffer frame */
{
@@ -339,7 +339,7 @@ buf_frame_get_lock_mutex(
block = buf_block_align(ptr);
- return(block->lock_mutex);
+ return(&block->mutex);
}
/*************************************************************************
@@ -512,6 +512,7 @@ buf_block_buf_fix_inc_debug(
ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
ut_ad(ret == TRUE);
+ ut_ad(mutex_own(&block->mutex));
#endif
block->buf_fix_count++;
}
@@ -524,6 +525,9 @@ buf_block_buf_fix_inc(
/*==================*/
buf_block_t* block) /* in: block to bufferfix */
{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&block->mutex));
+#endif
block->buf_fix_count++;
}
#endif /* UNIV_SYNC_DEBUG */
@@ -618,23 +622,24 @@ buf_page_release(
ut_ad(block);
- mutex_enter_fast(&(buf_pool->mutex));
-
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(block->buf_fix_count > 0);
if (rw_latch == RW_X_LATCH && mtr->modifications) {
-
+ mutex_enter(&buf_pool->mutex);
buf_flush_note_modification(block, mtr);
+ mutex_exit(&buf_pool->mutex);
}
+ mutex_enter(&block->mutex);
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
#endif
buf_fix_count = block->buf_fix_count;
block->buf_fix_count = buf_fix_count - 1;
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&block->mutex);
if (rw_latch == RW_S_LATCH) {
rw_lock_s_unlock(&(block->lock));
diff --git a/innobase/include/dict0crea.h b/innobase/include/dict0crea.h
index 5dd571be59c..44acca61c5e 100644
--- a/innobase/include/dict0crea.h
+++ b/innobase/include/dict0crea.h
@@ -62,8 +62,10 @@ dict_truncate_index_tree(
/* out: new root page number, or
FIL_NULL on failure */
dict_table_t* table, /* in: the table the index belongs to */
- rec_t* rec, /* in: record in the clustered index of
- SYS_INDEXES table */
+ btr_pcur_t* pcur, /* in/out: persistent cursor pointing to
+ record in the clustered index of
+ SYS_INDEXES table. The cursor may be
+ repositioned in this call. */
mtr_t* mtr); /* in: mtr having the latch
on the record page. The mtr may be
committed and restarted in this call. */
diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h
index fecd910683e..ba712d14aad 100644
--- a/innobase/include/sync0arr.h
+++ b/innobase/include/sync0arr.h
@@ -75,17 +75,12 @@ sync_array_free_cell(
sync_array_t* arr, /* in: wait array */
ulint index); /* in: index of the cell in array */
/**************************************************************************
-Looks for the cells in the wait array which refer
-to the wait object specified,
-and sets their corresponding events to the signaled state. In this
-way releases the threads waiting for the object to contend for the object.
-It is possible that no such cell is found, in which case does nothing. */
+Note that one of the wait objects was signalled. */
void
-sync_array_signal_object(
-/*=====================*/
- sync_array_t* arr, /* in: wait array */
- void* object);/* in: wait object */
+sync_array_object_signalled(
+/*========================*/
+ sync_array_t* arr); /* in: wait array */
/**************************************************************************
If the wakeup algorithm does not work perfectly at semaphore relases,
this function will do the waking (see the comment in mutex_exit). This
diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h
index 911c8ac3f4a..741f9500612 100644
--- a/innobase/include/sync0rw.h
+++ b/innobase/include/sync0rw.h
@@ -411,6 +411,7 @@ blocked by readers, a writer may queue for the lock by setting the writer
field. Then no new readers are allowed in. */
struct rw_lock_struct {
+ os_event_t event; /* Used by sync0arr.c for thread queueing */
ulint reader_count; /* Number of readers who have locked this
lock in the shared mode */
ulint writer; /* This field is set to RW_LOCK_EX if there
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index 9e15475ae53..31a1ea6562a 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -382,7 +382,8 @@ rw_lock_s_unlock_func(
mutex_exit(mutex);
if (UNIV_UNLIKELY(sg)) {
- sync_array_signal_object(sync_primary_wait_array, lock);
+ os_event_set(lock->event);
+ sync_array_object_signalled(sync_primary_wait_array);
}
ut_ad(rw_lock_validate(lock));
@@ -462,7 +463,8 @@ rw_lock_x_unlock_func(
mutex_exit(&(lock->mutex));
if (UNIV_UNLIKELY(sg)) {
- sync_array_signal_object(sync_primary_wait_array, lock);
+ os_event_set(lock->event);
+ sync_array_object_signalled(sync_primary_wait_array);
}
ut_ad(rw_lock_validate(lock));
diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h
index 5955ab9a06a..9893921c5d2 100644
--- a/innobase/include/sync0sync.h
+++ b/innobase/include/sync0sync.h
@@ -453,6 +453,7 @@ Do not use its fields directly! The structure used in the spin lock
implementation of a mutual exclusion semaphore. */
struct mutex_struct {
+ os_event_t event; /* Used by sync0arr.c for the wait queue */
ulint lock_word; /* This ulint is the target of the atomic
test-and-set instruction in Win32 */
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 075005c3611..5e5c4b19eb0 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -1718,7 +1718,7 @@ os_file_set_size(
}
/* Print about progress for each 100 MB written */
- if ((current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024)
+ if ((ib_longlong) (current_size + n_bytes) / (ib_longlong)(100 * 1024 * 1024)
!= current_size / (ib_longlong)(100 * 1024 * 1024)) {
fprintf(stderr, " %lu00",
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index 8bafb73baf8..a3204a7b3e8 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -21,6 +21,7 @@ Created 9/6/1995 Heikki Tuuri
/* Type definition for an operating system mutex struct */
struct os_mutex_struct{
+ os_event_t event; /* Used by sync0arr.c for queing threads */
void* handle; /* OS handle to mutex */
ulint count; /* we use this counter to check
that the same thread does not
@@ -35,6 +36,7 @@ struct os_mutex_struct{
/* Mutex protecting counts and the lists of OS mutexes and events */
os_mutex_t os_sync_mutex;
ibool os_sync_mutex_inited = FALSE;
+ibool os_sync_free_called = FALSE;
/* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */
@@ -50,6 +52,10 @@ ulint os_event_count = 0;
ulint os_mutex_count = 0;
ulint os_fast_mutex_count = 0;
+/* Because a mutex is embedded inside an event and there is an
+event embedded inside a mutex, on free, this generates a recursive call.
+This version of the free event function doesn't acquire the global lock */
+static void os_event_free_internal(os_event_t event);
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
@@ -76,6 +82,7 @@ os_sync_free(void)
os_event_t event;
os_mutex_t mutex;
+ os_sync_free_called = TRUE;
event = UT_LIST_GET_FIRST(os_event_list);
while (event) {
@@ -99,6 +106,7 @@ os_sync_free(void)
mutex = UT_LIST_GET_FIRST(os_mutex_list);
}
+ os_sync_free_called = FALSE;
}
/*************************************************************
@@ -146,14 +154,21 @@ os_event_create(
event->signal_count = 0;
#endif /* __WIN__ */
- /* Put to the list of events */
- os_mutex_enter(os_sync_mutex);
+ /* The os_sync_mutex can be NULL because during startup an event
+ can be created [ because it's embedded in the mutex/rwlock ] before
+ this module has been initialized */
+ if (os_sync_mutex != NULL) {
+ os_mutex_enter(os_sync_mutex);
+ }
+ /* Put to the list of events */
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
os_event_count++;
- os_mutex_exit(os_sync_mutex);
+ if (os_sync_mutex != NULL) {
+ os_mutex_exit(os_sync_mutex);
+ }
return(event);
}
@@ -256,6 +271,35 @@ os_event_reset(
}
/**************************************************************
+Frees an event object, without acquiring the global lock. */
+static
+void
+os_event_free_internal(
+/*===================*/
+ os_event_t event) /* in: event to free */
+{
+#ifdef __WIN__
+ ut_a(event);
+
+ ut_a(CloseHandle(event->handle));
+#else
+ ut_a(event);
+
+ /* This is to avoid freeing the mutex twice */
+ os_fast_mutex_free(&(event->os_mutex));
+
+ ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
+#endif
+ /* Remove from the list of events */
+
+ UT_LIST_REMOVE(os_event_list, os_event_list, event);
+
+ os_event_count--;
+
+ ut_free(event);
+}
+
+/**************************************************************
Frees an event object. */
void
@@ -456,6 +500,7 @@ os_mutex_create(
mutex_str->handle = mutex;
mutex_str->count = 0;
+ mutex_str->event = os_event_create(NULL);
if (os_sync_mutex_inited) {
/* When creating os_sync_mutex itself we cannot reserve it */
@@ -532,6 +577,10 @@ os_mutex_free(
{
ut_a(mutex);
+ if (!os_sync_free_called) {
+ os_event_free_internal(mutex->event);
+ }
+
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 955c7139de7..efbb93ba9f5 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -2920,12 +2920,10 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
goto next_rec;
}
- btr_pcur_store_position(&pcur, &mtr);
+ /* This call may commit and restart mtr
+ and reposition pcur. */
+ root_page_no = dict_truncate_index_tree(table, &pcur, &mtr);
- /* This call may commit and restart mtr. */
- root_page_no = dict_truncate_index_tree(table, rec, &mtr);
-
- btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr);
rec = btr_pcur_get_rec(&pcur);
if (root_page_no != FIL_NULL) {
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index ec56afbb4f5..f8a65e6ff82 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -1323,6 +1323,12 @@ rec_loop:
ULINT_UNDEFINED, &heap);
if (srv_locks_unsafe_for_binlog) {
+
+ if (page_rec_is_supremum(rec)) {
+
+ goto next_rec;
+ }
+
lock_type = LOCK_REC_NOT_GAP;
} else {
lock_type = LOCK_ORDINARY;
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 8530f117c9d..b41dcbe44cd 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1142,10 +1142,7 @@ innobase_start_or_create_for_mysql(void)
#if defined(__NETWARE__)
-/* Create less event semaphores because Win 98/ME had difficulty creating
-40000 event semaphores.
-Comment from Novell, Inc.: also, these just take a lot of memory on
-NetWare. */
+ /* Comment from Novell, Inc.: These take a lot of memory on NetWare.*/
srv_max_n_threads = 1000;
#else
if (srv_pool_size >= 1000 * 1024) {
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index 198ef49ca9f..64f9310bad3 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -62,9 +62,6 @@ struct sync_cell_struct {
ibool waiting; /* TRUE if the thread has already
called sync_array_event_wait
on this cell */
- ibool event_set; /* TRUE if the event is set */
- os_event_t event; /* operating system event
- semaphore handle */
time_t reservation_time;/* time when the thread reserved
the wait cell */
};
@@ -218,10 +215,7 @@ sync_array_create(
for (i = 0; i < n_cells; i++) {
cell = sync_array_get_nth_cell(arr, i);
cell->wait_object = NULL;
-
- /* Create an operating system event semaphore with no name */
- cell->event = os_event_create(NULL);
- cell->event_set = FALSE; /* it is created in reset state */
+ cell->waiting = FALSE;
}
return(arr);
@@ -235,19 +229,12 @@ sync_array_free(
/*============*/
sync_array_t* arr) /* in, own: sync wait array */
{
- ulint i;
- sync_cell_t* cell;
ulint protection;
ut_a(arr->n_reserved == 0);
sync_array_validate(arr);
- for (i = 0; i < arr->n_cells; i++) {
- cell = sync_array_get_nth_cell(arr, i);
- os_event_free(cell->event);
- }
-
protection = arr->protection;
/* Release the mutex protecting the wait array complex */
@@ -293,27 +280,19 @@ sync_array_validate(
}
/***********************************************************************
-Puts the cell event in set state. */
-static
-void
-sync_cell_event_set(
-/*================*/
- sync_cell_t* cell) /* in: array cell */
-{
- os_event_set(cell->event);
- cell->event_set = TRUE;
-}
-
-/***********************************************************************
Puts the cell event in reset state. */
static
void
sync_cell_event_reset(
/*==================*/
- sync_cell_t* cell) /* in: array cell */
+ ulint type, /* in: lock type mutex/rw_lock */
+ void* object) /* in: the rw_lock/mutex object */
{
- os_event_reset(cell->event);
- cell->event_set = FALSE;
+ if (type == SYNC_MUTEX) {
+ os_event_reset(((mutex_t *) object)->event);
+ } else {
+ os_event_reset(((rw_lock_t *) object)->event);
+ }
}
/**********************************************************************
@@ -346,14 +325,7 @@ sync_array_reserve_cell(
if (cell->wait_object == NULL) {
- /* Make sure the event is reset */
- if (cell->event_set) {
- sync_cell_event_reset(cell);
- }
-
- cell->reservation_time = time(NULL);
- cell->thread = os_thread_get_curr_id();
-
+ cell->waiting = FALSE;
cell->wait_object = object;
if (type == SYNC_MUTEX) {
@@ -363,7 +335,6 @@ sync_array_reserve_cell(
}
cell->request_type = type;
- cell->waiting = FALSE;
cell->file = file;
cell->line = line;
@@ -373,6 +344,13 @@ sync_array_reserve_cell(
*index = i;
sync_array_exit(arr);
+
+ /* Make sure the event is reset */
+ sync_cell_event_reset(type, object);
+
+ cell->reservation_time = time(NULL);
+
+ cell->thread = os_thread_get_curr_id();
return;
}
@@ -408,7 +386,12 @@ sync_array_wait_event(
ut_a(!cell->waiting);
ut_ad(os_thread_get_curr_id() == cell->thread);
- event = cell->event;
+ if (cell->request_type == SYNC_MUTEX) {
+ event = ((mutex_t*) cell->wait_object)->event;
+ } else {
+ event = ((rw_lock_t*) cell->wait_object)->event;
+ }
+
cell->waiting = TRUE;
#ifdef UNIV_SYNC_DEBUG
@@ -510,10 +493,6 @@ sync_array_cell_print(
if (!cell->waiting) {
fputs("wait has ended\n", file);
}
-
- if (cell->event_set) {
- fputs("wait is ending\n", file);
- }
}
#ifdef UNIV_SYNC_DEBUG
@@ -623,7 +602,7 @@ sync_array_detect_deadlock(
depth++;
- if (cell->event_set || !cell->waiting) {
+ if (!cell->waiting) {
return(FALSE); /* No deadlock here */
}
@@ -802,6 +781,7 @@ sync_array_free_cell(
ut_a(cell->wait_object != NULL);
+ cell->waiting = FALSE;
cell->wait_object = NULL;
ut_a(arr->n_reserved > 0);
@@ -811,44 +791,17 @@ sync_array_free_cell(
}
/**************************************************************************
-Looks for the cells in the wait array which refer to the wait object
-specified, and sets their corresponding events to the signaled state. In this
-way releases the threads waiting for the object to contend for the object.
-It is possible that no such cell is found, in which case does nothing. */
+Increments the signalled count. */
void
-sync_array_signal_object(
-/*=====================*/
- sync_array_t* arr, /* in: wait array */
- void* object) /* in: wait object */
+sync_array_object_signalled(
+/*========================*/
+ sync_array_t* arr) /* in: wait array */
{
- sync_cell_t* cell;
- ulint count;
- ulint i;
-
sync_array_enter(arr);
arr->sg_count++;
- i = 0;
- count = 0;
-
- while (count < arr->n_reserved) {
-
- cell = sync_array_get_nth_cell(arr, i);
-
- if (cell->wait_object != NULL) {
-
- count++;
- if (cell->wait_object == object) {
-
- sync_cell_event_set(cell);
- }
- }
-
- i++;
- }
-
sync_array_exit(arr);
}
@@ -881,7 +834,17 @@ sync_arr_wake_threads_if_sema_free(void)
if (sync_arr_cell_can_wake_up(cell)) {
- sync_cell_event_set(cell);
+ if (cell->request_type == SYNC_MUTEX) {
+ mutex_t* mutex;
+
+ mutex = cell->wait_object;
+ os_event_set(mutex->event);
+ } else {
+ rw_lock_t* lock;
+
+ lock = cell->wait_object;
+ os_event_set(lock->event);
+ }
}
}
@@ -911,7 +874,7 @@ sync_array_print_long_waits(void)
cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
- if (cell->wait_object != NULL
+ if (cell->wait_object != NULL && cell->waiting
&& difftime(time(NULL), cell->reservation_time) > 240) {
fputs("InnoDB: Warning: a long semaphore wait:\n",
stderr);
@@ -919,7 +882,7 @@ sync_array_print_long_waits(void)
noticed = TRUE;
}
- if (cell->wait_object != NULL
+ if (cell->wait_object != NULL && cell->waiting
&& difftime(time(NULL), cell->reservation_time)
> fatal_timeout) {
fatal = TRUE;
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index 973b46fdd50..050de73db9e 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -128,6 +128,7 @@ rw_lock_create_func(
lock->last_x_file_name = "not yet reserved";
lock->last_s_line = 0;
lock->last_x_line = 0;
+ lock->event = os_event_create(NULL);
mutex_enter(&rw_lock_list_mutex);
@@ -163,6 +164,7 @@ rw_lock_free(
mutex_free(rw_lock_get_mutex(lock));
mutex_enter(&rw_lock_list_mutex);
+ os_event_free(lock->event);
if (UT_LIST_GET_PREV(list, lock)) {
ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 43249f4b96f..95bf83dce79 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -212,6 +212,7 @@ mutex_create_func(
os_fast_mutex_init(&(mutex->os_fast_mutex));
mutex->lock_word = 0;
#endif
+ mutex->event = os_event_create(NULL);
mutex_set_waiters(mutex, 0);
mutex->magic_n = MUTEX_MAGIC_N;
#ifdef UNIV_SYNC_DEBUG
@@ -288,6 +289,8 @@ mutex_free(
mutex_exit(&mutex_list_mutex);
}
+ os_event_free(mutex->event);
+
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex));
#endif
@@ -564,8 +567,8 @@ mutex_signal_object(
/* The memory order of resetting the waiters field and
signaling the object is important. See LEMMA 1 above. */
-
- sync_array_signal_object(sync_primary_wait_array, mutex);
+ os_event_set(mutex->event);
+ sync_array_object_signalled(sync_primary_wait_array);
}
#ifdef UNIV_SYNC_DEBUG
@@ -1114,6 +1117,7 @@ sync_thread_add_level(
ut_a(sync_thread_levels_g(array, SYNC_PURGE_SYS));
} else if (level == SYNC_TREE_NODE) {
ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
+ || sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
} else if (level == SYNC_TREE_NODE_FROM_HASH) {
ut_a(1);
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index c2d98a81042..dc6d658fcdf 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -89,8 +89,8 @@ DEFS = -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" $(target_defs)
if HAVE_YASSL
-yassl_las = $(top_srcdir)/extra/yassl/src/libyassl.la \
- $(top_srcdir)/extra/yassl/taocrypt/src/libtaocrypt.la
+yassl_las = $(top_builddir)/extra/yassl/src/libyassl.la \
+ $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la
endif
# The automatic dependencies miss this
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 9e1d70a47df..59089d5ec18 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -82,6 +82,7 @@ const char *client_errors[]=
"Prepared statement contains no metadata",
"Attempt to read a row while there is no result set associated with the statement",
"This feature is not implemented yet",
+ "Lost connection to MySQL server at '%s', system error: %d",
""
};
@@ -145,6 +146,7 @@ const char *client_errors[]=
"Prepared statement contains no metadata",
"Attempt to read a row while there is no result set associated with the statement",
"This feature is not implemented yet",
+ "Lost connection to MySQL server at '%s', system error: %d",
""
};
@@ -206,6 +208,7 @@ const char *client_errors[]=
"Prepared statement contains no metadata",
"Attempt to read a row while there is no result set associated with the statement",
"This feature is not implemented yet",
+ "Lost connection to MySQL server at '%s', system error: %d",
""
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 8786655d9c3..304c20132ff 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -175,6 +175,9 @@ void STDCALL mysql_server_end()
#ifdef EMBEDDED_LIBRARY
end_embedded_server();
#endif
+ finish_client_errs();
+ vio_end();
+
/* If library called my_init(), free memory allocated by it */
if (!org_my_init_done)
{
@@ -185,10 +188,11 @@ void STDCALL mysql_server_end()
#endif
}
else
+ {
+ free_charsets();
mysql_thread_end();
- finish_client_errs();
- free_charsets();
- vio_end();
+ }
+
mysql_client_init= org_my_init_done= 0;
#ifdef EMBEDDED_SERVER
if (stderror_file)
@@ -2100,7 +2104,7 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
}
stmt->bind= stmt->params + stmt->param_count;
stmt->state= MYSQL_STMT_PREPARE_DONE;
- DBUG_PRINT("info", ("Parameter count: %ld", stmt->param_count));
+ DBUG_PRINT("info", ("Parameter count: %u", stmt->param_count));
DBUG_RETURN(0);
}
@@ -2443,10 +2447,10 @@ static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
{
NET *net= &stmt->mysql->net;
DBUG_ENTER("store_param");
- DBUG_PRINT("enter",("type: %d, buffer:%lx, length: %lu is_null: %d",
+ DBUG_PRINT("enter",("type: %d buffer: 0x%lx length: %lu is_null: %d",
param->buffer_type,
- param->buffer ? param->buffer : "0", *param->length,
- *param->is_null));
+ (long) (param->buffer ? param->buffer : NullS),
+ *param->length, *param->is_null));
if (*param->is_null)
store_param_null(net, param);
@@ -2478,6 +2482,8 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
NET *net= &mysql->net;
char buff[4 /* size of stmt id */ +
5 /* execution flags */];
+ my_bool res;
+
DBUG_ENTER("execute");
DBUG_DUMP("packet", packet, length);
@@ -2485,16 +2491,18 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
int4store(buff, stmt->stmt_id); /* Send stmt id to server */
buff[4]= (char) stmt->flags;
int4store(buff+5, 1); /* iteration count */
- if (cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
- packet, length, 1, NULL) ||
- (*mysql->methods->read_query_result)(mysql))
+
+ res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
+ packet, length, 1, NULL) ||
+ (*mysql->methods->read_query_result)(mysql));
+ stmt->affected_rows= mysql->affected_rows;
+ stmt->server_status= mysql->server_status;
+ stmt->insert_id= mysql->insert_id;
+ if (res)
{
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
DBUG_RETURN(1);
}
- stmt->affected_rows= mysql->affected_rows;
- stmt->server_status= mysql->server_status;
- stmt->insert_id= mysql->insert_id;
DBUG_RETURN(0);
}
@@ -3325,8 +3333,8 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
MYSQL_BIND *param;
DBUG_ENTER("mysql_stmt_send_long_data");
DBUG_ASSERT(stmt != 0);
- DBUG_PRINT("enter",("param no : %d, data : %lx, length : %ld",
- param_number, data, length));
+ DBUG_PRINT("enter",("param no: %d data: 0x%lx, length : %ld",
+ param_number, (long) data, length));
/*
We only need to check for stmt->param_count, if it's not null
@@ -4409,7 +4417,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
ulong bind_count= stmt->field_count;
uint param_count= 0;
DBUG_ENTER("mysql_stmt_bind_result");
- DBUG_PRINT("enter",("field_count: %d", bind_count));
+ DBUG_PRINT("enter",("field_count: %lu", bind_count));
if (!bind_count)
{
diff --git a/libmysql_r/Makefile.am b/libmysql_r/Makefile.am
index aaf81add00b..062acccda07 100644
--- a/libmysql_r/Makefile.am
+++ b/libmysql_r/Makefile.am
@@ -29,8 +29,6 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
## automake barfs if you don't use $(srcdir) or $(top_srcdir) in include
include $(top_srcdir)/libmysql/Makefile.shared
-libmysql_dir = $(top_srcdir)/libmysql
-
libmysqlclient_r_la_SOURCES = $(target_sources)
libmysqlclient_r_la_LIBADD = $(target_libadd) $(yassl_las)
libmysqlclient_r_la_LDFLAGS = $(target_ldflags)
@@ -38,7 +36,9 @@ libmysqlclient_r_la_LDFLAGS = $(target_ldflags)
# This is called from the toplevel makefile
link_sources:
set -x; \
- for f in `cd $(libmysql_dir) && echo *.[ch]`; do \
- rm -f $$f; \
- @LN_CP_F@ $(libmysql_dir)/$$f $$f; \
+ for d in $(top_srcdir)/libmysql $(top_builddir)/libmysql; do \
+ for f in `cd $$d && echo *.[ch]`; do \
+ rm -f $$f; \
+ @LN_CP_F@ $$d/$$f $$f; \
+ done; \
done
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index 89b473fb815..cdd71724166 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -25,9 +25,10 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
-DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\""
-INCLUDES= @bdb_includes@ \
+INCLUDES= @bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \
-I$(top_builddir)/include -I$(top_srcdir)/include \
- -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples \
+ -I$(top_builddir)/sql -I$(top_srcdir)/sql \
+ -I$(top_srcdir)/sql/examples \
-I$(top_srcdir)/regex \
$(openssl_includes) @ZLIB_INCLUDES@
@@ -118,16 +119,28 @@ endif
#libmysqld_la_LDFLAGS = -version-info @SHARED_LIB_VERSION@
#CLEANFILES = $(libmysqld_la_LIBADD) libmysqld.la
-# This is called from the toplevel makefile
+# This is called from the toplevel makefile. If we can link now
+# to an existing file in source, we do that, else we assume it
+# will show up in the build tree eventually (generated file).
link_sources:
set -x; \
for f in $(sqlsources); do \
rm -f $$f; \
- @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \
+ if test -e $(top_srcdir)/sql/$$f ; \
+ then \
+ @LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \
+ else \
+ @LN_CP_F@ $(top_builddir)/sql/$$f $$f; \
+ fi ; \
done; \
for f in $(libmysqlsources); do \
rm -f $$f; \
- @LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \
+ if test -e $(top_srcdir)/libmysql/$$f ; \
+ then \
+ @LN_CP_F@ $(top_srcdir)/libmysql/$$f $$f; \
+ else \
+ @LN_CP_F@ $(top_builddir)/libmysql/$$f $$f; \
+ fi ; \
done; \
for f in $(sqlexamplessources); do \
rm -f $$f; \
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 0df7014ba16..1006ee61923 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -278,26 +278,27 @@ static int emb_stmt_execute(MYSQL_STMT *stmt)
{
DBUG_ENTER("emb_stmt_execute");
char header[5];
- MYSQL_DATA *res;
THD *thd;
+ my_bool res;
int4store(header, stmt->stmt_id);
header[4]= stmt->flags;
thd= (THD*)stmt->mysql->thd;
thd->client_param_count= stmt->param_count;
thd->client_params= stmt->params;
- if (emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE,0,0,
- header, sizeof(header), 1, stmt) ||
- emb_read_query_result(stmt->mysql))
+
+ res= test(emb_advanced_command(stmt->mysql, COM_STMT_EXECUTE, 0, 0,
+ header, sizeof(header), 1, stmt) ||
+ emb_read_query_result(stmt->mysql));
+ stmt->affected_rows= stmt->mysql->affected_rows;
+ stmt->insert_id= stmt->mysql->insert_id;
+ stmt->server_status= stmt->mysql->server_status;
+ if (res)
{
NET *net= &stmt->mysql->net;
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
DBUG_RETURN(1);
}
- stmt->affected_rows= stmt->mysql->affected_rows;
- stmt->insert_id= stmt->mysql->insert_id;
- stmt->server_status= stmt->mysql->server_status;
-
DBUG_RETURN(0);
}
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index cb4fa104b4c..58a22686199 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -206,7 +206,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
}
}
- DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
+ DBUG_PRINT("exit",("Mysql handler: 0x%lx", (long) mysql));
DBUG_RETURN(mysql);
error:
diff --git a/myisam/mi_close.c b/myisam/mi_close.c
index 62f5617de1a..8a4f6ee7f5d 100644
--- a/myisam/mi_close.c
+++ b/myisam/mi_close.c
@@ -28,8 +28,9 @@ int mi_close(register MI_INFO *info)
int error=0,flag;
MYISAM_SHARE *share=info->s;
DBUG_ENTER("mi_close");
- DBUG_PRINT("enter",("base: %lx reopen: %u locks: %u",
- info,(uint) share->reopen, (uint) share->tot_locks));
+ DBUG_PRINT("enter",("base: 0x%lx reopen: %u locks: %u",
+ (long) info, (uint) share->reopen,
+ (uint) share->tot_locks));
pthread_mutex_lock(&THR_LOCK_myisam);
if (info->lock_type == F_EXTRA_LCK)
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index c6e9da03adf..7515438f3a4 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -428,8 +428,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_segs)
share.state.rec_per_key_part[key_segs-1]=1L;
length+=key_length;
- keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff,
- pointer,MI_MAX_KEYPTR_SIZE);
+ keydef->block_length= (uint16) MI_BLOCK_SIZE(length-real_length_diff,
+ pointer,MI_MAX_KEYPTR_SIZE);
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
length >= MI_MAX_KEY_BUFF)
{
diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c
index 85cc60bdd9d..471420d99c0 100644
--- a/myisam/mi_delete.c
+++ b/myisam/mi_delete.c
@@ -165,7 +165,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
DBUG_PRINT("error",("Couldn't allocate memory"));
DBUG_RETURN(my_errno=ENOMEM);
}
- DBUG_PRINT("info",("root_page: %ld",old_root));
+ DBUG_PRINT("info",("root_page: %ld", (long) old_root));
if (!_mi_fetch_keypage(info,keyinfo,old_root,DFLT_INIT_HITS,root_buff,0))
{
error= -1;
@@ -410,7 +410,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key,
MYISAM_SHARE *share=info->s;
MI_KEY_PARAM s_temp;
DBUG_ENTER("del");
- DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", leaf_page,
+ DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", (long) leaf_page,
(ulong) keypos));
DBUG_DUMP("leaf_buff",(byte*) leaf_buff,mi_getint(leaf_buff));
@@ -597,7 +597,8 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
else
{ /* Page is full */
endpos=anc_buff+anc_length;
- DBUG_PRINT("test",("anc_buff: %lx endpos: %lx",anc_buff,endpos));
+ DBUG_PRINT("test",("anc_buff: 0x%lx endpos: 0x%lx",
+ (long) anc_buff, (long) endpos));
if (keypos != anc_buff+2+key_reflength &&
!_mi_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length))
goto err;
@@ -775,7 +776,7 @@ static uint remove_key(MI_KEYDEF *keyinfo, uint nod_flag,
int s_length;
uchar *start;
DBUG_ENTER("remove_key");
- DBUG_PRINT("enter",("keypos: %lx page_end: %lx",keypos,page_end));
+ DBUG_PRINT("enter",("keypos: 0x%lx page_end: 0x%lx",(long) keypos, (long) page_end));
start=keypos;
if (!(keyinfo->flag &
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index ef5ab73f1a9..6590e6bd92b 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -1066,8 +1066,8 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
err:
my_errno= HA_ERR_WRONG_IN_RECORD;
- DBUG_PRINT("error",("to_end: %lx -> %lx from_end: %lx -> %lx",
- to,to_end,from,from_end));
+ DBUG_PRINT("error",("to_end: 0x%lx -> 0x%lx from_end: 0x%lx -> 0x%lx",
+ (long) to, (long) to_end, (long) from, (long) from_end));
DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length);
DBUG_RETURN(MY_FILE_ERROR);
} /* _mi_rec_unpack */
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 01bd0c43119..c6f9799bd67 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -52,7 +52,7 @@ static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record);
uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
const byte *record, my_off_t filepos)
{
- byte *pos,*end;
+ byte *pos;
uchar *start;
reg1 HA_KEYSEG *keyseg;
my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
@@ -107,18 +107,17 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
}
if (keyseg->flag & HA_SPACE_PACK)
{
- end= pos + length;
if (type != HA_KEYTYPE_NUM)
{
- while (end > pos && end[-1] == ' ')
- end--;
+ length= cs->cset->lengthsp(cs, pos, length);
}
else
{
+ byte *end= pos + length;
while (pos < end && pos[0] == ' ')
pos++;
+ length=(uint) (end-pos);
}
- length=(uint) (end-pos);
FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
memcpy((byte*) key,(byte*) pos,(size_t) char_length);
@@ -403,8 +402,10 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
pos= record+keyseg->start;
if (keyseg->type != (int) HA_KEYTYPE_NUM)
{
- memcpy(pos,key,(size_t) length);
- bfill(pos+length,keyseg->length-length,' ');
+ memcpy(pos,key,(size_t) length);
+ keyseg->charset->cset->fill(keyseg->charset,
+ pos + length, keyseg->length - length,
+ ' ');
}
else
{
diff --git a/myisam/mi_keycache.c b/myisam/mi_keycache.c
index fb13f3703a2..d595be3a684 100644
--- a/myisam/mi_keycache.c
+++ b/myisam/mi_keycache.c
@@ -54,8 +54,8 @@ int mi_assign_to_key_cache(MI_INFO *info,
int error= 0;
MYISAM_SHARE* share= info->s;
DBUG_ENTER("mi_assign_to_key_cache");
- DBUG_PRINT("enter",("old_key_cache_handle: %lx new_key_cache_handle: %lx",
- share->key_cache, key_cache));
+ DBUG_PRINT("enter",("old_key_cache_handle: 0x%lx new_key_cache_handle: 0x%lx",
+ (long) share->key_cache, (long) key_cache));
/*
Skip operation if we didn't change key cache. This can happen if we
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index a52ab5aad1f..bf20eb3f270 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -336,6 +336,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
goto err;
}
}
+ else if (pos->type == HA_KEYTYPE_BINARY)
+ pos->charset= &my_charset_bin;
}
if (share->keyinfo[i].flag & HA_SPATIAL)
{
diff --git a/myisam/mi_page.c b/myisam/mi_page.c
index 5240c063fba..d18a10c3cde 100644
--- a/myisam/mi_page.c
+++ b/myisam/mi_page.c
@@ -27,7 +27,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
uchar *tmp;
uint page_size;
DBUG_ENTER("_mi_fetch_keypage");
- DBUG_PRINT("enter",("page: %ld",page));
+ DBUG_PRINT("enter",("page: %ld", (long) page));
tmp=(uchar*) key_cache_read(info->s->key_cache,
info->s->kfile, page, level, (byte*) buff,
@@ -80,7 +80,7 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
my_errno=EINVAL;
DBUG_RETURN((-1));
}
- DBUG_PRINT("page",("write page at: %lu",(long) page,buff));
+ DBUG_PRINT("page",("write page at: %lu",(long) page));
DBUG_DUMP("buff",(byte*) buff,mi_getint(buff));
#endif
diff --git a/myisam/mi_statrec.c b/myisam/mi_statrec.c
index 42352f63c66..5e6ea939eca 100644
--- a/myisam/mi_statrec.c
+++ b/myisam/mi_statrec.c
@@ -255,8 +255,8 @@ int _mi_read_rnd_static_record(MI_INFO *info, byte *buf,
if (filepos >= info->state->data_file_length)
{
DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld",
- filepos/share->base.reclength,filepos,
- info->state->records, info->state->del));
+ (long) filepos/share->base.reclength, (long) filepos,
+ (long) info->state->records, (long) info->state->del));
fast_mi_writeinfo(info);
DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE);
}
diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c
index 6a6dcb971a2..0959769992c 100644
--- a/myisam/mi_test2.c
+++ b/myisam/mi_test2.c
@@ -813,7 +813,7 @@ end:
printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
if (rec_pointer_size)
printf("Record pointer size: %d\n",rec_pointer_size);
- printf("myisam_block_size: %u\n", myisam_block_size);
+ printf("myisam_block_size: %lu\n", myisam_block_size);
if (key_cacheing)
{
puts("Key cache used");
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index 9ab8753f6d7..fb64ec2bb8b 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -339,7 +339,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
my_bool was_last_key;
my_off_t next_page, dupp_key_pos;
DBUG_ENTER("w_search");
- DBUG_PRINT("enter",("page: %ld",page));
+ DBUG_PRINT("enter",("page: %ld", (long) page));
search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
@@ -462,7 +462,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
uchar *endpos, *prev_key;
MI_KEY_PARAM s_temp;
DBUG_ENTER("_mi_insert");
- DBUG_PRINT("enter",("key_pos: %lx",key_pos));
+ DBUG_PRINT("enter",("key_pos: 0x%lx", (long) key_pos));
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,USE_WHOLE_KEY););
nod_flag=mi_test_if_nod(anc_buff);
@@ -483,8 +483,8 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
DBUG_PRINT("test",("t_length: %d ref_len: %d",
t_length,s_temp.ref_length));
- DBUG_PRINT("test",("n_ref_len: %d n_length: %d key_pos: %lx",
- s_temp.n_ref_length,s_temp.n_length,s_temp.key));
+ DBUG_PRINT("test",("n_ref_len: %d n_length: %d key_pos: 0x%lx",
+ s_temp.n_ref_length,s_temp.n_length, (long) s_temp.key));
}
#endif
if (t_length > 0)
@@ -677,7 +677,8 @@ uchar *_mi_find_half_pos(uint nod_flag, MI_KEYDEF *keyinfo, uchar *page,
} while (page < end);
*return_key_length=length;
*after_key=page;
- DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end));
+ DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx half: 0x%lx",
+ (long) lastpos, (long) page, (long) end));
DBUG_RETURN(lastpos);
} /* _mi_find_half_pos */
@@ -732,7 +733,8 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page,
}
*return_key_length=last_length;
*after_key=lastpos;
- DBUG_PRINT("exit",("returns: %lx page: %lx end: %lx",prevpos,page,end));
+ DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx end: 0x%lx",
+ (long) prevpos,(long) page,(long) end));
DBUG_RETURN(prevpos);
} /* _mi_find_last_pos */
@@ -768,7 +770,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
next_page= _mi_kpos(info->s->base.key_reflength,
father_key_pos+father_keylength);
buff=info->buff;
- DBUG_PRINT("test",("use right page: %lu",next_page));
+ DBUG_PRINT("test",("use right page: %lu", (ulong) next_page));
}
else
{
@@ -777,7 +779,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo,
next_page= _mi_kpos(info->s->base.key_reflength,father_key_pos);
/* Fix that curr_buff is to left */
buff=curr_buff; curr_buff=info->buff;
- DBUG_PRINT("test",("use left page: %lu",next_page));
+ DBUG_PRINT("test",("use left page: %lu", (ulong) next_page));
} /* father_key_pos ptr to parting key */
if (!_mi_fetch_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,info->buff,0))
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index e80a3ffacd9..912ed22d278 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -1105,18 +1105,18 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
my_off_t total_count;
char llbuf[32];
- DBUG_PRINT("info", ("column: %3u", count - huff_counts + 1));
+ DBUG_PRINT("info", ("column: %3u", (uint) (count - huff_counts + 1)));
if (verbose >= 2)
- VOID(printf("column: %3u\n", count - huff_counts + 1));
+ VOID(printf("column: %3u\n", (uint) (count - huff_counts + 1)));
if (count->tree_buff)
{
DBUG_PRINT("info", ("number of distinct values: %u",
- (count->tree_pos - count->tree_buff) /
- count->field_length));
+ (uint) ((count->tree_pos - count->tree_buff) /
+ count->field_length)));
if (verbose >= 2)
VOID(printf("number of distinct values: %u\n",
- (count->tree_pos - count->tree_buff) /
- count->field_length));
+ (uint) ((count->tree_pos - count->tree_buff) /
+ count->field_length)));
}
total_count= 0;
for (idx= 0; idx < 256; idx++)
@@ -1965,7 +1965,7 @@ static char *bindigits(ulonglong value, uint bits)
DBUG_ASSERT(idx < sizeof(digits));
while (idx)
- *(ptr++)= '0' + ((value >> (--idx)) & 1);
+ *(ptr++)= '0' + ((char) (value >> (--idx)) & (char) 1);
*ptr= '\0';
return digits;
}
@@ -1995,7 +1995,7 @@ static char *hexdigits(ulonglong value)
DBUG_ASSERT(idx < sizeof(digits));
while (idx)
{
- if ((*(ptr++)= '0' + ((value >> (4 * (--idx))) & 0xf)) > '9')
+ if ((*(ptr++)= '0' + ((char) (value >> (4 * (--idx))) & (char) 0xf)) > '9')
*(ptr - 1)+= 'a' - '9' - 1;
}
*ptr= '\0';
@@ -2036,7 +2036,7 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees)
uint huff_tree_bits;
huff_tree_bits=max_bit(trees ? trees-1 : 0);
- DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", (" "));
DBUG_PRINT("info", ("column types:"));
DBUG_PRINT("info", ("FIELD_NORMAL 0"));
DBUG_PRINT("info", ("FIELD_SKIP_ENDSPACE 1"));
@@ -2048,12 +2048,12 @@ static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees)
DBUG_PRINT("info", ("FIELD_ZERO 7"));
DBUG_PRINT("info", ("FIELD_VARCHAR 8"));
DBUG_PRINT("info", ("FIELD_CHECK 9"));
- DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", (" "));
DBUG_PRINT("info", ("pack type as a set of flags:"));
DBUG_PRINT("info", ("PACK_TYPE_SELECTED 1"));
DBUG_PRINT("info", ("PACK_TYPE_SPACE_FIELDS 2"));
DBUG_PRINT("info", ("PACK_TYPE_ZERO_FILL 4"));
- DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", (" "));
if (verbose >= 2)
{
VOID(printf("\n"));
@@ -2126,7 +2126,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
return 0;
}
- DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", (" "));
if (verbose >= 2)
VOID(printf("\n"));
tree_no= 0;
@@ -2137,7 +2137,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
if (huff_tree->tree_number == 0)
continue; /* Deleted tree */
tree_no++;
- DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", (" "));
if (verbose >= 3)
VOID(printf("\n"));
/* Count the total number of elements (byte codes or column values). */
@@ -2280,11 +2280,11 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
{
VOID(fflush(stdout));
VOID(fprintf(stderr, "error: Huffman code too long: %u/%u\n",
- bits, 8 * sizeof(code)));
+ bits, (uint) (8 * sizeof(code))));
errors++;
break;
}
- idx+= code & 1;
+ idx+= (uint) code & 1;
if (idx >= length)
{
VOID(fflush(stdout));
@@ -2329,7 +2329,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
}
flush_bits();
}
- DBUG_PRINT("info", (""));
+ DBUG_PRINT("info", (" "));
if (verbose >= 2)
VOID(printf("\n"));
my_afree((gptr) packed_tree);
@@ -2507,7 +2507,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
end_pos-=count->max_zero_fill;
field_length-=count->max_zero_fill;
- switch(count->field_type) {
+ switch (count->field_type) {
case FIELD_SKIP_ZERO:
if (!memcmp((byte*) start_pos,zero_string,field_length))
{
@@ -2726,6 +2726,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
break;
}
case FIELD_LAST:
+ case FIELD_enum_val_count:
abort(); /* Impossible */
}
start_pos+=count->max_zero_fill;
diff --git a/myisam/sort.c b/myisam/sort.c
index f3a5fe59e13..eebef888e4a 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -322,159 +322,164 @@ pthread_handler_t thr_find_all_keys(void *arg)
if (my_thread_init())
goto err;
- DBUG_ENTER("thr_find_all_keys");
- DBUG_PRINT("enter", ("master: %d", sort_param->master));
- if (sort_param->sort_info->got_error)
- goto err;
- if (sort_param->keyinfo->flag && HA_VAR_LENGTH_KEY)
- {
- sort_param->write_keys= write_keys_varlen;
- sort_param->read_to_buffer= read_to_buffer_varlen;
- sort_param->write_key= write_merge_key_varlen;
- }
- else
- {
- sort_param->write_keys= write_keys;
- sort_param->read_to_buffer= read_to_buffer;
- sort_param->write_key= write_merge_key;
- }
+ { /* Add extra block since DBUG_ENTER declare variables */
+ DBUG_ENTER("thr_find_all_keys");
+ DBUG_PRINT("enter", ("master: %d", sort_param->master));
+ if (sort_param->sort_info->got_error)
+ goto err;
- my_b_clear(&sort_param->tempfile);
- my_b_clear(&sort_param->tempfile_for_exceptions);
- bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
- bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
- sort_keys= (uchar **) NULL;
+ if (sort_param->keyinfo->flag & HA_VAR_LENGTH_KEY)
+ {
+ sort_param->write_keys= write_keys_varlen;
+ sort_param->read_to_buffer= read_to_buffer_varlen;
+ sort_param->write_key= write_merge_key_varlen;
+ }
+ else
+ {
+ sort_param->write_keys= write_keys;
+ sort_param->read_to_buffer= read_to_buffer;
+ sort_param->write_key= write_merge_key;
+ }
- memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY);
- idx= sort_param->sort_info->max_records;
- sort_length= sort_param->key_length;
- maxbuffer= 1;
+ my_b_clear(&sort_param->tempfile);
+ my_b_clear(&sort_param->tempfile_for_exceptions);
+ bzero((char*) &sort_param->buffpek, sizeof(sort_param->buffpek));
+ bzero((char*) &sort_param->unique, sizeof(sort_param->unique));
+ sort_keys= (uchar **) NULL;
- while (memavl >= MIN_SORT_MEMORY)
- {
- if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <=
- (my_off_t) memavl)
- keys= idx+1;
- else
+ memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY);
+ idx= sort_param->sort_info->max_records;
+ sort_length= sort_param->key_length;
+ maxbuffer= 1;
+
+ while (memavl >= MIN_SORT_MEMORY)
{
- uint skr;
- do
+ if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <=
+ (my_off_t) memavl)
+ keys= idx+1;
+ else
{
- skr=maxbuffer;
- if (memavl < sizeof(BUFFPEK)*maxbuffer ||
- (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
- (sort_length+sizeof(char*))) <= 1 ||
- keys < (uint) maxbuffer)
+ uint skr;
+ do
{
- mi_check_print_error(sort_param->sort_info->param,
- "sort_buffer_size is to small");
- goto err;
+ skr= maxbuffer;
+ if (memavl < sizeof(BUFFPEK)*maxbuffer ||
+ (keys=(memavl-sizeof(BUFFPEK)*maxbuffer)/
+ (sort_length+sizeof(char*))) <= 1 ||
+ keys < (uint) maxbuffer)
+ {
+ mi_check_print_error(sort_param->sort_info->param,
+ "sort_buffer_size is to small");
+ goto err;
+ }
}
+ while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
}
- while ((maxbuffer= (int) (idx/(keys-1)+1)) != skr);
- }
- if ((sort_keys= (uchar**)
- my_malloc(keys*(sort_length+sizeof(char*))+
- ((sort_param->keyinfo->flag & HA_FULLTEXT) ?
- HA_FT_MAXBYTELEN : 0), MYF(0))))
- {
- if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
- maxbuffer, maxbuffer/2))
+ if ((sort_keys= (uchar**)
+ my_malloc(keys*(sort_length+sizeof(char*))+
+ ((sort_param->keyinfo->flag & HA_FULLTEXT) ?
+ HA_FT_MAXBYTELEN : 0), MYF(0))))
{
- my_free((gptr) sort_keys,MYF(0));
- sort_keys= (uchar **) NULL; /* for err: label */
+ if (my_init_dynamic_array(&sort_param->buffpek, sizeof(BUFFPEK),
+ maxbuffer, maxbuffer/2))
+ {
+ my_free((gptr) sort_keys,MYF(0));
+ sort_keys= (uchar **) NULL; /* for err: label */
+ }
+ else
+ break;
}
- else
- break;
+ old_memavl= memavl;
+ if ((memavl= memavl/4*3) < MIN_SORT_MEMORY &&
+ old_memavl > MIN_SORT_MEMORY)
+ memavl= MIN_SORT_MEMORY;
+ }
+ if (memavl < MIN_SORT_MEMORY)
+ {
+ mi_check_print_error(sort_param->sort_info->param,
+ "Sort buffer too small");
+ goto err; /* purecov: tested */
}
- old_memavl=memavl;
- if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY)
- memavl=MIN_SORT_MEMORY;
- }
- if (memavl < MIN_SORT_MEMORY)
- {
- mi_check_print_error(sort_param->sort_info->param, "Sort buffer too small");
- goto err; /* purecov: tested */
- }
- if (sort_param->sort_info->param->testflag & T_VERBOSE)
- printf("Key %d - Allocating buffer for %d keys\n",
- sort_param->key + 1, keys);
- sort_param->sort_keys= sort_keys;
+ if (sort_param->sort_info->param->testflag & T_VERBOSE)
+ printf("Key %d - Allocating buffer for %d keys\n",
+ sort_param->key + 1, keys);
+ sort_param->sort_keys= sort_keys;
- idx=error=0;
- sort_keys[0]=(uchar*) (sort_keys+keys);
+ idx= error= 0;
+ sort_keys[0]= (uchar*) (sort_keys+keys);
- DBUG_PRINT("info", ("reading keys"));
- while (!(error= sort_param->sort_info->got_error) &&
- !(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
- {
- if (sort_param->real_key_length > sort_param->key_length)
+ DBUG_PRINT("info", ("reading keys"));
+ while (!(error= sort_param->sort_info->got_error) &&
+ !(error= (*sort_param->key_read)(sort_param, sort_keys[idx])))
{
- if (write_key(sort_param, sort_keys[idx],
- &sort_param->tempfile_for_exceptions))
- goto err;
- continue;
- }
+ if (sort_param->real_key_length > sort_param->key_length)
+ {
+ if (write_key(sort_param, sort_keys[idx],
+ &sort_param->tempfile_for_exceptions))
+ goto err;
+ continue;
+ }
- if (++idx == keys)
+ if (++idx == keys)
+ {
+ if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
+ (BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
+ &sort_param->tempfile))
+ goto err;
+ sort_keys[0]= (uchar*) (sort_keys+keys);
+ memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length);
+ idx= 1;
+ }
+ sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
+ }
+ if (error > 0)
+ goto err;
+ if (sort_param->buffpek.elements)
{
- if (sort_param->write_keys(sort_param, sort_keys, idx - 1,
+ if (sort_param->write_keys(sort_param, sort_keys, idx,
(BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
&sort_param->tempfile))
goto err;
- sort_keys[0]=(uchar*) (sort_keys+keys);
- memcpy(sort_keys[0], sort_keys[idx - 1], (size_t) sort_param->key_length);
- idx=1;
+ sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
}
- sort_keys[idx]= sort_keys[idx - 1] + sort_param->key_length;
- }
- if (error > 0)
- goto err;
- if (sort_param->buffpek.elements)
- {
- if (sort_param->write_keys(sort_param, sort_keys, idx,
- (BUFFPEK*) alloc_dynamic(&sort_param->buffpek),
- &sort_param->tempfile))
- goto err;
- sort_param->keys= (sort_param->buffpek.elements - 1) * (keys - 1) + idx;
- }
- else
- sort_param->keys= idx;
+ else
+ sort_param->keys= idx;
- sort_param->sort_keys_length= keys;
- goto ok;
+ sort_param->sort_keys_length= keys;
+ goto ok;
err:
- DBUG_PRINT("error", ("got some error"));
- sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
- if (sort_keys)
- my_free((gptr) sort_keys,MYF(0));
- sort_param->sort_keys= 0;
- delete_dynamic(& sort_param->buffpek);
- close_cached_file(&sort_param->tempfile);
- close_cached_file(&sort_param->tempfile_for_exceptions);
+ DBUG_PRINT("error", ("got some error"));
+ sort_param->sort_info->got_error= 1; /* no need to protect with a mutex */
+ if (sort_keys)
+ my_free((gptr) sort_keys,MYF(0));
+ sort_param->sort_keys= 0;
+ delete_dynamic(& sort_param->buffpek);
+ close_cached_file(&sort_param->tempfile);
+ close_cached_file(&sort_param->tempfile_for_exceptions);
ok:
- /*
- Detach from the share if the writer is involved. Avoid others to
- be blocked. This includes a flush of the write buffer. This will
- also indicate EOF to the readers.
- */
- if (sort_param->sort_info->info->rec_cache.share)
- remove_io_thread(&sort_param->sort_info->info->rec_cache);
-
- /* Readers detach from the share if any. Avoid others to be blocked. */
- if (sort_param->read_cache.share)
- remove_io_thread(&sort_param->read_cache);
-
- pthread_mutex_lock(&sort_param->sort_info->mutex);
- if (!--sort_param->sort_info->threads_running)
- pthread_cond_signal(&sort_param->sort_info->cond);
- pthread_mutex_unlock(&sort_param->sort_info->mutex);
-
- DBUG_PRINT("exit", ("======== ending thread ========"));
+ /*
+ Detach from the share if the writer is involved. Avoid others to
+ be blocked. This includes a flush of the write buffer. This will
+ also indicate EOF to the readers.
+ */
+ if (sort_param->sort_info->info->rec_cache.share)
+ remove_io_thread(&sort_param->sort_info->info->rec_cache);
+
+ /* Readers detach from the share if any. Avoid others to be blocked. */
+ if (sort_param->read_cache.share)
+ remove_io_thread(&sort_param->read_cache);
+
+ pthread_mutex_lock(&sort_param->sort_info->mutex);
+ if (!--sort_param->sort_info->threads_running)
+ pthread_cond_signal(&sort_param->sort_info->cond);
+ pthread_mutex_unlock(&sort_param->sort_info->mutex);
+
+ DBUG_PRINT("exit", ("======== ending thread ========"));
+ }
my_thread_end();
return NULL;
}
@@ -542,7 +547,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
{
if (got_error)
continue;
- if (sinfo->keyinfo->flag && HA_VAR_LENGTH_KEY)
+ if (sinfo->keyinfo->flag & HA_VAR_LENGTH_KEY)
{
sinfo->write_keys=write_keys_varlen;
sinfo->read_to_buffer=read_to_buffer_varlen;
diff --git a/myisammrg/myrg_extra.c b/myisammrg/myrg_extra.c
index 62cf5f01aba..30bb46d27d4 100644
--- a/myisammrg/myrg_extra.c
+++ b/myisammrg/myrg_extra.c
@@ -28,7 +28,7 @@ int myrg_extra(MYRG_INFO *info,enum ha_extra_function function,
int error,save_error=0;
MYRG_TABLE *file;
DBUG_ENTER("myrg_extra");
- DBUG_PRINT("info",("function: %d",(ulong) function));
+ DBUG_PRINT("info",("function: %lu", (ulong) function));
if (function == HA_EXTRA_CACHE)
{
diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c
index f87b264081e..85464374d5d 100644
--- a/myisammrg/myrg_rkey.c
+++ b/myisammrg/myrg_rkey.c
@@ -88,7 +88,7 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table;
mi->once_flags|= RRND_PRESERVE_LASTINX;
DBUG_PRINT("info", ("using table no: %d",
- info->current_table - info->open_tables + 1));
+ (int) (info->current_table - info->open_tables + 1)));
DBUG_DUMP("result key", (byte*) mi->lastkey, mi->lastkey_length);
DBUG_RETURN(_myrg_mi_read_record(mi,buf));
}
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index 9f54b4fe192..74f8f478a33 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -58,6 +58,7 @@ dist-hook:
$(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.slave-mi $(distdir)/t
$(INSTALL_SCRIPT) $(srcdir)/t/*.sh $(distdir)/t
$(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include
+ $(INSTALL_DATA) $(srcdir)/include/*.test $(distdir)/include
$(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r
$(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data
@@ -87,6 +88,7 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/r/*.result $(DESTDIR)$(testdir)/r
$(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r
$(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include
+ $(INSTALL_DATA) $(srcdir)/include/*.test $(DESTDIR)$(testdir)/include
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data
diff --git a/mysql-test/include/analyze_failure_sync_with_master.test b/mysql-test/include/analyze_failure_sync_with_master.test
new file mode 100644
index 00000000000..e6fd32d2f46
--- /dev/null
+++ b/mysql-test/include/analyze_failure_sync_with_master.test
@@ -0,0 +1,15 @@
+# Connect to both master and slave
+connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
+connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
+
+vertical_results;
+
+echo == MASTER ===========================================================;
+connection master;
+show master status;
+show slave status;
+
+echo == SLAVE ===========================================================;
+connection slave;
+show master status;
+show slave status;
diff --git a/mysql-test/include/ctype_like_escape.inc b/mysql-test/include/ctype_like_escape.inc
index ac97fbaa1a0..d4abc33c178 100644
--- a/mysql-test/include/ctype_like_escape.inc
+++ b/mysql-test/include/ctype_like_escape.inc
@@ -11,8 +11,8 @@ insert into t1 values('ab_def');
insert into t1 values('abc_ef');
insert into t1 values('abcd_f');
insert into t1 values('abcde_');
--- should return ab_def
+# should return ab_def
select c1 as c1u from t1 where c1 like 'ab\_def';
--- should return ab_def
+# should return ab_def
select c1 as c2h from t1 where c1 like 'ab#_def' escape '#';
drop table t1;
diff --git a/mysql-test/include/federated.inc b/mysql-test/include/federated.inc
index 35cd33db3fb..c8e8ededa11 100644
--- a/mysql-test/include/federated.inc
+++ b/mysql-test/include/federated.inc
@@ -6,7 +6,7 @@ source ./include/master-slave.inc;
# remote table creation
connection slave;
---replicate-ignore-db=federated
+#--replicate-ignore-db=federated
stop slave;
--disable_warnings
diff --git a/mysql-test/include/mysqltest_while.inc b/mysql-test/include/mysqltest_while.inc
deleted file mode 100644
index 90b05ee2695..00000000000
--- a/mysql-test/include/mysqltest_while.inc
+++ /dev/null
@@ -1,137 +0,0 @@
-let $1 = 10;
-while ($1)
-{
-while ($1)
-{
-while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- while ($1)
-{
- echo $1;
- dec $1;
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
-}
diff --git a/mysql-test/include/report-features.test b/mysql-test/include/report-features.test
new file mode 100644
index 00000000000..df395f6e3f0
--- /dev/null
+++ b/mysql-test/include/report-features.test
@@ -0,0 +1,11 @@
+#
+# show server variables
+#
+
+--disable_query_log
+--echo ===== ENGINES =====
+show engines;
+--echo ===== VARIABLES =====
+show variables;
+--echo ===== STOP =====
+--enable_query_log
diff --git a/mysql-test/include/sourced.inc b/mysql-test/include/sourced.inc
deleted file mode 100644
index be1a270641a..00000000000
--- a/mysql-test/include/sourced.inc
+++ /dev/null
@@ -1 +0,0 @@
-echo here is the sourced script;
diff --git a/mysql-test/include/sourced1.inc b/mysql-test/include/sourced1.inc
deleted file mode 100644
index 920561e5de2..00000000000
--- a/mysql-test/include/sourced1.inc
+++ /dev/null
@@ -1 +0,0 @@
---source include/sourced.inc
diff --git a/mysql-test/include/sp-vars.inc b/mysql-test/include/sp-vars.inc
index 3e02c9d1709..c241af2fb54 100644
--- a/mysql-test/include/sp-vars.inc
+++ b/mysql-test/include/sp-vars.inc
@@ -1,6 +1,6 @@
delimiter |;
----------------------------------------------------------------------------
+# --------------------------------------------------------------------------
CREATE PROCEDURE sp_vars_check_dflt()
BEGIN
@@ -40,7 +40,7 @@ BEGIN
SELECT v17, v18, v19, v20;
END|
----------------------------------------------------------------------------
+# --------------------------------------------------------------------------
CREATE PROCEDURE sp_vars_check_assignment()
BEGIN
@@ -89,34 +89,43 @@ BEGIN
SELECT d1, d2, d3;
END|
----------------------------------------------------------------------------
+# --------------------------------------------------------------------------
CREATE FUNCTION sp_vars_check_ret1() RETURNS TINYINT
BEGIN
RETURN 1e200;
END|
----------------------------------------------------------------------------
+# --------------------------------------------------------------------------
CREATE FUNCTION sp_vars_check_ret2() RETURNS TINYINT
BEGIN
RETURN 10 * 10 * 10;
END|
----------------------------------------------------------------------------
+# --------------------------------------------------------------------------
CREATE FUNCTION sp_vars_check_ret3() RETURNS TINYINT
BEGIN
RETURN 'Hello, world';
END|
----------------------------------------------------------------------------
+# --------------------------------------------------------------------------
CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2)
BEGIN
RETURN 12 * 10 + 34 + 0.1234;
END|
----------------------------------------------------------------------------
+# --------------------------------------------------------------------------
+
+CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER
+BEGIN
+ DECLARE div_zero INTEGER;
+ SELECT 1/0 INTO div_zero;
+ RETURN div_zero;
+END|
+
+# --------------------------------------------------------------------------
delimiter ;|
diff --git a/mysql-test/include/strict_autoinc.inc b/mysql-test/include/strict_autoinc.inc
index 6960440f3a7..823efcc2040 100644
--- a/mysql-test/include/strict_autoinc.inc
+++ b/mysql-test/include/strict_autoinc.inc
@@ -2,6 +2,10 @@
# Test for strict-mode autoincrement
#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
set @org_mode=@@sql_mode;
eval create table t1
(
diff --git a/mysql-test/include/wait_for_query_to_suceed.inc b/mysql-test/include/wait_for_query_to_suceed.inc
new file mode 100644
index 00000000000..6ac1144620e
--- /dev/null
+++ b/mysql-test/include/wait_for_query_to_suceed.inc
@@ -0,0 +1,25 @@
+#
+# Run a query over and over until it suceeds ot timeout occurs
+#
+
+
+let $counter= 100;
+
+disable_abort_on_error;
+disable_query_log;
+disable_result_log;
+eval $query;
+while ($mysql_errno)
+{
+ eval $query;
+ sleep 0.1;
+ dec $counter;
+
+ if (!$counter)
+ {
+ die("Waited too long for query to suceed");
+ }
+}
+enable_abort_on_error;
+enable_query_log;
+enable_result_log;
diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh
index 4554b92857e..c30583503dc 100644
--- a/mysql-test/install_test_db.sh
+++ b/mysql-test/install_test_db.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (C) 1997-2002 MySQL AB
+# Copyright (C) 1997-2006 MySQL AB
# For a more info consult the file COPYRIGHT distributed with this file
# This scripts creates the privilege tables db, host, user, tables_priv,
@@ -7,19 +7,26 @@
if [ x$1 = x"--bin" ]; then
shift 1
+ BINARY_DIST=1
+
+ bindir=../bin
+ scriptdir=../bin
+ libexecdir=../libexec
# Check if it's a binary distribution or a 'make install'
if test -x ../libexec/mysqld
then
execdir=../libexec
+ elif test -x ../../sbin/mysqld # RPM installation
+ then
+ execdir=../../sbin
+ bindir=../../bin
+ scriptdir=../../bin
+ libexecdir=../../libexec
else
execdir=../bin
fi
- bindir=../bin
- BINARY_DIST=1
fix_bin=mysql-test
- scriptdir=../bin
- libexecdir=../libexec
else
execdir=../sql
bindir=../client
diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl
index 009269f382e..d270d72d526 100644
--- a/mysql-test/lib/mtr_cases.pl
+++ b/mysql-test/lib/mtr_cases.pl
@@ -5,11 +5,14 @@
# same name.
use File::Basename;
+use IO::File();
use strict;
sub collect_test_cases ($);
sub collect_one_test_case ($$$$$$$);
+sub mtr_options_from_test_file($$);
+
##############################################################################
#
# Collect information about test cases we are to run
@@ -37,12 +40,31 @@ sub collect_test_cases ($) {
opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!");
+ # ----------------------------------------------------------------------
+ # Disable some tests listed in disabled.def
+ # ----------------------------------------------------------------------
+ my %disabled;
+ if ( open(DISABLED, "$testdir/disabled.def" ) )
+ {
+ while ( <DISABLED> )
+ {
+ chomp;
+ if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
+ {
+ $disabled{$1}= $2;
+ }
+ }
+ close DISABLED;
+ }
+
if ( @::opt_cases )
{
- foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
+ foreach my $tname ( @::opt_cases )
+ {
+ # Run in specified order, no sort
my $elem= undef;
my $component_id= undef;
-
+
# Get rid of directory part (path). Leave the extension since it is used
# to understand type of the test.
@@ -65,7 +87,7 @@ sub collect_test_cases ($) {
# If target component is known, check that the specified test case
# exists.
- #
+ #
# Otherwise, try to guess the target component.
if ( $component_id )
@@ -100,31 +122,15 @@ sub collect_test_cases ($) {
}
}
- collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{},
+ collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
$component_id);
}
closedir TESTDIR;
}
else
{
- # ----------------------------------------------------------------------
- # Disable some tests listed in disabled.def
- # ----------------------------------------------------------------------
- my %disabled;
- if ( ! $::opt_ignore_disabled_def and open(DISABLED, "$testdir/disabled.def" ) )
+ foreach my $elem ( sort readdir(TESTDIR) )
{
- while ( <DISABLED> )
- {
- chomp;
- if ( /^\s*([^\s:]+)\s*:\s*(.*?)\s*$/ )
- {
- $disabled{$1}= $2;
- }
- }
- close DISABLED;
- }
-
- foreach my $elem ( sort readdir(TESTDIR) ) {
my $component_id= undef;
my $tname= undef;
@@ -140,8 +146,10 @@ sub collect_test_cases ($) {
{
next;
}
-
- next if $::opt_do_test and ! defined mtr_match_prefix($elem,$::opt_do_test);
+
+ # Skip tests that does not match the --do-test= filter
+ next if $::opt_do_test and
+ ! defined mtr_match_prefix($elem,$::opt_do_test);
collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
$component_id);
@@ -149,43 +157,79 @@ sub collect_test_cases ($) {
closedir TESTDIR;
}
- # To speed things up, we sort first in if the test require a restart
- # or not, second in alphanumeric order.
-
+ # Reorder the test cases in an order that will make them faster to run
if ( $::opt_reorder )
{
my %sort_criteria;
- my $tinfo;
# Make a mapping of test name to a string that represents how that test
# should be sorted among the other tests. Put the most important criterion
# first, then a sub-criterion, then sub-sub-criterion, et c.
- foreach $tinfo (@$cases)
+ foreach my $tinfo (@$cases)
{
- my @this_criteria = ();
-
- # Append the criteria for sorting, in order of importance.
- push(@this_criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~"); # Ending with "~" makes empty sort later than filled
- push(@this_criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0"));
- push(@this_criteria, "restart=" . ($tinfo->{'master_restart'} ? "1" : "0"));
- push(@this_criteria, "big_test=" . ($tinfo->{'big_test'} ? "1" : "0"));
- push(@this_criteria, join("|", sort keys %{$tinfo})); # Group similar things together. The values may differ substantially. FIXME?
- push(@this_criteria, $tinfo->{'name'}); # Finally, order by the name
-
- $sort_criteria{$tinfo->{"name"}} = join(" ", @this_criteria);
+ my @criteria = ();
+
+ # Look for tests that muct be in run in a defined order
+ # that is defined by test having the same name except for
+ # the ending digit
+
+ # Put variables into hash
+ my $test_name= $tinfo->{'name'};
+ my $depend_on_test_name;
+ if ( $test_name =~ /^([\D]+)([0-9]{1})$/ )
+ {
+ my $base_name= $1;
+ my $idx= $2;
+ mtr_verbose("$test_name => $base_name idx=$idx");
+ if ( $idx > 1 )
+ {
+ $idx-= 1;
+ $base_name= "$base_name$idx";
+ mtr_verbose("New basename $base_name");
+ }
+
+ foreach my $tinfo2 (@$cases)
+ {
+ if ( $tinfo2->{'name'} eq $base_name )
+ {
+ mtr_verbose("found dependent test $tinfo2->{'name'}");
+ $depend_on_test_name=$base_name;
+ }
+ }
+ }
+
+ if ( defined $depend_on_test_name )
+ {
+ mtr_verbose("Giving $test_name same critera as $depend_on_test_name");
+ $sort_criteria{$test_name} = $sort_criteria{$depend_on_test_name};
+ }
+ else
+ {
+ #
+ # Append the criteria for sorting, in order of importance.
+ #
+ push(@criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0"));
+ # Group test with equal options together.
+ # Ending with "~" makes empty sort later than filled
+ push(@criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~");
+
+ $sort_criteria{$test_name} = join(" ", @criteria);
+ }
}
- @$cases = sort { $sort_criteria{$a->{"name"}} cmp $sort_criteria{$b->{"name"}}; } @$cases;
+ @$cases = sort {
+ $sort_criteria{$a->{'name'}} . $a->{'name'} cmp
+ $sort_criteria{$b->{'name'}} . $b->{'name'}; } @$cases;
-### For debugging the sort-order
-# foreach $tinfo (@$cases)
-# {
-# print $sort_criteria{$tinfo->{"name"}};
-# print " -> \t";
-# print $tinfo->{"name"};
-# print "\n";
-# }
+ if ( $::opt_script_debug )
+ {
+ # For debugging the sort-order
+ foreach my $tinfo (@$cases)
+ {
+ print("$sort_criteria{$tinfo->{'name'}} -> \t$tinfo->{'name'}\n");
+ }
+ }
}
return $cases;
@@ -219,9 +263,6 @@ sub collect_one_test_case($$$$$$$) {
return;
}
- # ----------------------------------------------------------------------
- # Skip some tests but include in list, just mark them to skip
- # ----------------------------------------------------------------------
my $tinfo= {};
$tinfo->{'name'}= $tname;
@@ -229,6 +270,10 @@ sub collect_one_test_case($$$$$$$) {
$tinfo->{'component_id'} = $component_id;
push(@$cases, $tinfo);
+ # ----------------------------------------------------------------------
+ # Skip some tests but include in list, just mark them to skip
+ # ----------------------------------------------------------------------
+
if ( $::opt_skip_test and defined mtr_match_prefix($tname,$::opt_skip_test) )
{
$tinfo->{'skip'}= 1;
@@ -242,57 +287,31 @@ sub collect_one_test_case($$$$$$$) {
$tinfo->{'path'}= $path;
$tinfo->{'timezone'}= "GMT-3"; # for UNIX_TIMESTAMP tests to work
+ $tinfo->{'slave_num'}= 0; # Default, no slave
if ( defined mtr_match_prefix($tname,"rpl") )
{
if ( $::opt_skip_rpl )
{
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No replication tests(--skip-rpl)";
return;
}
- $tinfo->{'slave_num'}= 1; # Default, use one slave
- # FIXME currently we always restart slaves
- $tinfo->{'slave_restart'}= 1;
+ $tinfo->{'slave_num'}= 1; # Default for rpl* tests, use one slave
if ( $tname eq 'rpl_failsafe' or $tname eq 'rpl_chain_temp_table' )
{
-# $tinfo->{'slave_num'}= 3; # Not 3 ? Check old code, strange
+ # $tinfo->{'slave_num'}= 3; # Not 3 ? Check old code, strange
}
}
if ( defined mtr_match_prefix($tname,"federated") )
{
- $tinfo->{'slave_num'}= 1; # Default, use one slave
-
- # FIXME currently we always restart slaves
- $tinfo->{'slave_restart'}= 1;
- }
-
- # Cluster is needed by test case if testname contains ndb
- if ( defined mtr_match_substring($tname,"ndb") )
- {
- $tinfo->{'ndb_test'}= 1;
- if ( $::opt_skip_ndbcluster )
- {
- # Skip all ndb tests
- $tinfo->{'skip'}= 1;
- return;
- }
- if ( ! $::opt_with_ndbcluster )
- {
- # Ndb is not supported, skip them
- $tinfo->{'skip'}= 1;
- return;
- }
- }
- else
- {
- $tinfo->{'ndb_test'}= 0;
+ # Default, federated uses the first slave as it's federated database
+ $tinfo->{'slave_num'}= 1;
}
- # FIXME what about embedded_server + ndbcluster, skip ?!
-
my $master_opt_file= "$testdir/$tname-master.opt";
my $slave_opt_file= "$testdir/$tname-slave.opt";
my $slave_mi_file= "$testdir/$tname.slave-mi";
@@ -307,57 +326,59 @@ sub collect_one_test_case($$$$$$$) {
if ( -f $master_opt_file )
{
- $tinfo->{'master_restart'}= 1; # We think so for now
- MASTER_OPT:
- {
- my $master_opt= mtr_get_opts_from_file($master_opt_file);
+ my $master_opt= mtr_get_opts_from_file($master_opt_file);
- foreach my $opt ( @$master_opt )
- {
- my $value;
+ foreach my $opt ( @$master_opt )
+ {
+ my $value;
- # This is a dirty hack from old mysql-test-run, we use the opt
- # file to flag other things as well, it is not a opt list at
- # all
+ # The opt file is used both to send special options to the mysqld
+ # as well as pass special test case specific options to this
+ # script
- $value= mtr_match_prefix($opt, "--timezone=");
- if ( defined $value )
- {
- $tinfo->{'timezone'}= $value;
- last MASTER_OPT;
- }
+ $value= mtr_match_prefix($opt, "--timezone=");
+ if ( defined $value )
+ {
+ $tinfo->{'timezone'}= $value;
+ next;
+ }
- $value= mtr_match_prefix($opt, "--result-file=");
- if ( defined $value )
- {
- $tinfo->{'result_file'}= "r/$value.result";
- if ( $::opt_result_ext and $::opt_record or
- -f "$tinfo->{'result_file'}$::opt_result_ext")
- {
- $tinfo->{'result_file'}.= $::opt_result_ext;
- }
- $tinfo->{'master_restart'}= 0;
- last MASTER_OPT;
- }
+ $value= mtr_match_prefix($opt, "--result-file=");
+ if ( defined $value )
+ {
+ # Specifies the file mysqltest should compare
+ # output against
+ $tinfo->{'result_file'}= "r/$value.result";
+ next;
+ }
- # If we set default time zone, remove the one we have
- $value= mtr_match_prefix($opt, "--default-time-zone=");
- if ( defined $value )
- {
- $tinfo->{'master_opt'}= [];
- }
+ # If we set default time zone, remove the one we have
+ $value= mtr_match_prefix($opt, "--default-time-zone=");
+ if ( defined $value )
+ {
+ # Set timezone for this test case to something different
+ $tinfo->{'timezone'}= "GMT-8";
+ # Fallthrough, add the --default-time-zone option
+ }
+ # The --restart option forces a restart even if no special
+ # option is set. If the options are the same as next testcase
+ # there is no need to restart after the testcase
+ # has completed
+ if ( $opt eq "--force-restart" )
+ {
+ $tinfo->{'force_restart'}= 1;
+ next;
}
- # Ok, this was a real option list, add it
- push(@{$tinfo->{'master_opt'}}, @$master_opt);
+ # Ok, this was a real option, add it
+ push(@{$tinfo->{'master_opt'}}, $opt);
}
}
if ( -f $slave_opt_file )
{
- $tinfo->{'slave_restart'}= 1;
my $slave_opt= mtr_get_opts_from_file($slave_opt_file);
foreach my $opt ( @$slave_opt )
@@ -372,7 +393,6 @@ sub collect_one_test_case($$$$$$$) {
if ( -f $slave_mi_file )
{
$tinfo->{'slave_mi'}= mtr_get_opts_from_file($slave_mi_file);
- $tinfo->{'slave_restart'}= 1;
}
if ( -f $master_sh )
@@ -380,11 +400,12 @@ sub collect_one_test_case($$$$$$$) {
if ( $::glob_win32_perl )
{
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No tests with sh scripts on Windows";
+ return;
}
else
{
$tinfo->{'master_sh'}= $master_sh;
- $tinfo->{'master_restart'}= 1;
}
}
@@ -393,11 +414,12 @@ sub collect_one_test_case($$$$$$$) {
if ( $::glob_win32_perl )
{
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No tests with sh scripts on Windows";
+ return;
}
else
{
$tinfo->{'slave_sh'}= $slave_sh;
- $tinfo->{'slave_restart'}= 1;
}
}
@@ -411,56 +433,195 @@ sub collect_one_test_case($$$$$$$) {
}
# FIXME why this late?
+ my $marked_as_disabled= 0;
if ( $disabled->{$tname} )
{
- $tinfo->{'skip'}= 1;
- $tinfo->{'disable'}= 1; # Sub type of 'skip'
- $tinfo->{'comment'}= $disabled->{$tname} if $disabled->{$tname};
+ $marked_as_disabled= 1;
+ $tinfo->{'comment'}= $disabled->{$tname};
}
if ( -f $disabled_file )
{
- $tinfo->{'skip'}= 1;
- $tinfo->{'disable'}= 1; # Sub type of 'skip'
+ $marked_as_disabled= 1;
$tinfo->{'comment'}= mtr_fromfile($disabled_file);
}
+ # If test was marked as disabled, either opt_enable_disabled is off and then
+ # we skip this test, or it is on and then we run this test but warn
+
+ if ( $marked_as_disabled )
+ {
+ if ( $::opt_enable_disabled )
+ {
+ $tinfo->{'dont_skip_though_disabled'}= 1;
+ }
+ else
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'disable'}= 1; # Sub type of 'skip'
+ return;
+ }
+ }
+
if ( $component_id eq 'im' )
{
if ( $::glob_use_embedded_server )
{
$tinfo->{'skip'}= 1;
-
- mtr_report(
- "Instance Manager tests are not available in embedded mode. " .
- "Test case '$tname' is skipped.");
+ $tinfo->{'comment'}= "No IM with embedded server";
+ return;
}
elsif ( $::opt_ps_protocol )
{
$tinfo->{'skip'}= 1;
-
- mtr_report(
- "Instance Manager tests are not run with --ps-protocol. " .
- "Test case '$tname' is skipped.");
+ $tinfo->{'comment'}= "No IM with --ps-protocol";
+ return;
}
elsif ( $::opt_skip_im )
{
$tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No IM tests(--skip-im)";
+ return;
+ }
+ }
+ else
+ {
+ mtr_options_from_test_file($tinfo,"$testdir/${tname}.test");
+
+ if ( $tinfo->{'big_test'} and ! $::opt_big_test )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test need 'big-test' option";
+ return;
+ }
+
+ if ( $tinfo->{'ndb_extra'} and ! $::opt_ndb_extra_test )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test need 'ndb_extra' option";
+ return;
+ }
+
+ if ( $tinfo->{'require_manager'} )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test need the _old_ manager(to be removed)";
+ return;
+ }
+
+ if ( defined $tinfo->{'binlog_format'} and
+ ! ( $tinfo->{'binlog_format'} eq $::used_binlog_format ) )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Not running with binlog format '$tinfo->{'binlog_format'}'";
+ return;
+ }
+
+ if ( $tinfo->{'need_debug'} && ! $::debug_compiled_binaries )
+ {
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Test need debug binaries";
+ return;
+ }
- mtr_report(
- "Instance Manager executable is unavailable." .
- "Test case '$tname' is skipped.");
+ if ( $tinfo->{'ndb_test'} )
+ {
+ # This is a NDB test
+ if ( ! $::glob_ndbcluster_supported )
+ {
+ # Ndb is not supported, skip it
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No ndbcluster support";
+ return;
+ }
+ elsif ( $::opt_skip_ndbcluster )
+ {
+ # All ndb test's should be skipped
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No ndbcluster tests(--skip-ndbcluster)";
+ return;
+ }
+ }
+ else
+ {
+ # This is not a ndb test
+ if ( $::opt_with_ndbcluster_only )
+ {
+ # Only the ndb test should be run, all other should be skipped
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "Only ndbcluster tests(--with-ndbcluster-only)";
+ return;
+ }
}
+
+ if ( $tinfo->{'innodb_test'} )
+ {
+ # This is a test that need inndob
+ if ( $::mysqld_variables{'innodb'} eq "FALSE" )
+ {
+ # innodb is not supported, skip it
+ $tinfo->{'skip'}= 1;
+ $tinfo->{'comment'}= "No innodb support";
+ return;
+ }
+ }
+
}
+}
- # We can't restart a running server that may be in use
- if ( $::glob_use_running_server and
- ( $tinfo->{'master_restart'} or $tinfo->{'slave_restart'} ) )
+# List of tags in the .test files that if found should set
+# the specified value in "tinfo"
+our @tags=
+(
+ ["include/have_innodb.inc", "innodb_test", 1],
+ ["include/have_binlog_format_row.inc", "binlog_format", "row"],
+ ["include/have_binlog_format_statement.inc", "binlog_format", "stmt"],
+ ["include/have_binlog_format_mixed.inc", "binlog_format", "mixed"],
+ ["include/big_test.inc", "big_test", 1],
+ ["include/have_debug.inc", "need_debug", 1],
+ ["include/have_ndb.inc", "ndb_test", 1],
+ ["include/have_ndb_extra.inc", "ndb_extra", 1],
+ ["require_manager", "require_manager", 1],
+);
+
+sub mtr_options_from_test_file($$) {
+ my $tinfo= shift;
+ my $file= shift;
+ #mtr_verbose("$file");
+ my $F= IO::File->new($file) or mtr_error("can't open file \"$file\": $!");
+
+ while ( my $line= <$F> )
{
- $tinfo->{'skip'}= 1;
+ # Match this line against tag in "tags" array
+ foreach my $tag (@tags)
+ {
+ if ( index($line, $tag->[0]) >= 0 )
+ {
+ # Tag matched, assign value to "tinfo"
+ $tinfo->{"$tag->[1]"}= $tag->[2];
+ }
+ }
+
+ # If test sources another file, open it as well
+ if ( $line =~ /^\-\-([[:space:]]*)source(.*)$/ or
+ $line =~ /^([[:space:]]*)source(.*);$/ )
+ {
+ my $value= $2;
+ $value =~ s/^\s+//; # Remove leading space
+ $value =~ s/[[:space:]]+$//; # Remove ending space
+
+ my $sourced_file= "$::glob_mysql_test_dir/$value";
+ if ( -f $sourced_file )
+ {
+ # Only source the file if it exists, we may get
+ # false positives in the regexes above if someone
+ # writes "source nnnn;" in a test case(such as mysqltest.test)
+ mtr_options_from_test_file($tinfo, $sourced_file);
+ }
+ }
+
}
}
-
1;
diff --git a/mysql-test/lib/mtr_gcov.pl b/mysql-test/lib/mtr_gcov.pl
index 07aac1d2017..71d3d6a2a43 100644
--- a/mysql-test/lib/mtr_gcov.pl
+++ b/mysql-test/lib/mtr_gcov.pl
@@ -23,12 +23,28 @@ sub gcov_prepare () {
-or -name \*.da | xargs rm`;
}
+# Used by gcov
+our @mysqld_src_dirs=
+ (
+ "strings",
+ "mysys",
+ "include",
+ "extra",
+ "regex",
+ "isam",
+ "merge",
+ "myisam",
+ "myisammrg",
+ "heap",
+ "sql",
+ );
+
sub gcov_collect () {
print "Collecting source coverage info...\n";
-f $::opt_gcov_msg and unlink($::opt_gcov_msg);
-f $::opt_gcov_err and unlink($::opt_gcov_err);
- foreach my $d ( @::mysqld_src_dirs )
+ foreach my $d ( @mysqld_src_dirs )
{
chdir("$::glob_basedir/$d");
foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) )
diff --git a/mysql-test/lib/mtr_im.pl b/mysql-test/lib/mtr_im.pl
index 4a497cc7ed2..967e92dfcdd 100644
--- a/mysql-test/lib/mtr_im.pl
+++ b/mysql-test/lib/mtr_im.pl
@@ -249,7 +249,7 @@ sub mtr_im_check_main_alive($) {
# Check that IM does not accept client connections.
- if ( mtr_ping_mysqld_server($im->{'port'}) )
+ if ( mtr_ping_port($im->{'port'}) )
{
mtr_debug("IM-main (port: $im->{port}) " .
"is accepting connections.");
@@ -338,7 +338,7 @@ sub mtr_im_check_mysqld_alive($) {
# Check that mysqld does not accept client connections.
- if ( mtr_ping_mysqld_server($mysqld_instance->{'port'}) )
+ if ( mtr_ping_port($mysqld_instance->{'port'}) )
{
mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " .
"is accepting connections.");
@@ -510,7 +510,7 @@ sub mtr_im_wait_for_connection($$$) {
{
mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)...");
- if ( mtr_ping_mysqld_server($im->{'port'}) )
+ if ( mtr_ping_port($im->{'port'}) )
{
mtr_debug("IM is accepting connections " .
"on port $im->{port}.");
@@ -543,7 +543,7 @@ sub mtr_im_wait_for_mysqld($$$) {
mtr_debug("Trying to connect to mysqld " .
"($cur_attempt of $total_attempts)...");
- if ( mtr_ping_mysqld_server($mysqld->{'port'}) )
+ if ( mtr_ping_port($mysqld->{'port'}) )
{
mtr_debug("Mysqld is accepting connections " .
"on port $mysqld->{port}.");
@@ -582,7 +582,7 @@ sub mtr_im_start($$) {
mtr_add_arg($args, $opt);
}
- $im->{'pid'} =
+ $im->{'spawner_pid'} =
mtr_spawn(
$::exe_im, # path to the executable
$args, # cmd-line args
@@ -593,7 +593,7 @@ sub mtr_im_start($$) {
{ append_log_file => 1 } # append log files
);
- unless ( $im->{'pid'} )
+ unless ( $im->{'spawner_pid'} )
{
mtr_error('Could not start Instance Manager.')
}
diff --git a/mysql-test/lib/mtr_io.pl b/mysql-test/lib/mtr_io.pl
index bdf91212b59..5be1d2ffddb 100644
--- a/mysql-test/lib/mtr_io.pl
+++ b/mysql-test/lib/mtr_io.pl
@@ -11,6 +11,8 @@ sub mtr_get_opts_from_file ($);
sub mtr_fromfile ($);
sub mtr_tofile ($@);
sub mtr_tonewfile($@);
+sub mtr_lastlinefromfile($);
+sub mtr_appendfile_to_file ($$);
##############################################################################
#
@@ -35,18 +37,17 @@ sub mtr_get_pid_from_file ($) {
open(FILE, '<', $pid_file_path)
or mtr_error("can't open file \"$pid_file_path\": $!");
+ # Read pid number from file
my $pid= <FILE>;
-
- chomp($pid) if defined $pid;
-
+ chomp $pid;
close FILE;
- return $pid if defined $pid && $pid ne '';
+ return $pid if $pid=~ /^(\d+)/;
- mtr_debug("Pid file '$pid_file_path' is empty. " .
- "Sleeping $timeout second(s)...");
+ mtr_debug("Pid file '$pid_file_path' does not yet contain pid number.\n" .
+ "Sleeping $timeout second(s) more...");
- sleep(1);
+ sleep($timeout);
}
mtr_error("Pid file '$pid_file_path' is corrupted. " .
@@ -139,6 +140,20 @@ sub mtr_fromfile ($) {
return $text;
}
+sub mtr_lastlinefromfile ($) {
+ my $file= shift;
+ my $text;
+
+ open(FILE,"<",$file) or mtr_error("can't open file \"$file\": $!");
+ while (my $line= <FILE>)
+ {
+ $text= $line;
+ }
+ close FILE;
+ return $text;
+}
+
+
sub mtr_tofile ($@) {
my $file= shift;
@@ -155,5 +170,17 @@ sub mtr_tonewfile ($@) {
close FILE;
}
+sub mtr_appendfile_to_file ($$) {
+ my $from_file= shift;
+ my $to_file= shift;
+
+ open(TOFILE,">>",$to_file) or mtr_error("can't open file \"$to_file\": $!");
+ open(FROMFILE,"<",$from_file)
+ or mtr_error("can't open file \"$from_file\": $!");
+ print TOFILE while (<FROMFILE>);
+ close FROMFILE;
+ close TOFILE;
+}
+
1;
diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl
index 0ab09a40b37..846ca25b725 100644
--- a/mysql-test/lib/mtr_misc.pl
+++ b/mysql-test/lib/mtr_misc.pl
@@ -14,6 +14,7 @@ sub mtr_path_exists(@);
sub mtr_script_exists(@);
sub mtr_file_exists(@);
sub mtr_exe_exists(@);
+sub mtr_exe_maybe_exists(@);
sub mtr_copy_dir($$);
sub mtr_same_opts($$);
sub mtr_cmp_opts($$);
@@ -65,6 +66,10 @@ sub mtr_add_arg ($$@) {
##############################################################################
+#
+# NOTE! More specific paths should be given before less specific.
+# For example /client/debug should be listed before /client
+#
sub mtr_path_exists (@) {
foreach my $path ( @_ )
{
@@ -80,6 +85,11 @@ sub mtr_path_exists (@) {
}
}
+
+#
+# NOTE! More specific paths should be given before less specific.
+# For example /client/debug should be listed before /client
+#
sub mtr_script_exists (@) {
foreach my $path ( @_ )
{
@@ -102,6 +112,11 @@ sub mtr_script_exists (@) {
}
}
+
+#
+# NOTE! More specific paths should be given before less specific.
+# For example /client/debug should be listed before /client
+#
sub mtr_file_exists (@) {
foreach my $path ( @_ )
{
@@ -110,8 +125,14 @@ sub mtr_file_exists (@) {
return "";
}
-sub mtr_exe_exists (@) {
+
+#
+# NOTE! More specific paths should be given before less specific.
+# For example /client/debug should be listed before /client
+#
+sub mtr_exe_maybe_exists (@) {
my @path= @_;
+
map {$_.= ".exe"} @path if $::glob_win32;
foreach my $path ( @path )
{
@@ -124,6 +145,21 @@ sub mtr_exe_exists (@) {
return $path if -x $path;
}
}
+ return "";
+}
+
+
+#
+# NOTE! More specific paths should be given before less specific.
+# For example /client/debug should be listed before /client
+#
+sub mtr_exe_exists (@) {
+ my @path= @_;
+ if (my $path= mtr_exe_maybe_exists(@path))
+ {
+ return $path;
+ }
+ # Could not find exe, show error
if ( @path == 1 )
{
mtr_error("Could not find $path[0]");
@@ -139,6 +175,8 @@ sub mtr_copy_dir($$) {
my $from_dir= shift;
my $to_dir= shift;
+ # mtr_verbose("Copying from $from_dir to $to_dir");
+
mkpath("$to_dir");
opendir(DIR, "$from_dir")
or mtr_error("Can't find $from_dir$!");
diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl
index 00b12ba5fb5..8a8b8d0858a 100644
--- a/mysql-test/lib/mtr_process.pl
+++ b/mysql-test/lib/mtr_process.pl
@@ -4,23 +4,25 @@
# and is part of the translation of the Bourne shell script with the
# same name.
-#use Carp qw(cluck);
use Socket;
use Errno;
use strict;
-#use POSIX ":sys_wait_h";
use POSIX 'WNOHANG';
sub mtr_run ($$$$$$;$);
sub mtr_spawn ($$$$$$;$);
-sub mtr_stop_mysqld_servers ($);
+sub mtr_check_stop_servers ($);
sub mtr_kill_leftovers ();
+sub mtr_wait_blocking ($);
sub mtr_record_dead_children ();
+sub mtr_ndbmgm_start($$);
+sub mtr_mysqladmin_start($$$);
sub mtr_exit ($);
sub sleep_until_file_created ($$$);
sub mtr_kill_processes ($);
-sub mtr_ping_mysqld_server ($);
+sub mtr_ping_with_timeout($);
+sub mtr_ping_port ($);
# static in C
sub spawn_impl ($$$$$$$$);
@@ -32,7 +34,6 @@ sub spawn_impl ($$$$$$$$);
##############################################################################
# This function try to mimic the C version used in "netware/mysql_test_run.c"
-# FIXME learn it to handle append mode as well, a "new" flag or a "append"
sub mtr_run ($$$$$$;$) {
my $path= shift;
@@ -113,6 +114,9 @@ sub spawn_impl ($$$$$$$$) {
print STDERR "#### ", "-" x 78, "\n";
}
+ mtr_error("Can't spawn with empty \"path\"") unless defined $path;
+
+
FORK:
{
my $pid= fork();
@@ -145,17 +149,6 @@ sub spawn_impl ($$$$$$$$) {
$SIG{INT}= 'DEFAULT'; # Parent do some stuff, we don't
- if ( $::glob_cygwin_shell and $mode eq 'test' )
- {
- # Programs started from mysqltest under Cygwin, are to
- # execute them within Cygwin. Else simple things in test
- # files like
- # --system "echo 1 > file"
- # will fail.
- # FIXME not working :-(
-# $ENV{'COMSPEC'}= "$::glob_cygwin_shell -c";
- }
-
my $log_file_open_mode = '>';
if ($spawn_opts and $spawn_opts->{'append_log_file'})
@@ -165,7 +158,15 @@ sub spawn_impl ($$$$$$$$) {
if ( $output )
{
- if ( ! open(STDOUT,$log_file_open_mode,$output) )
+ if ( $::glob_win32_perl )
+ {
+ # Don't redirect stdout on ActiveState perl since this is
+ # just another thread in the same process.
+ # Should be fixed so that the thread that is created with fork
+ # executes the exe in another process and wait's for it to return.
+ # In the meanwhile, we get all the output from mysqld's to screen
+ }
+ elsif ( ! open(STDOUT,$log_file_open_mode,$output) )
{
mtr_child_error("can't redirect STDOUT to \"$output\": $!");
}
@@ -217,8 +218,7 @@ sub spawn_parent_impl {
{
# Simple run of command, we wait for it to return
my $ret_pid= waitpid($pid,0);
-
- if ( $ret_pid <= 0 )
+ if ( $ret_pid != $pid )
{
mtr_error("$path ($pid) got lost somehow");
}
@@ -246,7 +246,6 @@ sub spawn_parent_impl {
# Someone terminated, don't know who. Collect
# status info first before $? is lost,
# but not $exit_value, this is flagged from
- #
my $timer_name= mtr_timer_timeout($::glob_timers, $ret_pid);
if ( $timer_name )
@@ -273,45 +272,22 @@ sub spawn_parent_impl {
last;
}
- # If one of the mysqld processes died, we want to
- # mark this, and kill the mysqltest process.
-
- foreach my $idx (0..1)
- {
- if ( $::master->[$idx]->{'pid'} eq $ret_pid )
- {
- mtr_debug("child $ret_pid was master[$idx], " .
- "exit during mysqltest run");
- $::master->[$idx]->{'pid'}= 0;
- last;
- }
- }
+ # One of the child processes died, unless this was expected
+ # mysqltest should be killed and test aborted
- foreach my $idx (0..2)
- {
- if ( $::slave->[$idx]->{'pid'} eq $ret_pid )
- {
- mtr_debug("child $ret_pid was slave[$idx], " .
- "exit during mysqltest run");
- $::slave->[$idx]->{'pid'}= 0;
- last;
- }
- }
-
- mtr_debug("waitpid() catched exit of unknown child $ret_pid, " .
- "exit during mysqltest run");
+ check_expected_crash_and_restart($ret_pid);
}
if ( $ret_pid != $pid )
{
# We terminated the waiting because a "mysqld" process died.
# Kill the mysqltest process.
-
+ mtr_verbose("Kill mysqltest because another process died");
kill(9,$pid);
$ret_pid= waitpid($pid,0);
- if ( $ret_pid == -1 )
+ if ( $ret_pid != $pid )
{
mtr_error("$path ($pid) got lost somehow");
}
@@ -352,71 +328,88 @@ sub mtr_process_exit_status {
#
##############################################################################
-# We just "ping" on the ports, and if we can't do a socket connect
-# we assume the server is dead. So we don't *really* know a server
-# is dead, we just hope that it after letting the listen port go,
-# it is dead enough for us to start a new server.
+# Kill all processes(mysqld, ndbd, ndb_mgmd and im) that would conflict with
+# this run
+# Make sure to remove the PID file, if any.
+# kill IM manager first, else it will restart the servers
sub mtr_kill_leftovers () {
mtr_report("Killing Possible Leftover Processes");
mtr_debug("mtr_kill_leftovers(): started.");
- mkpath("$::opt_vardir/log"); # Needed for mysqladmin log
+ my @kill_pids;
+ my %admin_pids;
- # Stop or kill Instance Manager and all its children. If we failed to do
- # that, we can only abort -- there is nothing left to do.
+ foreach my $srv (@{$::master}, @{$::slave})
+ {
+ mtr_debug(" - mysqld " .
+ "(pid: $srv->{pid}; " .
+ "pid file: '$srv->{path_pid}'; " .
+ "socket: '$srv->{path_sock}'; ".
+ "port: $srv->{port})");
+
+ my $pid= mtr_mysqladmin_start($srv, "shutdown", 70);
+
+ # Save the pid of the mysqladmin process
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $srv->{'pid'},
+ pidfile => $srv->{'path_pid'},
+ sockfile => $srv->{'path_sock'},
+ port => $srv->{'port'},
+ });
+ $srv->{'pid'}= 0; # Assume we are done with it
+ }
- mtr_error("Failed to stop Instance Manager.")
- unless mtr_im_stop($::instance_manager);
+ if ( ! $::opt_skip_ndbcluster )
+ {
+ # Start shutdown of clusters.
+ mtr_debug("Shutting down cluster...");
- # Kill mysqld servers (masters and slaves) that would conflict with this
- # run. Make sure to remove the PID file, if any.
- # Don't touch IM-managed mysqld instances -- they should be stopped by
- # mtr_im_stop().
+ foreach my $cluster (@{$::clusters})
+ {
+ mtr_debug(" - cluster " .
+ "(pid: $cluster->{pid}; " .
+ "pid file: '$cluster->{path_pid})");
- mtr_debug("Collecting mysqld-instances to shutdown...");
+ my $pid= mtr_ndbmgm_start($cluster, "shutdown");
- my @args;
+ # Save the pid of the ndb_mgm process
+ $admin_pids{$pid}= 1;
- for ( my $idx= 0; $idx < 2; $idx++ )
- {
- my $pidfile= $::master->[$idx]->{'path_mypid'};
- my $sockfile= $::master->[$idx]->{'path_mysock'};
- my $port= $::master->[$idx]->{'path_myport'};
+ push(@kill_pids,{
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
+ });
- push(@args,{
- pid => 0, # We don't know the PID
- pidfile => $pidfile,
- sockfile => $sockfile,
- port => $port,
- });
+ $cluster->{'pid'}= 0; # Assume we are done with it
- mtr_debug(" - Master mysqld " .
- "(idx: $idx; pid: '$pidfile'; socket: '$sockfile'; port: $port)");
- $::master->[$idx]->{'pid'}= 0; # Assume we are done with it
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ mtr_debug(" - ndbd " .
+ "(pid: $ndbd->{pid}; " .
+ "pid file: '$ndbd->{path_pid})");
+
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0; # Assume we are done with it
+ }
+ }
}
- for ( my $idx= 0; $idx < 3; $idx++ )
- {
- my $pidfile= $::slave->[$idx]->{'path_mypid'};
- my $sockfile= $::slave->[$idx]->{'path_mysock'};
- my $port= $::slave->[$idx]->{'path_myport'};
-
- push(@args,{
- pid => 0, # We don't know the PID
- pidfile => $pidfile,
- sockfile => $sockfile,
- port => $port,
- });
-
- mtr_debug(" - Slave mysqld " .
- "(idx: $idx; pid: '$pidfile'; socket: '$sockfile'; port: $port)");
+ # Wait for all the admin processes to complete
+ mtr_wait_blocking(\%admin_pids);
- $::slave->[$idx]->{'pid'}= 0; # Assume we are done with it
- }
+ # If we trusted "mysqladmin --shutdown_timeout= ..." we could just
+ # terminate now, but we don't (FIXME should be debugged).
+ # So we try again to ping and at least wait the same amount of time
+ # mysqladmin would for all to die.
- mtr_mysqladmin_shutdown(\@args, 20);
+ mtr_ping_with_timeout(\@kill_pids);
# We now have tried to terminate nice. We have waited for the listen
# port to be free, but can't really tell if the mysqld process died
@@ -445,25 +438,35 @@ sub mtr_kill_leftovers () {
while ( my $elem= readdir(RUNDIR) )
{
- my $pidfile= "$rundir/$elem";
-
- if ( -f $pidfile )
+ # Only read pid from files that end with .pid
+ if ( $elem =~ /.*[.]pid$/)
{
- mtr_debug("Processing PID file: '$pidfile'...");
-
- my $pid= mtr_get_pid_from_file($pidfile);
-
- mtr_debug("Got pid: $pid from file '$pidfile'");
-
- if ( $::glob_cygwin_perl or kill(0, $pid) )
- {
- mtr_debug("There is process with pid $pid -- scheduling for kill.");
- push(@pids, $pid); # We know (cygwin guess) it exists
- }
- else
- {
- mtr_debug("There is no process with pid $pid -- skipping.");
- }
+ my $pidfile= "$rundir/$elem";
+
+ if ( -f $pidfile )
+ {
+ mtr_debug("Processing PID file: '$pidfile'...");
+
+ my $pid= mtr_get_pid_from_file($pidfile);
+
+ mtr_debug("Got pid: $pid from file '$pidfile'");
+
+ if ( $::glob_cygwin_perl or kill(0, $pid) )
+ {
+ mtr_debug("There is process with pid $pid -- scheduling for kill.");
+ push(@pids, $pid); # We know (cygwin guess) it exists
+ }
+ else
+ {
+ mtr_debug("There is no process with pid $pid -- skipping.");
+ }
+ }
+ }
+ else
+ {
+ mtr_warning("Found non pid file $elem in $rundir")
+ if -f "$rundir/$elem";
+ next;
}
}
closedir(RUNDIR);
@@ -490,7 +493,7 @@ sub mtr_kill_leftovers () {
{
mtr_debug("Sending SIGKILL to pids: " . join(' ', @pids));
kill(9, @pids);
- mtr_debug("Sleep 1 second waiting for processes to die");
+ mtr_report("Sleep 1 second waiting for processes to die");
sleep(1) # Wait one second
} while ( $retries-- and kill(0, @pids) );
@@ -508,57 +511,65 @@ sub mtr_kill_leftovers () {
mtr_debug("Directory for PID files ($rundir) does not exist.");
}
- # We may have failed everything, bug we now check again if we have
+ # We may have failed everything, but we now check again if we have
# the listen ports free to use, and if they are free, just go for it.
mtr_debug("Checking known mysqld servers...");
- foreach my $srv ( @args )
+ foreach my $srv ( @kill_pids )
{
- if ( mtr_ping_mysqld_server($srv->{'port'}) )
+ if ( defined $srv->{'port'} and mtr_ping_port($srv->{'port'}) )
{
- mtr_warning("can't kill old mysqld holding port $srv->{'port'}");
+ mtr_warning("can't kill old process holding port $srv->{'port'}");
}
}
mtr_debug("mtr_kill_leftovers(): finished.");
}
-##############################################################################
-#
-# Shut down mysqld servers we have started from this run of this script
-#
-##############################################################################
-
-# To speed things we kill servers in parallel. The argument is a list
-# of 'ports', 'pids', 'pidfiles' and 'socketfiles'.
+# Check that all processes in list are killed
+# The argument is a list of 'ports', 'pids', 'pidfiles' and 'socketfiles'
+# for which shutdown has been started. Make sure they all get killed
+# in one way or the other.
+#
# FIXME On Cygwin, and maybe some other platforms, $srv->{'pid'} and
-# $srv->{'pidfile'} will not be the same PID. We need to try to kill
+# the pid in $srv->{'pidfile'} will not be the same PID. We need to try to kill
# both I think.
-sub mtr_stop_mysqld_servers ($) {
+sub mtr_check_stop_servers ($) {
my $spec= shift;
- # ----------------------------------------------------------------------
- # First try nice normal shutdown using 'mysqladmin'
- # ----------------------------------------------------------------------
+ # Return if no processes are defined
+ return if ! @$spec;
- # Shutdown time must be high as slave may be in reconnect
- mtr_mysqladmin_shutdown($spec, 70);
+ #mtr_report("mtr_check_stop_servers");
+
+ mtr_ping_with_timeout(\@$spec);
# ----------------------------------------------------------------------
# We loop with waitpid() nonblocking to see how many of the ones we
- # are to kill, actually got killed by mtr_mysqladmin_shutdown().
- # Note that we don't rely on this, the mysqld server might have stop
+ # are to kill, actually got killed by mysqladmin or ndb_mgm
+ #
+ # Note that we don't rely on this, the mysqld server might have stopped
# listening to the port, but still be alive. But it is a start.
# ----------------------------------------------------------------------
foreach my $srv ( @$spec )
{
- if ( $srv->{'pid'} and (waitpid($srv->{'pid'},&WNOHANG) == $srv->{'pid'}) )
+ my $ret_pid;
+ if ( $srv->{'pid'} )
{
- $srv->{'pid'}= 0;
+ $ret_pid= waitpid($srv->{'pid'},&WNOHANG);
+ if ($ret_pid == $srv->{'pid'})
+ {
+ mtr_verbose("Caught exit of process $ret_pid");
+ $srv->{'pid'}= 0;
+ }
+ else
+ {
+ # mtr_warning("caught exit of unknown child $ret_pid");
+ }
}
}
@@ -592,13 +603,12 @@ sub mtr_stop_mysqld_servers ($) {
}
# ----------------------------------------------------------------------
- # If the processes where started from this script, and we had no PIDS
+ # If all the processes in list already have been killed,
# then we don't have to do anything.
# ----------------------------------------------------------------------
if ( ! keys %mysqld_pids )
{
- # cluck "This is how we got here!";
return;
}
@@ -647,123 +657,127 @@ sub mtr_stop_mysqld_servers ($) {
foreach my $file ($srv->{'pidfile'}, $srv->{'sockfile'})
{
# Know it is dead so should be no race, careful anyway
- if ( -f $file and ! unlink($file) and -f $file )
+ if ( defined $file and -f $file and ! unlink($file) and -f $file )
{
$errors++;
mtr_warning("couldn't delete $file");
}
}
+ $srv->{'pid'}= 0;
}
}
}
if ( $errors )
{
- # We are in trouble, just die....
- mtr_error("we could not kill or clean up all processes");
+ # There where errors killing processes
+ # do one last attempt to ping the servers
+ # and if they can't be pinged, assume they are dead
+ if ( ! mtr_ping_with_timeout( \@$spec ) )
+ {
+ mtr_error("we could not kill or clean up all processes");
+ }
+ else
+ {
+ mtr_verbose("All ports were free, continuing");
+ }
}
}
# FIXME We just assume they are all dead, for Cygwin we are not
# really sure
-
+
}
+# Wait for all the process in the list to terminate
+sub mtr_wait_blocking($) {
+ my $admin_pids= shift;
-##############################################################################
-#
-# Shut down mysqld servers using "mysqladmin ... shutdown".
-# To speed this up, we start them in parallel and use waitpid() to
-# catch their termination. Note that this doesn't say the servers
-# are terminated, just that 'mysqladmin' is terminated.
-#
-# Note that mysqladmin will ask the server about what PID file it uses,
-# and mysqladmin will wait for it to be removed before it terminates
-# (unless passes timeout).
-#
-# This function will take at most about 20 seconds, and we still are not
-# sure we killed them all. If none is responding to ping, we return 1,
-# else we return 0.
-#
-##############################################################################
-
-sub mtr_mysqladmin_shutdown {
- my $spec= shift;
- my $adm_shutdown_tmo= shift;
- my %mysql_admin_pids;
- my @to_kill_specs;
+ # Return if no processes defined
+ return if ! %$admin_pids;
- mtr_debug("mtr_mysqladmin_shutdown(): starting...");
- mtr_debug("Collecting mysqld-instances to shutdown...");
+ mtr_verbose("mtr_wait_blocking");
- foreach my $srv ( @$spec )
+ # Wait for all the started processes to exit
+ # As mysqladmin is such a simple program, we trust it to terminate itself.
+ # I.e. we wait blocking, and wait for them all before we go on.
+ foreach my $pid (keys %{$admin_pids})
{
- if ( mtr_ping_mysqld_server($srv->{'port'}) )
- {
- mtr_debug("Mysqld (port: $srv->{port}) needs to be stopped.");
+ my $ret_pid= waitpid($pid,0);
- push(@to_kill_specs, $srv);
- }
}
+}
+
+# Start "mysqladmin shutdown" for a specific mysqld
+sub mtr_mysqladmin_start($$$) {
+ my $srv= shift;
+ my $command= shift;
+ my $adm_shutdown_tmo= shift;
+ my $args;
+ mtr_init_args(\$args);
- foreach my $srv ( @to_kill_specs )
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--user=%s", $::opt_user);
+ mtr_add_arg($args, "--password=");
+ mtr_add_arg($args, "--silent");
+ if ( -e $srv->{'path_sock'} )
{
- # Shutdown time must be high as slave may be in reconnect
- my $args;
+ mtr_add_arg($args, "--socket=%s", $srv->{'path_sock'});
+ }
+ if ( $srv->{'port'} )
+ {
+ mtr_add_arg($args, "--port=%s", $srv->{'port'});
+ }
+ if ( $srv->{'port'} and ! -e $srv->{'path_sock'} )
+ {
+ mtr_add_arg($args, "--protocol=tcp"); # Needed if no --socket
+ }
+ mtr_add_arg($args, "--connect_timeout=5");
- mtr_init_args(\$args);
+ # Shutdown time must be high as slave may be in reconnect
+ mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo");
+ mtr_add_arg($args, "$command");
+ my $path_mysqladmin_log= "$::opt_vardir/log/mysqladmin.log";
+ my $pid= mtr_spawn($::exe_mysqladmin, $args,
+ "", $path_mysqladmin_log, $path_mysqladmin_log, "",
+ { append_log_file => 1 });
+ mtr_verbose("mtr_mysqladmin_start, pid: $pid");
+ return $pid;
- mtr_add_arg($args, "--no-defaults");
- mtr_add_arg($args, "--user=%s", $::opt_user);
- mtr_add_arg($args, "--password=");
- if ( -e $srv->{'sockfile'} )
- {
- mtr_add_arg($args, "--socket=%s", $srv->{'sockfile'});
- }
- if ( $srv->{'port'} )
- {
- mtr_add_arg($args, "--port=%s", $srv->{'port'});
- }
- if ( $srv->{'port'} and ! -e $srv->{'sockfile'} )
- {
- mtr_add_arg($args, "--protocol=tcp"); # Needed if no --socket
- }
- mtr_add_arg($args, "--connect_timeout=5");
- mtr_add_arg($args, "--shutdown_timeout=$adm_shutdown_tmo");
- mtr_add_arg($args, "shutdown");
+}
- mtr_debug("Shutting down mysqld " .
- "(port: $srv->{port}; socket: '$srv->{sockfile}')...");
+# Start "ndb_mgm shutdown" for a specific cluster, it will
+# shutdown all data nodes and leave the ndb_mgmd running
+sub mtr_ndbmgm_start($$) {
+ my $cluster= shift;
+ my $command= shift;
- my $path_mysqladmin_log= "$::opt_vardir/log/mysqladmin.log";
- my $pid= mtr_spawn($::exe_mysqladmin, $args,
- "", $path_mysqladmin_log, $path_mysqladmin_log, "",
- { append_log_file => 1 });
- $mysql_admin_pids{$pid}= 1;
+ my $args;
- # We don't wait for termination of mysqladmin
- }
+ mtr_init_args(\$args);
- # As mysqladmin is such a simple program, we trust it to terminate.
- # I.e. we wait blocking, and wait wait for them all before we go on.
- while (keys %mysql_admin_pids)
- {
- foreach my $pid (keys %mysql_admin_pids)
- {
- if ( waitpid($pid,0) > 0 )
- {
- delete $mysql_admin_pids{$pid};
- }
- }
- }
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--core");
+ mtr_add_arg($args, "--try-reconnect=1");
+ mtr_add_arg($args, "--ndb_connectstring=%s", $cluster->{'connect_string'});
+ mtr_add_arg($args, "-e");
+ mtr_add_arg($args, "$command");
- # If we trusted "mysqladmin --shutdown_timeout= ..." we could just
- # terminate now, but we don't (FIXME should be debugged).
- # So we try again to ping and at least wait the same amount of time
- # mysqladmin would for all to die.
+ my $pid= mtr_spawn($::exe_ndb_mgm, $args,
+ "", "/dev/null", "/dev/null", "",
+ {});
+ mtr_verbose("mtr_ndbmgm_start, pid: $pid");
+ return $pid;
+
+}
- my $timeout= 20; # 20 seconds max
+
+# Ping all servers in list, exit when none of them answers
+# or when timeout has passed
+sub mtr_ping_with_timeout($) {
+ my $spec= shift;
+ my $timeout= 200; # 20 seconds max
my $res= 1; # If we just fall through, we are done
# in the sense that the servers don't
# listen to their ports any longer
@@ -773,16 +787,25 @@ sub mtr_mysqladmin_shutdown {
TIME:
while ( $timeout-- )
{
- foreach my $srv ( @to_kill_specs )
+ foreach my $srv ( @$spec )
{
$res= 1; # We are optimistic
- if ( mtr_ping_mysqld_server($srv->{'port'}) )
+ if ( $srv->{'pid'} and defined $srv->{'port'} )
{
- mtr_debug("Mysqld (port: $srv->{port}) is still alive.");
- mtr_debug("Sleep 1 second waiting for processes to stop using port");
- sleep(1); # One second
- $res= 0;
- next TIME;
+ if ( mtr_ping_port($srv->{'port'}) )
+ {
+ mtr_verbose("waiting for process $srv->{'pid'} to stop ".
+ "using port $srv->{'port'}");
+
+ # Millisceond sleep emulated with select
+ select(undef, undef, undef, (0.1));
+ $res= 0;
+ next TIME;
+ }
+ else
+ {
+ # Process was not using port
+ }
}
}
last; # If we got here, we are done
@@ -790,52 +813,162 @@ sub mtr_mysqladmin_shutdown {
if ($res)
{
- mtr_debug("mtr_mysqladmin_shutdown(): All mysqld instances are down.");
+ mtr_debug("mtr_ping_with_timeout(): All mysqld instances are down.");
}
else
{
- mtr_debug("mtr_mysqladmin_shutdown(): At least one server is alive.");
+ mtr_report("mtr_ping_with_timeout(): At least one server is alive.");
}
return $res;
}
-##############################################################################
+
#
-# The operating system will keep information about dead children,
-# we read this information here, and if we have records the process
-# is alive, we mark it as dead.
+# Loop through our list of processes and look for and entry
+# with the provided pid
+# Set the pid of that process to 0 if found
#
-##############################################################################
+sub mark_process_dead($)
+{
+ my $ret_pid= shift;
-sub mtr_record_dead_children () {
+ foreach my $mysqld (@{$::master}, @{$::slave})
+ {
+ if ( $mysqld->{'pid'} eq $ret_pid )
+ {
+ mtr_verbose("$mysqld->{'type'} $mysqld->{'idx'} exited, pid: $ret_pid");
+ $mysqld->{'pid'}= 0;
+ return;
+ }
+ }
- my $ret_pid;
+ foreach my $cluster (@{$::clusters})
+ {
+ if ( $cluster->{'pid'} eq $ret_pid )
+ {
+ mtr_verbose("$cluster->{'name'} cluster ndb_mgmd exited, pid: $ret_pid");
+ $cluster->{'pid'}= 0;
+ return;
+ }
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ if ( $ndbd->{'pid'} eq $ret_pid )
+ {
+ mtr_verbose("$cluster->{'name'} cluster ndbd exited, pid: $ret_pid");
+ $ndbd->{'pid'}= 0;
+ return;
+ }
+ }
+ }
+ mtr_warning("mark_process_dead couldn't find an entry for pid: $ret_pid");
- # FIXME the man page says to wait for -1 to terminate,
- # but on OS X we get '0' all the time...
- while ( ($ret_pid= waitpid(-1,&WNOHANG)) > 0 )
+}
+
+#
+# Loop through our list of processes and look for and entry
+# with the provided pid, if found check for the file indicating
+# expected crash and restart it.
+#
+sub check_expected_crash_and_restart($)
+{
+ my $ret_pid= shift;
+
+ foreach my $mysqld (@{$::master}, @{$::slave})
+ {
+ if ( $mysqld->{'pid'} eq $ret_pid )
+ {
+ mtr_verbose("$mysqld->{'type'} $mysqld->{'idx'} exited, pid: $ret_pid");
+ $mysqld->{'pid'}= 0;
+
+ # Check if crash expected and restart if it was
+ my $expect_file= "$::opt_vardir/tmp/" . "$mysqld->{'type'}" .
+ "$mysqld->{'idx'}" . ".expect";
+ if ( -f $expect_file )
+ {
+ mtr_verbose("Crash was expected, file $expect_file exists");
+ mysqld_start($mysqld, $mysqld->{'start_opts'},
+ $mysqld->{'start_slave_master_info'});
+ unlink($expect_file);
+ }
+
+ return;
+ }
+ }
+
+ foreach my $cluster (@{$::clusters})
{
- mtr_debug("waitpid() catched exit of child $ret_pid");
- foreach my $idx (0..1)
+ if ( $cluster->{'pid'} eq $ret_pid )
{
- if ( $::master->[$idx]->{'pid'} eq $ret_pid )
+ mtr_verbose("$cluster->{'name'} cluster ndb_mgmd exited, pid: $ret_pid");
+ $cluster->{'pid'}= 0;
+
+ # Check if crash expected and restart if it was
+ my $expect_file= "$::opt_vardir/tmp/ndb_mgmd_" . "$cluster->{'type'}" .
+ ".expect";
+ if ( -f $expect_file )
{
- mtr_debug("child $ret_pid was master[$idx]");
- $::master->[$idx]->{'pid'}= 0;
+ mtr_verbose("Crash was expected, file $expect_file exists");
+ ndbmgmd_start($cluster);
+ unlink($expect_file);
}
+ return;
}
- foreach my $idx (0..2)
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
{
- if ( $::slave->[$idx]->{'pid'} eq $ret_pid )
+ if ( $ndbd->{'pid'} eq $ret_pid )
{
- mtr_debug("child $ret_pid was slave[$idx]");
- $::slave->[$idx]->{'pid'}= 0;
- last;
+ mtr_verbose("$cluster->{'name'} cluster ndbd exited, pid: $ret_pid");
+ $ndbd->{'pid'}= 0;
+
+ # Check if crash expected and restart if it was
+ my $expect_file= "$::opt_vardir/tmp/ndbd_" . "$cluster->{'type'}" .
+ "$ndbd->{'idx'}" . ".expect";
+ if ( -f $expect_file )
+ {
+ mtr_verbose("Crash was expected, file $expect_file exists");
+ ndbd_start($cluster, $ndbd->{'idx'},
+ $ndbd->{'start_extra_args'});
+ unlink($expect_file);
+ }
+ return;
}
}
}
+
+ if ($::instance_manager->{'spawner_pid'} eq $ret_pid)
+ {
+ return;
+ }
+
+ mtr_warning("check_expected_crash_and_restart couldn't find an entry for pid: $ret_pid");
+
+}
+
+##############################################################################
+#
+# The operating system will keep information about dead children,
+# we read this information here, and if we have records the process
+# is alive, we mark it as dead.
+#
+##############################################################################
+
+sub mtr_record_dead_children () {
+
+ my $process_died= 0;
+ my $ret_pid;
+
+ # Wait without blockinng to see if any processes had died
+ # -1 or 0 means there are no more procesess to wait for
+ while ( ($ret_pid= waitpid(-1,&WNOHANG)) != 0 and $ret_pid != -1)
+ {
+ mtr_warning("mtr_record_dead_children: $ret_pid");
+ mark_process_dead($ret_pid);
+ $process_died= 1;
+ }
+ return $process_died;
}
sub start_reap_all {
@@ -847,16 +980,24 @@ sub start_reap_all {
# here. If a process terminated before setting $SIG{CHLD} (but after
# any attempt to waitpid() it), it will still be a zombie. So we
# have to handle any such process here.
- while(waitpid(-1, &WNOHANG) > 0) { };
+ my $pid;
+ while(($pid= waitpid(-1, &WNOHANG)) != 0 and $pid != -1)
+ {
+ mtr_warning("start_reap_all pid: $pid");
+ mark_process_dead($pid);
+ };
}
sub stop_reap_all {
$SIG{CHLD}= 'DEFAULT';
}
-sub mtr_ping_mysqld_server ($) {
+
+sub mtr_ping_port ($) {
my $port= shift;
+ mtr_verbose("mtr_ping_port: $port");
+
my $remote= "localhost";
my $iaddr= inet_aton($remote);
if ( ! $iaddr )
@@ -874,13 +1015,13 @@ sub mtr_ping_mysqld_server ($) {
if ( connect(SOCK, $paddr) )
{
- mtr_debug("Server (port: $port) is alive.");
close(SOCK); # FIXME check error?
+ mtr_verbose("USED");
return 1;
}
else
{
- mtr_debug("Server (port: $port) is dead.");
+ mtr_verbose("FREE");
return 0;
}
}
@@ -910,15 +1051,15 @@ sub sleep_until_file_created ($$$) {
# Check if it died after the fork() was successful
if ( $pid != 0 && waitpid($pid,&WNOHANG) == $pid )
{
+ mtr_warning("Process $pid died");
return 0;
}
- mtr_debug("Sleep $sleeptime milliseconds waiting for ".
- "creation of $pidfile");
+ mtr_debug("Sleep $sleeptime milliseconds waiting for $pidfile");
# Print extra message every 60 seconds
my $seconds= ($loop * $sleeptime) / 1000;
- if ( $seconds > 1 and $seconds % 60 == 0 )
+ if ( $seconds > 1 and int($seconds * 10) % 600 == 0 )
{
my $left= $timeout - $seconds;
mtr_warning("Waited $seconds seconds for $pidfile to be created, " .
@@ -936,20 +1077,18 @@ sub sleep_until_file_created ($$$) {
sub mtr_kill_processes ($) {
my $pids = shift;
- foreach my $sig (15, 9)
+ mtr_verbose("mtr_kill_processes " . join(" ", @$pids));
+
+ foreach my $pid (@$pids)
{
- my $retries= 10;
- while (1)
+ foreach my $sig (15, 9)
{
- kill($sig, @{$pids});
- last unless kill (0, @{$pids}) and $retries--;
-
- mtr_debug("Sleep 2 second waiting for processes to die");
- sleep(2);
+ last if mtr_im_kill_process([ $pid ], $sig, 10, 1);
}
}
}
+
##############################################################################
#
# When we exit, we kill off all children
@@ -959,12 +1098,11 @@ sub mtr_kill_processes ($) {
# FIXME something is wrong, we sometimes terminate with "Hangup" written
# to tty, and no STDERR output telling us why.
-# FIXME for some readon, setting HUP to 'IGNORE' will cause exit() to
+# FIXME for some reason, setting HUP to 'IGNORE' will cause exit() to
# write out "Hangup", and maybe loose some output. We insert a sleep...
sub mtr_exit ($) {
my $code= shift;
-# cluck("Called mtr_exit()");
mtr_timer_stop_all($::glob_timers);
local $SIG{HUP} = 'IGNORE';
# ToDo: Signalling -$$ will only work if we are the process group
@@ -974,8 +1112,8 @@ sub mtr_exit ($) {
# set ourselves as the group leader at startup (with
# POSIX::setpgrp(0,0)), but then care must be needed to always do
# proper child process cleanup.
- kill('HUP', -$$) if $$ == getpgrp();
- sleep 2;
+ kill('HUP', -$$) if !$::glob_win32_perl and $$ == getpgrp();
+
exit($code);
}
diff --git a/mysql-test/lib/mtr_report.pl b/mysql-test/lib/mtr_report.pl
index 69d19709d16..d0e836c1a90 100644
--- a/mysql-test/lib/mtr_report.pl
+++ b/mysql-test/lib/mtr_report.pl
@@ -10,6 +10,7 @@ sub mtr_report_test_name($);
sub mtr_report_test_passed($);
sub mtr_report_test_failed($);
sub mtr_report_test_skipped($);
+sub mtr_report_test_not_skipped_though_disabled($);
sub mtr_show_failed_diff ($);
sub mtr_report_stats ($);
@@ -21,6 +22,7 @@ sub mtr_warning (@);
sub mtr_error (@);
sub mtr_child_error (@);
sub mtr_debug (@);
+sub mtr_verbose (@);
##############################################################################
@@ -51,13 +53,6 @@ sub mtr_show_failed_diff ($) {
{
$result_file= $eval_file;
}
- elsif ( $::opt_result_ext and
- ( $::opt_record or -f "$result_file$::opt_result_ext" ))
- {
- # If we have an special externsion for result files we use it if we are
- # recording or a result file with that extension exists.
- $result_file= "$result_file$::opt_result_ext";
- }
my $diffopts= $::opt_udiff ? "-u" : "-c";
@@ -94,12 +89,33 @@ sub mtr_report_test_skipped ($) {
{
print "[ disabled ] $tinfo->{'comment'}\n";
}
+ elsif ( $tinfo->{'comment'} )
+ {
+ print "[ skipped ] $tinfo->{'comment'}\n";
+ }
else
{
print "[ skipped ]\n";
}
}
+sub mtr_report_tests_not_skipped_though_disabled ($) {
+ my $tests= shift;
+
+ if ( $::opt_enable_disabled )
+ {
+ my @disabled_tests= grep {$_->{'dont_skip_though_disabled'}} @$tests;
+ if ( @disabled_tests )
+ {
+ print "\nTest(s) which will be run though they are marked as disabled:\n";
+ foreach my $tinfo ( sort {$a->{'name'} cmp $b->{'name'}} @disabled_tests )
+ {
+ printf " %-20s : %s\n", $tinfo->{'name'}, $tinfo->{'comment'};
+ }
+ }
+ }
+}
+
sub mtr_report_test_passed ($) {
my $tinfo= shift;
@@ -107,7 +123,7 @@ sub mtr_report_test_passed ($) {
if ( $::opt_timer and -f "$::opt_vardir/log/timer" )
{
$timer= mtr_fromfile("$::opt_vardir/log/timer");
- $::glob_tot_real_time += $timer;
+ $::glob_tot_real_time += ($timer/1000);
$timer= sprintf "%12s", $timer;
}
$tinfo->{'result'}= 'MTR_RES_PASSED';
@@ -118,13 +134,9 @@ sub mtr_report_test_failed ($) {
my $tinfo= shift;
$tinfo->{'result'}= 'MTR_RES_FAILED';
- if ( $tinfo->{'timeout'} )
+ if ( defined $tinfo->{'timeout'} )
{
print "[ fail ] timeout\n";
- }
- elsif ( $tinfo->{'ndb_test'} and !$::flag_ndb_status_ok)
- {
- print "[ fail ] ndbcluster start failure\n";
return;
}
else
@@ -132,9 +144,11 @@ sub mtr_report_test_failed ($) {
print "[ fail ]\n";
}
- # FIXME Instead of this test, and meaningless error message in 'else'
- # we should write out into $::path_timefile when the error occurs.
- if ( -f $::path_timefile )
+ if ( $tinfo->{'comment'} )
+ {
+ print "\nERROR: $tinfo->{'comment'}\n";
+ }
+ elsif ( -f $::path_timefile )
{
print "\nErrors are (from $::path_timefile) :\n";
print mtr_fromfile($::path_timefile); # FIXME print_file() instead
@@ -157,7 +171,8 @@ sub mtr_report_stats ($) {
my $tot_passed= 0;
my $tot_failed= 0;
my $tot_tests= 0;
- my $found_problems= 0; # Some warnings are errors...
+ my $tot_restarts= 0;
+ my $found_problems= 0; # Some warnings in the logfiles are errors...
foreach my $tinfo (@$tests)
{
@@ -175,6 +190,10 @@ sub mtr_report_stats ($) {
$tot_tests++;
$tot_failed++;
}
+ if ( $tinfo->{'restarted'} )
+ {
+ $tot_restarts++;
+ }
}
# ----------------------------------------------------------------------
@@ -188,8 +207,9 @@ sub mtr_report_stats ($) {
else
{
my $ratio= $tot_passed * 100 / $tot_tests;
- printf "Failed $tot_failed/$tot_tests tests, " .
- "%.2f\% were successful.\n\n", $ratio;
+ print "Failed $tot_failed/$tot_tests tests, ";
+ printf("%.2f", $ratio);
+ print "\% were successful.\n\n";
print
"The log files in var/log may give you some hint\n",
"of what went wrong.\n",
@@ -197,6 +217,14 @@ sub mtr_report_stats ($) {
"the documentation at\n",
"http://www.mysql.com/doc/en/MySQL_test_suite.html\n";
}
+ print
+ "The servers were restarted $tot_restarts times\n";
+
+ if ( $::opt_timer )
+ {
+ print
+ "Spent $::glob_tot_real_time seconds actually executing testcases\n"
+ }
# ----------------------------------------------------------------------
# If a debug run, there might be interesting information inside
@@ -216,7 +244,10 @@ sub mtr_report_stats ($) {
else
{
# We report different types of problems in order
- foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x" )
+ foreach my $pattern ( "^Warning:", "^Error:", "^==.* at 0x",
+ "InnoDB: Warning", "missing DBUG_RETURN",
+ "mysqld: Warning",
+ "Attempting backtrace", "Assertion .* failed" )
{
foreach my $errlog ( sort glob("$::opt_vardir/log/*.err") )
{
@@ -230,7 +261,8 @@ sub mtr_report_stats ($) {
# Skip some non fatal warnings from the log files
if ( /Warning:\s+Table:.* on (delete|rename)/ or
/Warning:\s+Setting lower_case_table_names=2/ or
- /Warning:\s+One can only use the --user.*root/ )
+ /Warning:\s+One can only use the --user.*root/ or
+ /InnoDB: Warning: we did not need to do crash recovery/)
{
next; # Skip these lines
}
@@ -241,17 +273,18 @@ sub mtr_report_stats ($) {
}
}
}
- if ( $found_problems )
- {
- mtr_warning("Got errors/warnings while running tests, please examine",
- "\"$warnlog\" for details.");
- }
+ }
+ if ( $found_problems )
+ {
+ mtr_warning("Got errors/warnings while running tests, please examine",
+ "\"$warnlog\" for details.");
}
}
}
print "\n";
+ # Print a list of testcases that failed
if ( $tot_failed != 0 )
{
my $test_mode= join(" ", @::glob_test_mode) || "default";
@@ -265,7 +298,30 @@ sub mtr_report_stats ($) {
}
}
print "\n";
+
}
+
+ # Print a list of check_testcases that failed(if any)
+ if ( $::opt_check_testcases )
+ {
+ my @check_testcases= ();
+
+ foreach my $tinfo (@$tests)
+ {
+ if ( defined $tinfo->{'check_testcase_failed'} )
+ {
+ push(@check_testcases, $tinfo->{'name'});
+ }
+ }
+
+ if ( @check_testcases )
+ {
+ print "Check of testcase failed for: ";
+ print join(" ", @check_testcases);
+ print "\n\n";
+ }
+ }
+
if ( $tot_failed != 0 || $found_problems)
{
mtr_error("there where failing test cases");
@@ -331,5 +387,11 @@ sub mtr_debug (@) {
print STDERR "####: ",join(" ", @_),"\n";
}
}
+sub mtr_verbose (@) {
+ if ( $::opt_verbose )
+ {
+ print STDERR "> ",join(" ", @_),"\n";
+ }
+}
1;
diff --git a/mysql-test/lib/mtr_stress.pl b/mysql-test/lib/mtr_stress.pl
index 92bb220461b..1371eaa44c6 100644
--- a/mysql-test/lib/mtr_stress.pl
+++ b/mysql-test/lib/mtr_stress.pl
@@ -25,10 +25,9 @@ sub run_stress_test ()
mtr_report("Starting stress testing\n");
- if ( ! $::glob_use_embedded_server and ! $::opt_local_master )
+ if ( ! $::glob_use_embedded_server )
{
- $::master->[0]->{'pid'}= mysqld_start('master',0,[],[],0);
- if ( ! $::master->[0]->{'pid'} )
+ if ( ! mysqld_start($::master->[0],[],[]) )
{
mtr_error("Can't start the mysqld server");
}
@@ -123,7 +122,7 @@ sub run_stress_test ()
mtr_init_args(\$args);
- mtr_add_arg($args, "--server-socket=%s", $::master->[0]->{'path_mysock'});
+ mtr_add_arg($args, "--server-socket=%s", $::master->[0]->{'path_sock'});
mtr_add_arg($args, "--server-user=%s", $::opt_user);
mtr_add_arg($args, "--server-database=%s", "test");
mtr_add_arg($args, "--stress-suite-basedir=%s", $::glob_mysql_test_dir);
@@ -141,7 +140,7 @@ sub run_stress_test ()
if ( $::opt_stress_init_file )
{
- mtr_add_arg($args, "--stress-init-file=%", $::opt_stress_init_file);
+ mtr_add_arg($args, "--stress-init-file=%s", $::opt_stress_init_file);
}
if ( !$::opt_stress_loop_count && !$::opt_stress_test_count &&
@@ -169,10 +168,9 @@ sub run_stress_test ()
#Run stress test
mtr_run("$::glob_mysql_test_dir/mysql-stress-test.pl", $args, "", "", "", "");
-
if ( ! $::glob_use_embedded_server )
{
- stop_masters();
+ stop_all_servers();
}
}
diff --git a/mysql-test/lib/mtr_timer.pl b/mysql-test/lib/mtr_timer.pl
index a85ab8c6122..06374716c62 100644
--- a/mysql-test/lib/mtr_timer.pl
+++ b/mysql-test/lib/mtr_timer.pl
@@ -4,23 +4,19 @@
# and is part of the translation of the Bourne shell script with the
# same name.
-use Carp qw(cluck);
use Socket;
use Errno;
use strict;
-#use POSIX ":sys_wait_h";
-use POSIX 'WNOHANG';
-
sub mtr_init_timers ();
sub mtr_timer_start($$$);
sub mtr_timer_stop($$);
sub mtr_timer_stop_all($);
-sub mtr_timer_waitpid($$$);
+
##############################################################################
#
-# Initiate a structure shared by all timers
+# Initiate the structure shared by all timers
#
##############################################################################
@@ -35,17 +31,19 @@ sub mtr_init_timers () {
# Start, stop and poll a timer
#
# As alarm() isn't portable to Windows, we use separate processes to
-# implement timers. That is why there is a mtr_timer_waitpid(), as this
-# is where we catch a timeout.
+# implement timers.
#
##############################################################################
sub mtr_timer_start($$$) {
my ($timers,$name,$duration)= @_;
+ mtr_verbose("mtr_timer_start: $name, $duration");
+
if ( exists $timers->{'timers'}->{$name} )
{
# We have an old running timer, kill it
+ mtr_verbose("There is an old timer running");
mtr_timer_stop($timers,$name);
}
@@ -57,7 +55,7 @@ sub mtr_timer_start($$$) {
{
if ( $! == $!{EAGAIN} ) # See "perldoc Errno"
{
- mtr_debug("Got EAGAIN from fork(), sleep 1 second and redo");
+ mtr_warning("Got EAGAIN from fork(), sleep 1 second and redo");
sleep(1);
redo FORK;
}
@@ -70,6 +68,7 @@ sub mtr_timer_start($$$) {
if ( $tpid )
{
# Parent, record the information
+ mtr_verbose("timer parent, record info($name, $tpid, $duration)");
$timers->{'timers'}->{$name}->{'pid'}= $tpid;
$timers->{'timers'}->{$name}->{'duration'}= $duration;
$timers->{'pids'}->{$tpid}= $name;
@@ -85,6 +84,7 @@ sub mtr_timer_start($$$) {
$SIG{INT}= 'DEFAULT';
$0= "mtr_timer(timers,$name,$duration)";
+ mtr_verbose("timer child $name, sleep $duration");
sleep($duration);
exit(0);
}
@@ -95,9 +95,12 @@ sub mtr_timer_start($$$) {
sub mtr_timer_stop ($$) {
my ($timers,$name)= @_;
+ mtr_verbose("mtr_timer_stop: $name");
+
if ( exists $timers->{'timers'}->{$name} )
{
my $tpid= $timers->{'timers'}->{$name}->{'pid'};
+ mtr_verbose("Stopping timer with pid $tpid");
# FIXME as Cygwin reuses pids fast, maybe check that is
# the expected process somehow?!
@@ -114,7 +117,7 @@ sub mtr_timer_stop ($$) {
}
else
{
- mtr_debug("Asked to stop timer \"$name\" not started");
+ mtr_error("Asked to stop timer \"$name\" not started");
return 0;
}
}
@@ -136,10 +139,8 @@ sub mtr_timer_timeout ($$) {
return "" unless exists $timers->{'pids'}->{$pid};
- # We got a timeout
- my $name= $timers->{'pids'}->{$pid};
- mtr_timer_stop($timers, $timers->{'timers'}->{$name});
- return $name;
+ # We got a timeout, return the name ot the timer
+ return $timers->{'pids'}->{$pid};
}
1;
diff --git a/mysql-test/lib/mtr_unique.pl b/mysql-test/lib/mtr_unique.pl
new file mode 100644
index 00000000000..a8fb320c773
--- /dev/null
+++ b/mysql-test/lib/mtr_unique.pl
@@ -0,0 +1,156 @@
+#
+# This file is used from mysql-test-run.pl when choosing
+# port numbers and directories to use for running mysqld.
+#
+
+use strict;
+use Fcntl ':flock';
+
+#
+# Requested IDs are stored in a hash and released upon END.
+#
+my %mtr_unique_assigned_ids = ();
+END {
+ while(my ($id,$file) = each(%mtr_unique_assigned_ids)) {
+ print "Autoreleasing $file:$id\n";
+ mtr_release_unique_id($file, $id);
+ }
+}
+
+#
+# Require a unique, numerical ID, given a file name (where all
+# requested IDs are stored), a minimum and a maximum value.
+#
+# We use flock to implement locking for the ID file and ignore
+# possible problems arising from lack of support for it on
+# some platforms (it should work on most, and the possible
+# race condition would occur rarely). The proper solution for
+# this is a daemon that manages IDs, of course.
+#
+# If no unique ID within the specified parameters can be
+# obtained, return undef.
+#
+sub mtr_require_unique_id($$$) {
+ my $file = shift;
+ my $min = shift;
+ my $max = shift;
+ my $ret = undef;
+ my $changed = 0;
+
+ my $can_use_ps = `ps -e | grep '^[ ]*$$ '`;
+
+ if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
+ die 'lock file is a symbolic link';
+ }
+
+ chmod 0777, "$file.sem";
+ open SEM, ">", "$file.sem" or die "can't write to $file.sem";
+ flock SEM, LOCK_EX or die "can't lock $file.sem";
+ if(! -e $file) {
+ open FILE, ">", $file or die "can't create $file";
+ close FILE;
+ }
+
+ if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
+ die 'lock file is a symbolic link';
+ }
+
+ chmod 0777, $file;
+ open FILE, "+<", $file or die "can't open $file";
+ select undef,undef,undef,0.2;
+ seek FILE, 0, 0;
+ my %taken = ();
+ while(<FILE>) {
+ chomp;
+ my ($id, $pid) = split / /;
+ $taken{$id} = $pid;
+ if($can_use_ps) {
+ my $res = `ps -e | grep '^[ ]*$pid '`;
+ if(!$res) {
+ print "Ignoring slot $id used by missing process $pid.\n";
+ delete $taken{$id};
+ ++$changed;
+ }
+ }
+ }
+ for(my $i=$min; $i<=$max; ++$i) {
+ if(! exists $taken{$i}) {
+ $ret = $i;
+ $taken{$i} = $$;
+ ++$changed;
+ last;
+ }
+ }
+ if($changed) {
+ seek FILE, 0, 0;
+ truncate FILE, 0 or die "can't truncate $file";
+ for my $k (keys %taken) {
+ print FILE $k . ' ' . $taken{$k} . "\n";
+ }
+ }
+ close FILE;
+ flock SEM, LOCK_UN or warn "can't unlock $file.sem";
+ close SEM;
+ $mtr_unique_assigned_ids{$ret} = $file if defined $ret;
+ return $ret;
+}
+
+#
+# Require a unique ID like above, but sleep if no ID can be
+# obtained immediately.
+#
+sub mtr_require_unique_id_and_wait($$$) {
+ my $ret = mtr_require_unique_id($_[0],$_[1],$_[2]);
+ while(! defined $ret) {
+ sleep 30;
+ $ret = mtr_require_unique_id($_[0],$_[1],$_[2]);
+ print "Waiting for unique id to become available...\n" unless $ret;
+ }
+ return $ret;
+}
+
+#
+# Release a unique ID.
+#
+sub mtr_release_unique_id($$) {
+ my $file = shift;
+ my $myid = shift;
+
+ if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
+ die 'lock file is a symbolic link';
+ }
+
+ open SEM, ">", "$file.sem" or die "can't write to $file.sem";
+ flock SEM, LOCK_EX or die "can't lock $file.sem";
+
+ if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
+ die 'lock file is a symbolic link';
+ }
+
+ if(! -e $file) {
+ open FILE, ">", $file or die "can't create $file";
+ close FILE;
+ }
+ open FILE, "+<", $file or die "can't open $file";
+ select undef,undef,undef,0.2;
+ seek FILE, 0, 0;
+ my %taken = ();
+ while(<FILE>) {
+ chomp;
+ my ($id, $pid) = split / /;
+ $taken{$id} = $pid;
+ }
+ delete $taken{$myid};
+ seek FILE, 0, 0;
+ truncate FILE, 0 or die "can't truncate $file";
+ for my $k (keys %taken) {
+ print FILE $k . ' ' . $taken{$k} . "\n";
+ }
+ close FILE;
+ flock SEM, LOCK_UN or warn "can't unlock $file.sem";
+ close SEM;
+ delete $mtr_unique_assigned_ids{$myid};
+}
+
+1;
+
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 46de66adde4..6aacbfdf1ad 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -1,30 +1,24 @@
#!/usr/bin/perl
# -*- cperl -*-
-# This is a transformation of the "mysql-test-run" Bourne shell script
-# to Perl. There are reasons this rewrite is not the prettiest Perl
-# you have seen
#
-# - The original script is huge and for most part uncommented,
-# not even a usage description of the flags.
+##############################################################################
+#
+# mysql-test-run.pl
+#
+# Tool used for executing a suite of .test file
#
-# - There has been an attempt to write a replacement in C for the
-# original Bourne shell script. It was kind of working but lacked
-# lot of functionality to really be a replacement. Not to redo
-# that mistake and catch all the obscure features of the original
-# script, the rewrite in Perl is more close to the original script
-# meaning it also share some of the ugly parts as well.
+# See the "MySQL Test framework manual" for more information
+# http://dev.mysql.com/doc/mysqltest/en/index.html
#
-# - The original intention was that this script was to be a prototype
-# to be the base for a new C version with full functionality. Since
-# then it was decided that the Perl version should replace the
-# Bourne shell version, but the Perl style still reflects the wish
-# to make the Perl to C step easy.
+# Please keep the test framework tools identical in all versions!
+#
+##############################################################################
#
-# Some coding style from the original intent has been kept
+# Coding style directions for this perl script
#
# - To make this Perl script easy to alter even for those that not
-# code Perl that often, the coding style is as close as possible to
+# code Perl that often, keeep the coding style as close as possible to
# the C/C++ MySQL coding standard.
#
# - All lists of arguments to send to commands are Perl lists/arrays,
@@ -42,15 +36,6 @@
# the information. This separates the "find information" from the
# "do the work" and makes the program more easy to maintain.
#
-# - At the moment, there are tons of "global" variables that control
-# this script, even accessed from the files in "lib/*.pl". This
-# will change over time, for now global variables are used instead
-# of using %opt, %path and %exe hashes, because I want more
-# compile time checking, that hashes would not give me. Once this
-# script is debugged, hashes will be used and passed as parameters
-# to functions, to more closely mimic how it would be coded in C
-# using structs.
-#
# - The rule when it comes to the logic of this program is
#
# command_line_setup() - is to handle the logic between flags
@@ -66,10 +51,6 @@
# "http://www.plover.com/~mjd/perl/Trace/" and run this script like
# "perl -d:Trace mysql-test-run.pl"
#
-# FIXME Save a PID file from this code as well, to record the process
-# id we think it has. In Cygwin, a fork creates one Cygwin process,
-# and then the real Win32 process. Cygwin Perl can only kill Cygwin
-# processes. And "mysqld --bootstrap ..." doesn't save a PID file.
$Devel::Trace::TRACE= 0; # Don't trace boring init stuff
@@ -80,12 +61,18 @@ use File::Copy;
use Cwd;
use Getopt::Long;
use Sys::Hostname;
-#use Carp;
use IO::Socket;
use IO::Socket::INET;
-use Data::Dumper;
use strict;
-#use diagnostics;
+use warnings;
+
+select(STDOUT);
+$| = 1; # Automatically flush STDOUT
+
+our $glob_win32_perl= ($^O eq "MSWin32"); # ActiveState Win32 Perl
+our $glob_cygwin_perl= ($^O eq "cygwin"); # Cygwin Perl
+our $glob_win32= ($glob_win32_perl or $glob_cygwin_perl);
+our $glob_netware= ($^O eq "NetWare"); # NetWare
require "lib/mtr_cases.pl";
require "lib/mtr_im.pl";
@@ -99,41 +86,18 @@ require "lib/mtr_diff.pl";
require "lib/mtr_match.pl";
require "lib/mtr_misc.pl";
require "lib/mtr_stress.pl";
+require "lib/mtr_unique.pl";
$Devel::Trace::TRACE= 1;
-# Used by gcov
-our @mysqld_src_dirs=
- (
- "strings",
- "mysys",
- "include",
- "extra",
- "regex",
- "isam",
- "merge",
- "myisam",
- "myisammrg",
- "heap",
- "sql",
- );
-
##############################################################################
#
# Default settings
#
##############################################################################
-# We are to use handle_options() in "mysys/my_getopt.c" for the C version
-#
-# In the C version we want to use structs and, in some cases, arrays of
-# structs. We let each struct be a separate hash.
-
# Misc global variables
-
-our $glob_win32= 0; # OS and native Win32 executables
-our $glob_win32_perl= 0; # ActiveState Win32 Perl
-our $glob_cygwin_perl= 0; # Cygwin Perl
+our $mysql_version_id;
our $glob_mysql_test_dir= undef;
our $glob_mysql_bench_dir= undef;
our $glob_hostname= undef;
@@ -141,36 +105,38 @@ our $glob_scriptname= undef;
our $glob_timers= undef;
our $glob_use_running_server= 0;
our $glob_use_running_ndbcluster= 0;
+our $glob_use_running_ndbcluster_slave= 0;
our $glob_use_embedded_server= 0;
our @glob_test_mode;
-our $using_ndbcluster_master= 0;
-
our $glob_basedir;
-# The total result
-
our $path_charsetsdir;
our $path_client_bindir;
our $path_language;
our $path_timefile;
our $path_snapshot;
-our $path_slave_load_tmpdir; # What is this?!
our $path_mysqltest_log;
our $path_current_test_log;
our $path_my_basedir;
+
our $opt_vardir; # A path but set directly on cmd line
-our $opt_vardir_trace; # unix formatted opt_vardir for trace files
+our $path_vardir_trace; # unix formatted opt_vardir for trace files
our $opt_tmpdir; # A path but set directly on cmd line
+# Visual Studio produces executables in different sub-directories based on the
+# configuration used to build them. To make life easier, an environment
+# variable or command-line option may be specified to control which set of
+# executables will be used by the test suite.
+our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
+
+our $default_vardir;
+
our $opt_usage;
our $opt_suite;
-our $opt_netware;
-
our $opt_script_debug= 0; # Script debugging, enable with --script-debug
-
-# Options FIXME not all....
+our $opt_verbose= 0; # Verbose output, enable with --verbose
our $exe_master_mysqld;
our $exe_mysql;
@@ -178,12 +144,15 @@ our $exe_mysqladmin;
our $exe_mysqlbinlog;
our $exe_mysql_client_test;
our $exe_mysqld;
-our $exe_mysqlcheck; # Called from test case
-our $exe_mysqldump; # Called from test case
-our $exe_mysqlimport; # Called from test case
-our $exe_mysqlshow; # Called from test case
+our $exe_mysqlcheck;
+our $exe_mysqldump;
+our $exe_mysqlslap;
+our $exe_mysqlimport;
+our $exe_mysqlshow;
our $exe_mysql_fix_system_tables;
our $exe_mysqltest;
+our $exe_ndbd;
+our $exe_ndb_mgmd;
our $exe_slave_mysqld;
our $exe_im;
our $exe_my_print_defaults;
@@ -197,7 +166,6 @@ our $opt_big_test= 0; # Send --big-test to mysqltest
our @opt_extra_mysqld_opt;
-our $opt_comment;
our $opt_compress;
our $opt_ssl;
our $opt_skip_ssl;
@@ -214,7 +182,9 @@ our $opt_embedded_server;
our $opt_extern;
our $opt_fast;
our $opt_force;
-our $opt_reorder;
+our $opt_reorder= 0;
+our $opt_enable_disabled;
+our $opt_mem= $ENV{'MTR_MEM'};
our $opt_gcov;
our $opt_gcov_err;
@@ -228,6 +198,7 @@ our $opt_client_ddd;
our $opt_manual_gdb;
our $opt_manual_ddd;
our $opt_manual_debug;
+our $opt_mtr_build_thread=0;
our $opt_debugger;
our $opt_client_debugger;
@@ -236,27 +207,30 @@ our $opt_gprof_dir;
our $opt_gprof_master;
our $opt_gprof_slave;
-our $opt_local;
-our $opt_local_master;
-
-our $master; # Will be struct in C
+our $master;
our $slave;
+our $clusters;
our $instance_manager;
+our $opt_master_myport;
+our $opt_slave_myport;
+our $im_port;
+our $im_mysqld1_port;
+our $im_mysqld2_port;
our $opt_ndbcluster_port;
our $opt_ndbconnectstring;
-
-our $opt_old_master;
+our $opt_ndbcluster_port_slave;
+our $opt_ndbconnectstring_slave;
our $opt_record;
our $opt_check_testcases;
-
-our $opt_result_ext;
+my $opt_report_features;
our $opt_skip;
our $opt_skip_rpl;
our $max_slave_num= 0;
+our $use_innodb;
our $opt_skip_test;
our $opt_skip_im;
@@ -279,7 +253,7 @@ our $opt_start_from;
our $opt_strace_client;
-our $opt_timer;
+our $opt_timer= 1;
our $opt_user;
our $opt_user_test;
@@ -287,9 +261,10 @@ our $opt_user_test;
our $opt_valgrind= 0;
our $opt_valgrind_mysqld= 0;
our $opt_valgrind_mysqltest= 0;
-our $default_valgrind_options= "-v --show-reachable=yes";
+our $default_valgrind_options= "--show-reachable=yes";
our $opt_valgrind_options;
our $opt_valgrind_path;
+our $opt_callgrind;
our $opt_stress= "";
our $opt_stress_suite= "main";
@@ -309,20 +284,31 @@ our $opt_warnings;
our $opt_udiff;
-our $opt_skip_ndbcluster;
-our $opt_with_ndbcluster;
-our $opt_with_ndbcluster_only= 0; # dummy, ignored
-
-our $opt_with_openssl;
+our $opt_skip_ndbcluster= 0;
+our $opt_skip_ndbcluster_slave= 0;
+our $opt_with_ndbcluster= 0;
+our $opt_with_ndbcluster_only= 0;
+our $glob_ndbcluster_supported= 0;
+our $opt_ndb_extra_test= 0;
+our $opt_skip_master_binlog= 0;
+our $opt_skip_slave_binlog= 0;
our $exe_ndb_mgm;
+our $exe_ndb_waiter;
our $path_ndb_tools_dir;
-our $path_ndb_data_dir;
-our $file_ndb_testrun_log;
-our $flag_ndb_status_ok= 1;
+our $path_ndb_examples_dir;
+our $exe_ndb_example;
+our $path_ndb_testrun_log;
our @data_dir_lst;
+our $used_binlog_format;
+our $debug_compiled_binaries;
+our $glob_tot_real_time= 0;
+
+our %mysqld_variables;
+
+
######################################################################
#
# Function declarations
@@ -332,30 +318,37 @@ our @data_dir_lst;
sub main ();
sub initial_setup ();
sub command_line_setup ();
-sub snapshot_setup ();
+sub set_mtr_build_thread_ports($);
+sub datadir_setup ();
sub executable_setup ();
sub environment_setup ();
-sub kill_running_server ();
+sub kill_running_servers ();
sub cleanup_stale_files ();
-sub check_ssl_support ();
+sub check_ssl_support ($);
sub check_running_as_root();
-sub check_ndbcluster_support ();
-sub ndbcluster_install ();
-sub ndbcluster_start ($);
-sub ndbcluster_stop ();
+sub check_ndbcluster_support ($);
+sub rm_ndbcluster_tables ($);
+sub ndbcluster_start_install ($);
+sub ndbcluster_start ($$);
+sub ndbcluster_wait_started ($$);
+sub mysqld_wait_started($);
sub run_benchmarks ($);
sub initialize_servers ();
sub mysql_install_db ();
sub install_db ($$);
+sub copy_install_db ($$);
sub run_testcase ($);
+sub run_testcase_stop_servers ($$$);
+sub run_testcase_start_servers ($);
+sub run_testcase_check_skip_test($);
sub report_failure_and_restart ($);
-sub do_before_start_master ($$);
-sub do_before_start_slave ($$);
-sub mysqld_start ($$$$$);
-sub mysqld_arguments ($$$$$$);
-sub stop_masters_slaves ();
-sub stop_masters ();
-sub stop_slaves ();
+sub do_before_start_master ($);
+sub do_before_start_slave ($);
+sub ndbd_start ($$$);
+sub ndb_mgmd_start ($);
+sub mysqld_start ($$$);
+sub mysqld_arguments ($$$$$);
+sub stop_all_servers ();
sub run_mysqltest ($);
sub usage ($);
@@ -369,12 +362,13 @@ main();
sub main () {
- initial_setup();
command_line_setup();
- executable_setup();
- check_ndbcluster_support(); # We check whether to actually use it later
- check_ssl_support();
+ check_ndbcluster_support(\%mysqld_variables);
+ check_ssl_support(\%mysqld_variables);
+ check_debug_support(\%mysqld_variables);
+
+ executable_setup();
environment_setup();
signal_setup();
@@ -408,6 +402,8 @@ sub main () {
my ($need_ndbcluster,$need_im);
foreach my $test (@$tests)
{
+ next if $test->{skip};
+
$need_ndbcluster||= $test->{ndb_test};
$need_im||= $test->{component_id} eq 'im';
@@ -417,75 +413,40 @@ sub main () {
$max_slave_num= $test->{slave_num};
mtr_error("Too many slaves") if $max_slave_num > 3;
}
+ $use_innodb||= $test->{'innodb_test'};
}
- $opt_with_ndbcluster= 0 unless $need_ndbcluster;
- $opt_skip_im= 1 unless $need_im;
-
- snapshot_setup();
- initialize_servers();
-
- run_suite($opt_suite, $tests);
- }
-
- mtr_exit(0);
-}
-
-##############################################################################
-#
-# Initial setup independent on command line arguments
-#
-##############################################################################
-
-sub initial_setup () {
-
- select(STDOUT);
- $| = 1; # Make unbuffered
-
- $glob_scriptname= basename($0);
- $glob_win32_perl= ($^O eq "MSWin32");
- $glob_cygwin_perl= ($^O eq "cygwin");
- $glob_win32= ($glob_win32_perl or $glob_cygwin_perl);
+ # Check if cluster can be skipped
+ if ( !$need_ndbcluster )
+ {
+ $opt_skip_ndbcluster= 1;
+ $opt_skip_ndbcluster_slave= 1;
+ }
- # We require that we are in the "mysql-test" directory
- # to run mysql-test-run
+ # Check if slave cluster can be skipped
+ if ($max_slave_num == 0)
+ {
+ $opt_skip_ndbcluster_slave= 1;
+ }
- if (! -f $glob_scriptname)
- {
- mtr_error("Can't find the location for the mysql-test-run script\n" .
- "Go to to the mysql-test directory and execute the script " .
- "as follows:\n./$glob_scriptname");
- }
+ # Check if im can be skipped
+ if ( ! $need_im )
+ {
+ $opt_skip_im= 1;
+ }
- if ( -d "../sql" )
- {
- $opt_source_dist= 1;
- }
+ initialize_servers();
- $glob_hostname= mtr_short_hostname();
+ if ( $opt_report_features ) {
+ run_report_features();
+ }
- # 'basedir' is always parent of "mysql-test" directory
- $glob_mysql_test_dir= cwd();
- if ( $glob_cygwin_perl )
- {
- # Windows programs like 'mysqld' needs Windows paths
- $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`;
- chomp($glob_mysql_test_dir);
+ run_suite($opt_suite, $tests);
}
- $glob_basedir= dirname($glob_mysql_test_dir);
- $glob_mysql_bench_dir= "$glob_basedir/mysql-bench"; # FIXME make configurable
-
- # needs to be same length to test logging (FIXME what???)
- $path_slave_load_tmpdir= "../../var/tmp";
-
- $path_my_basedir=
- $opt_source_dist ? $glob_mysql_test_dir : $glob_basedir;
- $glob_timers= mtr_init_timers();
+ mtr_exit(0);
}
-
-
##############################################################################
#
# Default settings
@@ -497,43 +458,19 @@ sub command_line_setup () {
# These are defaults for things that are set on the command line
$opt_suite= "main"; # Special default suite
- my $opt_master_myport= 9306;
- my $opt_slave_myport= 9308;
- $opt_ndbcluster_port= 9350;
- my $im_port= 9311;
- my $im_mysqld1_port= 9312;
- my $im_mysqld2_port= 9314;
+ my $opt_comment;
+
+ $opt_master_myport= 9306;
+ $opt_slave_myport= 9308;
+ $opt_ndbcluster_port= 9310;
+ $opt_ndbcluster_port_slave= 9311;
+ $im_port= 9312;
+ $im_mysqld1_port= 9313;
+ $im_mysqld2_port= 9314;
- #
- # To make it easier for different devs to work on the same host,
- # an environment variable can be used to control all ports. A small
- # number is to be used, 0 - 16 or similar.
- #
- # Note the MASTER_MYPORT has to be set the same in all 4.x and 5.x
- # versions of this script, else a 4.0 test run might conflict with a
- # 5.1 test run, even if different MTR_BUILD_THREAD is used. This means
- # all port numbers might not be used in this version of the script.
- #
- # Also note the limiteation of ports we are allowed to hand out. This
- # differs between operating systems and configuration, see
- # http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html
- # But a fairly safe range seems to be 5001 - 32767
if ( $ENV{'MTR_BUILD_THREAD'} )
{
- # Up to two masters, up to three slaves
- $opt_master_myport= $ENV{'MTR_BUILD_THREAD'} * 10 + 10000; # and 1
- $opt_slave_myport= $opt_master_myport + 2; # and 3 4
- $opt_ndbcluster_port= $opt_master_myport + 5;
- $im_port= $opt_master_myport + 6;
- $im_mysqld1_port= $opt_master_myport + 7;
- $im_mysqld2_port= $opt_master_myport + 8;
- }
-
- if ( $opt_master_myport < 5001 or $opt_master_myport + 10 >= 32767 )
- {
- mtr_error("MTR_BUILD_THREAD number results in a port",
- "outside 5001 - 32767",
- "($opt_master_myport - $opt_master_myport + 10)");
+ set_mtr_build_thread_ports($ENV{'MTR_BUILD_THREAD'});
}
# This is needed for test log evaluation in "gen-build-status-page"
@@ -557,36 +494,47 @@ sub command_line_setup () {
'compress' => \$opt_compress,
'bench' => \$opt_bench,
'small-bench' => \$opt_small_bench,
+ 'with-ndbcluster' => \$opt_with_ndbcluster,
+ 'vs-config' => \$opt_vs_config,
# Control what test suites or cases to run
'force' => \$opt_force,
- 'with-ndbcluster' => \$opt_with_ndbcluster,
- 'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
'with-ndbcluster-only' => \$opt_with_ndbcluster_only,
+ 'skip-ndbcluster|skip-ndb' => \$opt_skip_ndbcluster,
+ 'skip-ndbcluster-slave|skip-ndb-slave'
+ => \$opt_skip_ndbcluster_slave,
+ 'ndb-extra-test' => \$opt_ndb_extra_test,
+ 'skip-master-binlog' => \$opt_skip_master_binlog,
+ 'skip-slave-binlog' => \$opt_skip_slave_binlog,
'do-test=s' => \$opt_do_test,
+ 'start-from=s' => \$opt_start_from,
'suite=s' => \$opt_suite,
'skip-rpl' => \$opt_skip_rpl,
'skip-im' => \$opt_skip_im,
'skip-test=s' => \$opt_skip_test,
+ 'big-test' => \$opt_big_test,
# Specify ports
'master_port=i' => \$opt_master_myport,
'slave_port=i' => \$opt_slave_myport,
- 'ndbcluster_port=i' => \$opt_ndbcluster_port,
+ 'ndbcluster-port|ndbcluster_port=i' => \$opt_ndbcluster_port,
+ 'ndbcluster-port-slave=i' => \$opt_ndbcluster_port_slave,
'im-port=i' => \$im_port, # Instance Manager port.
'im-mysqld1-port=i' => \$im_mysqld1_port, # Port of mysqld, controlled by IM
'im-mysqld2-port=i' => \$im_mysqld2_port, # Port of mysqld, controlled by IM
+ 'mtr-build-thread=i' => \$opt_mtr_build_thread,
# Test case authoring
'record' => \$opt_record,
'check-testcases' => \$opt_check_testcases,
- # ???
+ # Extra options used when starting mysqld
'mysqld=s' => \@opt_extra_mysqld_opt,
# Run test on running server
'extern' => \$opt_extern,
- 'ndbconnectstring=s' => \$opt_ndbconnectstring,
+ 'ndb-connectstring=s' => \$opt_ndbconnectstring,
+ 'ndb-connectstring-slave=s' => \$opt_ndbconnectstring_slave,
# Debugging
'gdb' => \$opt_gdb,
@@ -609,6 +557,7 @@ sub command_line_setup () {
'valgrind-mysqld' => \$opt_valgrind_mysqld,
'valgrind-options=s' => \$opt_valgrind_options,
'valgrind-path=s' => \$opt_valgrind_path,
+ 'callgrind' => \$opt_callgrind,
# Stress testing
'stress' => \$opt_stress,
@@ -624,24 +573,23 @@ sub command_line_setup () {
# Directories
'tmpdir=s' => \$opt_tmpdir,
'vardir=s' => \$opt_vardir,
+ 'benchdir=s' => \$glob_mysql_bench_dir,
+ 'mem:s' => \$opt_mem,
# Misc
- 'big-test' => \$opt_big_test,
+ 'report-features' => \$opt_report_features,
'comment=s' => \$opt_comment,
'debug' => \$opt_debug,
'fast' => \$opt_fast,
- 'local' => \$opt_local,
- 'local-master' => \$opt_local_master,
- 'netware' => \$opt_netware,
- 'old-master' => \$opt_old_master,
'reorder' => \$opt_reorder,
+ 'enable-disabled' => \$opt_enable_disabled,
'script-debug' => \$opt_script_debug,
+ 'verbose' => \$opt_verbose,
'sleep=i' => \$opt_sleep,
'socket=s' => \$opt_socket,
'start-dirty' => \$opt_start_dirty,
'start-and-exit' => \$opt_start_and_exit,
- 'start-from=s' => \$opt_start_from,
- 'timer' => \$opt_timer,
+ 'timer!' => \$opt_timer,
'unified-diff|udiff' => \$opt_udiff,
'user-test=s' => \$opt_user_test,
'user=s' => \$opt_user,
@@ -653,11 +601,97 @@ sub command_line_setup () {
'help|h' => \$opt_usage,
) or usage("Can't read options");
- if ( $opt_usage )
+ usage("") if $opt_usage;
+
+ $glob_scriptname= basename($0);
+
+ if ($opt_mtr_build_thread != 0)
+ {
+ set_mtr_build_thread_ports($opt_mtr_build_thread)
+ }
+ elsif ($ENV{'MTR_BUILD_THREAD'})
+ {
+ $opt_mtr_build_thread= $ENV{'MTR_BUILD_THREAD'};
+ }
+
+ # We require that we are in the "mysql-test" directory
+ # to run mysql-test-run
+ if (! -f $glob_scriptname)
+ {
+ mtr_error("Can't find the location for the mysql-test-run script\n" .
+ "Go to to the mysql-test directory and execute the script " .
+ "as follows:\n./$glob_scriptname");
+ }
+
+ if ( -d "../sql" )
{
- usage("");
+ $opt_source_dist= 1;
}
+ $glob_hostname= mtr_short_hostname();
+
+ # Find the absolute path to the test directory
+ $glob_mysql_test_dir= cwd();
+ if ( $glob_cygwin_perl )
+ {
+ # Windows programs like 'mysqld' needs Windows paths
+ $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`;
+ chomp($glob_mysql_test_dir);
+ }
+
+ # In most cases, the base directory we find everything relative to,
+ # is the parent directory of the "mysql-test" directory. For source
+ # distributions, TAR binary distributions and some other packages.
+ $glob_basedir= dirname($glob_mysql_test_dir);
+
+ # In the RPM case, binaries and libraries are installed in the
+ # default system locations, instead of having our own private base
+ # directory. And we install "/usr/share/mysql-test". Moving up one
+ # more directory relative to "mysql-test" gives us a usable base
+ # directory for RPM installs.
+ if ( ! $opt_source_dist and ! -d "$glob_basedir/bin" )
+ {
+ $glob_basedir= dirname($glob_basedir);
+ }
+
+ # Expect mysql-bench to be located adjacent to the source tree, by default
+ $glob_mysql_bench_dir= "$glob_basedir/../mysql-bench"
+ unless defined $glob_mysql_bench_dir;
+ $glob_mysql_bench_dir= undef
+ unless -d $glob_mysql_bench_dir;
+
+ $path_my_basedir=
+ $opt_source_dist ? $glob_mysql_test_dir : $glob_basedir;
+
+ $glob_timers= mtr_init_timers();
+
+ #
+ # Find the mysqld executable to be able to find the mysqld version
+ # number as early as possible
+ #
+
+ # Look for the client binaries
+ $path_client_bindir= mtr_path_exists(vs_config_dirs('client', ''),
+ "$glob_basedir/client_release",
+ "$glob_basedir/client_debug",
+ "$glob_basedir/client",
+ "$glob_basedir/bin");
+
+ $exe_mysqld= mtr_exe_exists (vs_config_dirs('sql', 'mysqld'),
+ "$glob_basedir/sql/mysqld",
+ "$path_client_bindir/mysqld-max-nt",
+ "$path_client_bindir/mysqld-max",
+ "$path_client_bindir/mysqld-nt",
+ "$path_client_bindir/mysqld",
+ "$path_client_bindir/mysqld-debug",
+ "$path_client_bindir/mysqld-max",
+ "$glob_basedir/libexec/mysqld",
+ "$glob_basedir/bin/mysqld",
+ "$glob_basedir/sbin/mysqld");
+
+ # Use the mysqld found above to find out what features are available
+ collect_mysqld_features();
+
if ( $opt_comment )
{
print "\n";
@@ -666,11 +700,6 @@ sub command_line_setup () {
print '#' x 78, "\n\n";
}
- if ( $opt_with_ndbcluster_only )
- {
- print "# Option '--with-ndbcluster-only' is ignored in this release.\n";
- }
-
foreach my $arg ( @ARGV )
{
if ( $arg =~ /^--skip-/ )
@@ -694,16 +723,78 @@ sub command_line_setup () {
}
# --------------------------------------------------------------------------
- # Set the "var/" directory, as it is the base for everything else
+ # Find out type of logging that are being used
+ # --------------------------------------------------------------------------
+ # NOTE if the default binlog format is changed, this has to be changed
+ $used_binlog_format= "stmt";
+ if ( $mysql_version_id >= 50100 )
+ {
+ $used_binlog_format= "mixed"; # Default value for binlog format
+
+ foreach my $arg ( @opt_extra_mysqld_opt )
+ {
+ if ( $arg =~ /binlog-format=(\S+)/ )
+ {
+ $used_binlog_format= $1;
+ }
+ }
+ mtr_report("Using binlog format '$used_binlog_format'");
+ }
+
# --------------------------------------------------------------------------
+ # Check if we should speed up tests by trying to run on tmpfs
+ # --------------------------------------------------------------------------
+ if ( defined $opt_mem )
+ {
+ mtr_error("Can't use --mem and --vardir at the same time ")
+ if $opt_vardir;
+ mtr_error("Can't use --mem and --tmpdir at the same time ")
+ if $opt_tmpdir;
+
+ # Search through list of locations that are known
+ # to be "fast disks" to list to find a suitable location
+ # Use --mem=<dir> as first location to look.
+ my @tmpfs_locations= ($opt_mem, "/dev/shm", "/tmp");
+
+ foreach my $fs (@tmpfs_locations)
+ {
+ if ( -d $fs )
+ {
+ mtr_report("Using tmpfs in $fs");
+ $opt_mem= "$fs/var";
+ $opt_mem .= $opt_mtr_build_thread if $opt_mtr_build_thread;
+ last;
+ }
+ }
+ }
+ # --------------------------------------------------------------------------
+ # Set the "var/" directory, as it is the base for everything else
+ # --------------------------------------------------------------------------
+ $default_vardir= "$glob_mysql_test_dir/var";
if ( ! $opt_vardir )
{
- $opt_vardir= "$glob_mysql_test_dir/var";
+ $opt_vardir= $default_vardir;
}
- $opt_vardir_trace= $opt_vardir;
+ elsif ( $mysql_version_id < 50000 and
+ $opt_vardir ne $default_vardir)
+ {
+ # Version 4.1 and --vardir was specified
+ # Only supported as a symlink from var/
+ # by setting up $opt_mem that symlink will be created
+ if ( ! $glob_win32 )
+ {
+ # Only platforms that have native symlinks can use the vardir trick
+ $opt_mem= $opt_vardir;
+ mtr_report("Using 4.1 vardir trick");
+ }
+
+ $opt_vardir= $default_vardir;
+ }
+
+ $path_vardir_trace= $opt_vardir;
# Chop off any "c:", DBUG likes a unix path ex: c:/src/... => /src/...
- $opt_vardir_trace=~ s/^\w://;
+ $path_vardir_trace=~ s/^\w://;
# We make the path absolute, as the server will do a chdir() before usage
unless ( $opt_vardir =~ m,^/, or
@@ -713,44 +804,61 @@ sub command_line_setup () {
$opt_vardir= "$glob_mysql_test_dir/$opt_vardir";
}
+ # Ensure a proper error message
+ mkpath("$opt_vardir");
+ unless ( -d $opt_vardir and -w $opt_vardir )
+ {
+ mtr_error("Writable 'var' directory is needed, use the '--vardir' option");
+ }
+
# --------------------------------------------------------------------------
- # If not set, set these to defaults
+ # Set tmpdir
# --------------------------------------------------------------------------
-
$opt_tmpdir= "$opt_vardir/tmp" unless $opt_tmpdir;
$opt_tmpdir =~ s,/+$,,; # Remove ending slash if any
# --------------------------------------------------------------------------
- # Do sanity checks of command line arguments
+ # Set socket
# --------------------------------------------------------------------------
+ if (!$opt_socket)
+ {
+ $opt_socket= $mysqld_variables{'socket'};
+ }
- if ( $opt_extern and $opt_local )
+ # --------------------------------------------------------------------------
+ # Check im suport
+ # --------------------------------------------------------------------------
+ if ( $mysql_version_id < 50000 )
{
- mtr_error("Can't use --extern and --local at the same time");
+ # Instance manager is not supported until 5.0
+ $opt_skip_im= 1;
+
}
- if ( ! $opt_socket )
- { # FIXME set default before reading options?
-# $opt_socket= '@MYSQL_UNIX_ADDR@';
- $opt_socket= "/tmp/mysql.sock"; # FIXME
+ if ( $glob_win32 )
+ {
+ mtr_report("Disable Instance manager - not supported on Windows");
+ $opt_skip_im= 1;
}
# --------------------------------------------------------------------------
- # Look at the command line options and set script flags
+ # Record flag
# --------------------------------------------------------------------------
-
if ( $opt_record and ! @opt_cases )
{
mtr_error("Will not run in record mode without a specific test case");
}
+ # --------------------------------------------------------------------------
+ # Embedded server flag
+ # --------------------------------------------------------------------------
if ( $opt_embedded_server )
{
$glob_use_embedded_server= 1;
push(@glob_test_mode, "embedded");
$opt_skip_rpl= 1; # We never run replication with embedded
- $opt_skip_ndbcluster= 1;
- $opt_skip_ssl= 1;
+ $opt_skip_ndbcluster= 1; # Turn off use of NDB cluster
+ $opt_skip_ssl= 1; # Turn off use of SSL
if ( $opt_extern )
{
@@ -758,33 +866,80 @@ sub command_line_setup () {
}
}
+
+ # --------------------------------------------------------------------------
+ # ps protcol flag
+ # --------------------------------------------------------------------------
if ( $opt_ps_protocol )
{
push(@glob_test_mode, "ps-protocol");
}
- # FIXME don't understand what this is
-# if ( $opt_local_master )
-# {
-# $opt_master_myport= 3306;
-# }
+ # --------------------------------------------------------------------------
+ # Ndb cluster flags
+ # --------------------------------------------------------------------------
+ if ( $opt_with_ndbcluster and !$opt_bench)
+ {
+ mtr_error("Can only use --with-ndbcluster togheter with --bench");
+ }
+ if ( $opt_ndbconnectstring )
+ {
+ $glob_use_running_ndbcluster= 1;
+ mtr_error("Can't specify --ndb-connectstring and --skip-ndbcluster")
+ if $opt_skip_ndbcluster;
+ mtr_error("Can't specify --ndb-connectstring and --ndbcluster-port")
+ if $opt_ndbcluster_port;
+ }
+ else
+ {
+ # Set default connect string
+ $opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port";
+ }
+
+ if ( $opt_ndbconnectstring_slave )
+ {
+ $glob_use_running_ndbcluster_slave= 1;
+ mtr_error("Can't specify ndb-connectstring_slave and " .
+ "--skip-ndbcluster-slave")
+ if $opt_skip_ndbcluster;
+ mtr_error("Can't specify --ndb-connectstring-slave and " .
+ "--ndbcluster-port-slave")
+ if $opt_ndbcluster_port_slave;
+ }
+ else
+ {
+ # Set default connect string
+ $opt_ndbconnectstring_slave= "host=localhost:$opt_ndbcluster_port_slave";
+ }
+
+ # --------------------------------------------------------------------------
+ # Bench flags
+ # --------------------------------------------------------------------------
if ( $opt_small_bench )
{
$opt_bench= 1;
}
+ # --------------------------------------------------------------------------
+ # Sleep flag
+ # --------------------------------------------------------------------------
if ( $opt_sleep )
{
$opt_sleep_time_after_restart= $opt_sleep;
}
+ # --------------------------------------------------------------------------
+ # Gcov flag
+ # --------------------------------------------------------------------------
if ( $opt_gcov and ! $opt_source_dist )
{
mtr_error("Coverage test needs the source - please use source dist");
}
+ # --------------------------------------------------------------------------
# Check debug related options
+ # --------------------------------------------------------------------------
if ( $opt_gdb || $opt_client_gdb || $opt_ddd || $opt_client_ddd ||
$opt_manual_gdb || $opt_manual_ddd || $opt_manual_debug ||
$opt_debugger || $opt_client_debugger )
@@ -799,29 +954,15 @@ sub command_line_setup () {
}
}
- if ( $opt_ndbconnectstring )
- {
- $glob_use_running_ndbcluster= 1;
- $opt_with_ndbcluster= 1;
- }
- else
- {
- $opt_ndbconnectstring= "host=localhost:$opt_ndbcluster_port";
- }
-
- if ( $opt_skip_ndbcluster )
- {
- $opt_with_ndbcluster= 0;
- }
-
- # Check IM arguments
- if ( $glob_win32 )
- {
- mtr_report("Disable Instance manager - not supported on Windows");
- $opt_skip_im= 1;
- }
+ # --------------------------------------------------------------------------
+ # Check if special exe was selected for master or slave
+ # --------------------------------------------------------------------------
+ $exe_master_mysqld= $exe_master_mysqld || $exe_mysqld;
+ $exe_slave_mysqld= $exe_slave_mysqld || $exe_mysqld;
+ # --------------------------------------------------------------------------
# Check valgrind arguments
+ # --------------------------------------------------------------------------
if ( $opt_valgrind or $opt_valgrind_path or defined $opt_valgrind_options)
{
mtr_report("Turning on valgrind for all executables");
@@ -836,8 +977,19 @@ sub command_line_setup () {
}
elsif ( $opt_valgrind_mysqltest )
{
- mtr_report("Turning on valgrind for mysqltest only");
+ mtr_report("Turning on valgrind for mysqltest and mysql_client_test only");
+ $opt_valgrind= 1;
+ }
+
+ if ( $opt_callgrind )
+ {
+ mtr_report("Turning on valgrind with callgrind for mysqld(s)");
$opt_valgrind= 1;
+ $opt_valgrind_mysqld= 1;
+
+ # Set special valgrind options unless options passed on command line
+ $opt_valgrind_options="--trace-children=yes"
+ unless defined $opt_valgrind_options;
}
if ( $opt_valgrind )
@@ -890,59 +1042,83 @@ sub command_line_setup () {
$master->[0]=
{
+ pid => 0,
+ type => "master",
+ idx => 0,
path_myddir => "$opt_vardir/master-data",
path_myerr => "$opt_vardir/log/master.err",
path_mylog => "$opt_vardir/log/master.log",
- path_mypid => "$opt_vardir/run/master.pid",
- path_mysock => "$sockdir/master.sock",
- path_myport => $opt_master_myport,
+ path_pid => "$opt_vardir/run/master.pid",
+ path_sock => "$sockdir/master.sock",
+ port => $opt_master_myport,
start_timeout => 400, # enough time create innodb tables
-
- ndbcluster => 1, # ndbcluster not started
+ cluster => 0, # index in clusters list
+ start_opts => [],
};
$master->[1]=
{
+ pid => 0,
+ type => "master",
+ idx => 1,
path_myddir => "$opt_vardir/master1-data",
path_myerr => "$opt_vardir/log/master1.err",
path_mylog => "$opt_vardir/log/master1.log",
- path_mypid => "$opt_vardir/run/master1.pid",
- path_mysock => "$sockdir/master1.sock",
- path_myport => $opt_master_myport + 1,
+ path_pid => "$opt_vardir/run/master1.pid",
+ path_sock => "$sockdir/master1.sock",
+ port => $opt_master_myport + 1,
start_timeout => 400, # enough time create innodb tables
+ cluster => 0, # index in clusters list
+ start_opts => [],
};
$slave->[0]=
{
+ pid => 0,
+ type => "slave",
+ idx => 0,
path_myddir => "$opt_vardir/slave-data",
path_myerr => "$opt_vardir/log/slave.err",
path_mylog => "$opt_vardir/log/slave.log",
- path_mypid => "$opt_vardir/run/slave.pid",
- path_mysock => "$sockdir/slave.sock",
- path_myport => $opt_slave_myport,
+ path_pid => "$opt_vardir/run/slave.pid",
+ path_sock => "$sockdir/slave.sock",
+ port => $opt_slave_myport,
start_timeout => 400,
+
+ cluster => 1, # index in clusters list
+ start_opts => [],
};
$slave->[1]=
{
+ pid => 0,
+ type => "slave",
+ idx => 1,
path_myddir => "$opt_vardir/slave1-data",
path_myerr => "$opt_vardir/log/slave1.err",
path_mylog => "$opt_vardir/log/slave1.log",
- path_mypid => "$opt_vardir/run/slave1.pid",
- path_mysock => "$sockdir/slave1.sock",
- path_myport => $opt_slave_myport + 1,
+ path_pid => "$opt_vardir/run/slave1.pid",
+ path_sock => "$sockdir/slave1.sock",
+ port => $opt_slave_myport + 1,
start_timeout => 300,
+ cluster => -1, # index in clusters list
+ start_opts => [],
};
$slave->[2]=
{
+ pid => 0,
+ type => "slave",
+ idx => 2,
path_myddir => "$opt_vardir/slave2-data",
path_myerr => "$opt_vardir/log/slave2.err",
path_mylog => "$opt_vardir/log/slave2.log",
- path_mypid => "$opt_vardir/run/slave2.pid",
- path_mysock => "$sockdir/slave2.sock",
- path_myport => $opt_slave_myport + 2,
+ path_pid => "$opt_vardir/run/slave2.pid",
+ path_sock => "$sockdir/slave2.sock",
+ port => $opt_slave_myport + 2,
start_timeout => 300,
+ cluster => -1, # index in clusters list
+ start_opts => [],
};
$instance_manager=
@@ -968,7 +1144,8 @@ sub command_line_setup () {
path_datadir => "$opt_vardir/im_mysqld_1.data",
path_sock => "$sockdir/mysqld_1.sock",
path_pid => "$opt_vardir/run/mysqld_1.pid",
- start_timeout => 400, # enough time create innodb tables
+ start_timeout => 400, # enough time create innodb tables
+ old_log_format => 1
};
$instance_manager->{'instances'}->[1]=
@@ -979,24 +1156,111 @@ sub command_line_setup () {
path_sock => "$sockdir/mysqld_2.sock",
path_pid => "$opt_vardir/run/mysqld_2.pid",
nonguarded => 1,
- start_timeout => 400, # enough time create innodb tables
+ start_timeout => 400, # enough time create innodb tables
+ old_log_format => 1
+ };
+
+ my $data_dir= "$opt_vardir/ndbcluster-$opt_ndbcluster_port";
+ $clusters->[0]=
+ {
+ name => "Master",
+ nodes => 2,
+ port => "$opt_ndbcluster_port",
+ data_dir => "$data_dir",
+ connect_string => "$opt_ndbconnectstring",
+ path_pid => "$data_dir/ndb_3.pid", # Nodes + 1
+ pid => 0, # pid of ndb_mgmd
+ installed_ok => 0,
+ };
+
+ $data_dir= "$opt_vardir/ndbcluster-$opt_ndbcluster_port_slave";
+ $clusters->[1]=
+ {
+ name => "Slave",
+ nodes => 1,
+ port => "$opt_ndbcluster_port_slave",
+ data_dir => "$data_dir",
+ connect_string => "$opt_ndbconnectstring_slave",
+ path_pid => "$data_dir/ndb_2.pid", # Nodes + 1
+ pid => 0, # pid of ndb_mgmd
+ installed_ok => 0,
};
+ # Init pids of ndbd's
+ foreach my $cluster ( @{$clusters} )
+ {
+ for ( my $idx= 0; $idx < $cluster->{'nodes'}; $idx++ )
+ {
+ my $nodeid= $idx+1;
+ $cluster->{'ndbds'}->[$idx]=
+ {
+ pid => 0,
+ nodeid => $nodeid,
+ path_pid => "$cluster->{'data_dir'}/ndb_${nodeid}.pid",
+ path_fs => "$cluster->{'data_dir'}/ndb_${nodeid}_fs",
+ };
+ }
+ }
+
if ( $opt_extern )
{
$glob_use_running_server= 1;
$opt_skip_rpl= 1; # We don't run rpl test cases
- $master->[0]->{'path_mysock'}= $opt_socket;
+ $master->[0]->{'path_sock'}= $opt_socket;
}
$path_timefile= "$opt_vardir/log/mysqltest-time";
$path_mysqltest_log= "$opt_vardir/log/mysqltest.log";
$path_current_test_log= "$opt_vardir/log/current_test";
+ $path_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log";
$path_snapshot= "$opt_tmpdir/snapshot_$opt_master_myport/";
}
-sub snapshot_setup () {
+#
+# To make it easier for different devs to work on the same host,
+# an environment variable can be used to control all ports. A small
+# number is to be used, 0 - 16 or similar.
+#
+# Note the MASTER_MYPORT has to be set the same in all 4.x and 5.x
+# versions of this script, else a 4.0 test run might conflict with a
+# 5.1 test run, even if different MTR_BUILD_THREAD is used. This means
+# all port numbers might not be used in this version of the script.
+#
+# Also note the limitation of ports we are allowed to hand out. This
+# differs between operating systems and configuration, see
+# http://www.ncftp.com/ncftpd/doc/misc/ephemeral_ports.html
+# But a fairly safe range seems to be 5001 - 32767
+#
+
+sub set_mtr_build_thread_ports($) {
+ my $mtr_build_thread= shift;
+
+ if ( lc($mtr_build_thread) eq 'auto' ) {
+ print "Requesting build thread... ";
+ $ENV{'MTR_BUILD_THREAD'} = $mtr_build_thread = mtr_require_unique_id_and_wait("/tmp/mysql-test-ports", 200, 299);
+ print "got ".$mtr_build_thread."\n";
+ }
+
+ # Up to two masters, up to three slaves
+ $opt_master_myport= $mtr_build_thread * 10 + 10000; # and 1
+ $opt_slave_myport= $opt_master_myport + 2; # and 3 4
+ $opt_ndbcluster_port= $opt_master_myport + 5;
+ $opt_ndbcluster_port_slave= $opt_master_myport + 6;
+ $im_port= $opt_master_myport + 7;
+ $im_mysqld1_port= $opt_master_myport + 8;
+ $im_mysqld2_port= $opt_master_myport + 9;
+
+ if ( $opt_master_myport < 5001 or $opt_master_myport + 10 >= 32767 )
+ {
+ mtr_error("MTR_BUILD_THREAD number results in a port",
+ "outside 5001 - 32767",
+ "($opt_master_myport - $opt_master_myport + 10)");
+ }
+}
+
+
+sub datadir_setup () {
# Make a list of all data_dirs
@data_dir_lst = (
@@ -1024,6 +1288,137 @@ sub snapshot_setup () {
#
##############################################################################
+
+sub collect_mysqld_features () {
+ #
+ # Execute "mysqld --no-defaults --help --verbose", that will
+ # print out version and a list of all features and settings
+ #
+ my $found_variable_list_start= 0;
+ my $spec_file= "$glob_mysql_test_dir/mysqld.spec.$$";
+ if ( mtr_run($exe_mysqld,
+ ["--no-defaults",
+ "--verbose",
+ "--help"],
+ "", "$spec_file", "$spec_file", "") != 0 )
+ {
+ mtr_error("Failed to get version and list of features from %s",
+ $exe_mysqld);
+ }
+
+ my $F= IO::File->new($spec_file) or
+ mtr_error("can't open file \"$spec_file\": $!");
+
+ while ( my $line= <$F> )
+ {
+ # First look for version
+ if ( !$mysql_version_id )
+ {
+ # Look for version
+ my $exe_name= basename($exe_mysqld);
+ mtr_verbose("exe_name: $exe_name");
+ if ( $line =~ /^\S*$exe_name\s\sVer\s([0-9]*)\.([0-9]*)\.([0-9]*)/ )
+ {
+ #print "Major: $1 Minor: $2 Build: $3\n";
+ $mysql_version_id= $1*10000 + $2*100 + $3;
+ #print "mysql_version_id: $mysql_version_id\n";
+ mtr_report("MySQL Version $1.$2.$3");
+ }
+ }
+ else
+ {
+ if (!$found_variable_list_start)
+ {
+ # Look for start of variables list
+ if ( $line =~ /[\-]+\s[\-]+/ )
+ {
+ $found_variable_list_start= 1;
+ }
+ }
+ else
+ {
+ # Put variables into hash
+ if ( $line =~ /^([\S]+)[ \t]+(.*?)\r?$/ )
+ {
+ # print "$1=\"$2\"\n";
+ $mysqld_variables{$1}= $2;
+ }
+ else
+ {
+ # The variable list is ended with a blank line
+ if ( $line =~ /^[\s]*$/ )
+ {
+ last;
+ }
+ else
+ {
+ # Send out a warning, we should fix the variables that has no
+ # space between variable name and it's value
+ # or should it be fixed width column parsing? It does not
+ # look like that in function my_print_variables in my_getopt.c
+ mtr_warning("Could not parse variable list line : $line");
+ }
+ }
+ }
+ }
+ }
+ unlink($spec_file);
+ mtr_error("Could not find version of MySQL") unless $mysql_version_id;
+ mtr_error("Could not find variabes list") unless $found_variable_list_start;
+
+}
+
+
+sub executable_setup_im () {
+
+ # Look for instance manager binary - mysqlmanager
+ $exe_im=
+ mtr_exe_maybe_exists(
+ "$glob_basedir/server-tools/instance-manager/mysqlmanager",
+ "$glob_basedir/libexec/mysqlmanager",
+ "$glob_basedir/bin/mysqlmanager",
+ "$glob_basedir/sbin/mysqlmanager");
+
+ return ($exe_im eq "");
+}
+
+sub executable_setup_ndb () {
+
+ # Look for ndb tols and binaries
+ my $ndb_path= mtr_file_exists("$glob_basedir/ndb",
+ "$glob_basedir/storage/ndb",
+ "$glob_basedir/bin");
+
+ $exe_ndbd=
+ mtr_exe_maybe_exists("$ndb_path/src/kernel/ndbd",
+ "$ndb_path/ndbd");
+ $exe_ndb_mgm=
+ mtr_exe_maybe_exists("$ndb_path/src/mgmclient/ndb_mgm",
+ "$ndb_path/ndb_mgm");
+ $exe_ndb_mgmd=
+ mtr_exe_maybe_exists("$ndb_path/src/mgmsrv/ndb_mgmd",
+ "$ndb_path/ndb_mgmd");
+ $exe_ndb_waiter=
+ mtr_exe_maybe_exists("$ndb_path/tools/ndb_waiter",
+ "$ndb_path/ndb_waiter");
+
+ # May not exist
+ $path_ndb_tools_dir= mtr_file_exists("$ndb_path/tools",
+ "$ndb_path");
+ # May not exist
+ $path_ndb_examples_dir=
+ mtr_file_exists("$ndb_path/ndbapi-examples",
+ "$ndb_path/examples");
+ # May not exist
+ $exe_ndb_example=
+ mtr_file_exists("$path_ndb_examples_dir/ndbapi_simple/ndbapi_simple");
+
+ return ( $exe_ndbd eq "" or
+ $exe_ndb_mgm eq "" or
+ $exe_ndb_mgmd eq "" or
+ $exe_ndb_waiter eq "");
+}
+
sub executable_setup () {
#
@@ -1041,164 +1436,167 @@ sub executable_setup () {
}
}
- if ( $opt_source_dist )
- {
- if ( $glob_win32 )
- {
- $path_client_bindir= mtr_path_exists("$glob_basedir/client_release",
- "$glob_basedir/client_debug",
- "$glob_basedir/client/release",
- "$glob_basedir/client/debug",
- "$glob_basedir/bin",);
- $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-max-nt",
- "$path_client_bindir/mysqld-max",
- "$path_client_bindir/mysqld-nt",
- "$path_client_bindir/mysqld",
- "$path_client_bindir/mysqld-debug",
- "$path_client_bindir/mysqld-max",
- "$glob_basedir/sql/release/mysqld",
- "$glob_basedir/sql/debug/mysqld");
- $path_language= mtr_path_exists("$glob_basedir/share/english/",
- "$glob_basedir/sql/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets",
- "$glob_basedir/sql/share/charsets/");
- $exe_my_print_defaults=
- mtr_exe_exists("$path_client_bindir/my_print_defaults",
- "$glob_basedir/extra/release/my_print_defaults",
- "$glob_basedir/extra/debug/my_print_defaults");
- $exe_perror=
- mtr_exe_exists("$path_client_bindir/perror",
- "$glob_basedir/extra/release/perror",
- "$glob_basedir/extra/debug/perror");
- }
- else
- {
- $path_client_bindir= mtr_path_exists("$glob_basedir/client");
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/sql/mysqld");
- $path_language= mtr_path_exists("$glob_basedir/sql/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/sql/share/charsets");
+ # Look for language files and charsetsdir, use same share
+ my $path_share= mtr_path_exists("$glob_basedir/share/mysql",
+ "$glob_basedir/sql/share",
+ "$glob_basedir/share");
- $exe_im= mtr_exe_exists(
- "$glob_basedir/server-tools/instance-manager/mysqlmanager");
- $exe_my_print_defaults=
- mtr_exe_exists("$glob_basedir/extra/my_print_defaults");
- $exe_perror=
- mtr_exe_exists("$glob_basedir/extra/perror");
- }
+ $path_language= mtr_path_exists("$path_share/english");
+ $path_charsetsdir= mtr_path_exists("$path_share/charsets");
- if ( $glob_use_embedded_server )
- {
- my $path_examples= "$glob_basedir/libmysqld/examples";
- $exe_mysqltest= mtr_exe_exists("$path_examples/mysqltest_embedded");
- $exe_mysql_client_test=
- mtr_exe_exists("$path_examples/mysql_client_test_embedded",
- "/usr/bin/false");
- }
- else
- {
- $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
- $exe_mysql_client_test=
- mtr_exe_exists("$glob_basedir/tests/mysql_client_test",
- "$path_client_bindir/mysql_client_test",
- "$glob_basedir/tests/release/mysql_client_test",
- "$glob_basedir/tests/debug/mysql_client_test",
- "$path_client_bindir/mysql_client_test",
- "/usr/bin/false");
- }
- $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
- $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
- $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
- $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
- $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
- $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
- $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
- $exe_mysql_fix_system_tables=
- mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables",
- "/usr/bin/false");
- $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools");
- $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm";
- $lib_udf_example=
- mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so",
- "$glob_basedir/sql/release/udf_example.dll",
- "$glob_basedir/sql/debug/udf_example.dll");
+ # Look for my_print_defaults
+ $exe_my_print_defaults=
+ mtr_exe_exists(vs_config_dirs('extra', 'my_print_defaults'),
+ "$path_client_bindir/my_print_defaults",
+ "$glob_basedir/extra/my_print_defaults");
+
+ # Look for perror
+ $exe_perror= mtr_exe_exists(vs_config_dirs('extra', 'perror'),
+ "$glob_basedir/extra/perror",
+ "$path_client_bindir/perror");
+
+ # Look for the client binaries
+ $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
+ $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
+ $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
+ $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
+ $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
+ $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
+ $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
+ if ( $mysql_version_id >= 50100 )
+ {
+ $exe_mysqlslap= mtr_exe_exists("$path_client_bindir/mysqlslap");
}
- else
+
+ if ( ! $glob_win32 )
{
- $path_client_bindir= mtr_path_exists("$glob_basedir/bin");
- $exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
- $exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
- $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
- $exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
- $exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
- $exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
- $exe_mysql= mtr_exe_exists("$path_client_bindir/mysql");
+ # Look for mysql_fix_system_table script
$exe_mysql_fix_system_tables=
- mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables",
- "$glob_basedir/scripts/mysql_fix_privilege_tables",
- "/usr/bin/false");
- $exe_my_print_defaults=
- mtr_exe_exists("$path_client_bindir/my_print_defaults");
- $exe_perror=
- mtr_exe_exists("$path_client_bindir/perror");
+ mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables",
+ "$path_client_bindir/mysql_fix_privilege_tables");
+ }
- $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/",
- "$glob_basedir/share/english/");
- $path_charsetsdir= mtr_path_exists("$glob_basedir/share/mysql/charsets",
- "$glob_basedir/share/charsets");
- if ( $glob_win32 )
- {
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/bin/mysqld-nt",
- "$glob_basedir/bin/mysqld",
- "$glob_basedir/bin/mysqld-debug",);
- }
- else
- {
- $exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld",
- "$glob_basedir/bin/mysqld");
- }
- $exe_im= mtr_exe_exists("$glob_basedir/libexec/mysqlmanager",
- "$glob_basedir/bin/mysqlmanager");
- if ( $glob_use_embedded_server )
- {
- $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest_embedded");
- $exe_mysql_client_test=
- mtr_exe_exists("$glob_basedir/tests/mysql_client_test_embedded",
- "$path_client_bindir/mysql_client_test_embedded",
- "/usr/bin/false");
- }
- else
+ if ( ! $opt_skip_ndbcluster and executable_setup_ndb())
+ {
+ mtr_warning("Could not find all required ndb binaries, " .
+ "all ndb tests will fail, use --skip-ndbcluster to " .
+ "skip testing it.");
+
+ foreach my $cluster (@{$clusters})
{
- $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest",
- "$glob_basedir/client/release/mysqltest",
- "$glob_basedir/client/debug/mysqltest");
- $exe_mysql_client_test=
- mtr_exe_exists("$path_client_bindir/mysql_client_test",
- "/usr/bin/false"); # FIXME temporary
+ $cluster->{"executable_setup_failed"}= 1;
}
+ }
- $path_ndb_tools_dir= "$glob_basedir/bin";
- $exe_ndb_mgm= "$glob_basedir/bin/ndb_mgm";
+ if ( ! $opt_skip_im and executable_setup_im())
+ {
+ mtr_warning("Could not find all required instance manager binaries, " .
+ "all im tests will fail, use --skip-im to " .
+ "continue without instance manager");
+ $instance_manager->{"executable_setup_failed"}= 1;
}
- $exe_master_mysqld= $exe_master_mysqld || $exe_mysqld;
- $exe_slave_mysqld= $exe_slave_mysqld || $exe_mysqld;
+ # Look for the udf_example library
+ $lib_udf_example=
+ mtr_file_exists(vs_config_dirs('sql', 'udf_example.dll'),
+ "$glob_basedir/sql/.libs/udf_example.so",);
+
+ # Look for mysqltest executable
+ if ( $glob_use_embedded_server )
+ {
+ $exe_mysqltest=
+ mtr_exe_exists(vs_config_dirs('libmysqld/examples', 'mysqltest_embedded'),
+ "$glob_basedir/libmysqld/examples/mysqltest_embedded",
+ "$path_client_bindir/mysqltest_embedded");
+ }
+ else
+ {
+ $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest");
+ }
+
+ # Look for mysql_client_test executable which may _not_ exist in
+ # some versions, test using it should be skipped
+ if ( $glob_use_embedded_server )
+ {
+ $exe_mysql_client_test=
+ mtr_exe_maybe_exists(
+ vs_config_dirs('libmysqld/examples', 'mysql_client_test_embedded'),
+ "$glob_basedir/libmysqld/examples/mysql_client_test_embedded");
+ }
+ else
+ {
+ $exe_mysql_client_test=
+ mtr_exe_maybe_exists(vs_config_dirs('tests', 'mysql_client_test'),
+ "$glob_basedir/tests/mysql_client_test",
+ "$glob_basedir/bin/mysql_client_test");
+ }
+}
+
- $path_ndb_data_dir= "$opt_vardir/ndbcluster-$opt_ndbcluster_port";
- $file_ndb_testrun_log= "$opt_vardir/log/ndb_testrun.log";
+sub generate_cmdline_mysqldump ($) {
+ my($mysqld) = @_;
+ return
+ "$exe_mysqldump --no-defaults -uroot " .
+ "--port=$mysqld->{'port'} " .
+ "--socket=$mysqld->{'path_sock'} --password=";
}
##############################################################################
#
-# Set environment to be used by childs of this process
+# Set environment to be used by childs of this process for
+# things that are constant duting the whole lifetime of mysql-test-run.pl
#
##############################################################################
+sub mysql_client_test_arguments()
+{
+ my $exe= $exe_mysql_client_test;
+
+ my $args;
+ mtr_init_args(\$args);
+ if ( $opt_valgrind_mysqltest )
+ {
+ valgrind_arguments($args, \$exe);
+ }
+
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--testcase");
+ mtr_add_arg($args, "--user=root");
+ mtr_add_arg($args, "--port=$master->[0]->{'port'}");
+ mtr_add_arg($args, "--socket=$master->[0]->{'path_sock'}");
+
+ if ( $mysql_version_id >= 50000 )
+ {
+ mtr_add_arg($args, "--vardir=$opt_vardir")
+ }
+
+ if ( $opt_debug )
+ {
+ mtr_add_arg($args,
+ "--debug=d:t:A,$path_vardir_trace/log/mysql_client_test.trace");
+ }
+
+ if ( $glob_use_embedded_server )
+ {
+ mtr_add_arg($args,
+ " -A --language=$path_language");
+ mtr_add_arg($args,
+ " -A --datadir=$slave->[0]->{'path_myddir'}");
+ mtr_add_arg($args,
+ " -A --character-sets-dir=$path_charsetsdir");
+ }
+
+ return join(" ", $exe, @$args);
+}
+
# Note that some env is setup in spawn/run, in "mtr_process.pl"
sub environment_setup () {
+ umask(022);
+
my @ld_library_paths;
# --------------------------------------------------------------------------
@@ -1207,11 +1605,21 @@ sub environment_setup () {
# --------------------------------------------------------------------------
if ( $opt_source_dist )
{
- push(@ld_library_paths, "$glob_basedir/libmysql/.libs/")
+ push(@ld_library_paths, "$glob_basedir/libmysql/.libs/",
+ "$glob_basedir/libmysql_r/.libs/",
+ "$glob_basedir/zlib.libs/");
}
else
{
- push(@ld_library_paths, "$glob_basedir/lib")
+ push(@ld_library_paths, "$glob_basedir/lib");
+ }
+
+ # --------------------------------------------------------------------------
+ # Add the path where libndbclient can be found
+ # --------------------------------------------------------------------------
+ if ( $glob_ndbcluster_supported )
+ {
+ push(@ld_library_paths, "$glob_basedir/storage/ndb/src/.libs");
}
# --------------------------------------------------------------------------
@@ -1223,7 +1631,7 @@ sub environment_setup () {
}
# --------------------------------------------------------------------------
- #Valgrind need to be run with debug libraries otherwise it's almost
+ # Valgrind need to be run with debug libraries otherwise it's almost
# impossible to add correct supressions, that means if "/usr/lib/debug"
# is available, it should be added to
# LD_LIBRARY_PATH
@@ -1235,17 +1643,21 @@ sub environment_setup () {
}
$ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths,
- split(':', $ENV{'LD_LIBRARY_PATH'}));
+ $ENV{'LD_LIBRARY_PATHS'} ?
+ split(':', $ENV{'LD_LIBRARY_PATH'}) : ());
mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}");
$ENV{'DYLD_LIBRARY_PATH'}= join(":", @ld_library_paths,
- split(':', $ENV{'DYLD_LIBRARY_PATH'}));
+ $ENV{'DYLD_LIBRARY_PATH'} ?
+ split(':', $ENV{'DYLD_LIBRARY_PATH'}) : ());
mtr_debug("DYLD_LIBRARY_PATH: $ENV{'DYLD_LIBRARY_PATH'}");
+
# --------------------------------------------------------------------------
# Also command lines in .opt files may contain env vars
# --------------------------------------------------------------------------
+ $ENV{'CHARSETSDIR'}= $path_charsetsdir;
$ENV{'UMASK'}= "0660"; # The octal *string*
$ENV{'UMASK_DIR'}= "0770"; # The octal *string*
$ENV{'LC_COLLATE'}= "C";
@@ -1253,43 +1665,259 @@ sub environment_setup () {
$ENV{'MYSQL_TEST_DIR'}= $glob_mysql_test_dir;
$ENV{'MYSQLTEST_VARDIR'}= $opt_vardir;
$ENV{'MYSQL_TMP_DIR'}= $opt_tmpdir;
- $ENV{'MASTER_MYSOCK'}= $master->[0]->{'path_mysock'};
- $ENV{'MASTER_MYSOCK1'}= $master->[1]->{'path_mysock'};
- $ENV{'MASTER_MYPORT'}= $master->[0]->{'path_myport'};
- $ENV{'MASTER_MYPORT1'}= $master->[1]->{'path_myport'};
- $ENV{'SLAVE_MYPORT'}= $slave->[0]->{'path_myport'};
- $ENV{'SLAVE_MYPORT1'}= $slave->[1]->{'path_myport'};
- $ENV{'SLAVE_MYPORT2'}= $slave->[2]->{'path_myport'};
-# $ENV{'MYSQL_TCP_PORT'}= '@MYSQL_TCP_PORT@'; # FIXME
- $ENV{'MYSQL_TCP_PORT'}= 3306;
-
- $ENV{'NDBCLUSTER_PORT'}= $opt_ndbcluster_port;
- $ENV{'NDB_STATUS_OK'}= "YES";
-
- $ENV{'IM_PATH_PID'}= $instance_manager->{path_pid};
- $ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid};
- $ENV{'IM_PORT'}= $instance_manager->{port};
-
- $ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock};
- $ENV{'IM_MYSQLD1_PORT'}= $instance_manager->{instances}->[0]->{port};
- $ENV{'IM_MYSQLD1_PATH_PID'}=$instance_manager->{instances}->[0]->{path_pid};
- $ENV{'IM_MYSQLD2_SOCK'}= $instance_manager->{instances}->[1]->{path_sock};
- $ENV{'IM_MYSQLD2_PORT'}= $instance_manager->{instances}->[1]->{port};
- $ENV{'IM_MYSQLD2_PATH_PID'}=$instance_manager->{instances}->[1]->{path_pid};
-
- $ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set
+ $ENV{'MASTER_MYSOCK'}= $master->[0]->{'path_sock'};
+ $ENV{'MASTER_MYSOCK1'}= $master->[1]->{'path_sock'};
+ $ENV{'MASTER_MYPORT'}= $master->[0]->{'port'};
+ $ENV{'MASTER_MYPORT1'}= $master->[1]->{'port'};
+ $ENV{'SLAVE_MYSOCK'}= $slave->[0]->{'path_sock'};
+ $ENV{'SLAVE_MYPORT'}= $slave->[0]->{'port'};
+ $ENV{'SLAVE_MYPORT1'}= $slave->[1]->{'port'};
+ $ENV{'SLAVE_MYPORT2'}= $slave->[2]->{'port'};
+ $ENV{'MYSQL_TCP_PORT'}= $mysqld_variables{'port'};
+
+ $ENV{'IM_PATH_SOCK'}= $instance_manager->{path_sock};
+ $ENV{'IM_USERNAME'}= $instance_manager->{admin_login};
+ $ENV{'IM_PASSWORD'}= $instance_manager->{admin_password};
+ $ENV{MTR_BUILD_THREAD}= $opt_mtr_build_thread;
+
+ $ENV{'EXE_MYSQL'}= $exe_mysql;
+
+
+ # ----------------------------------------------------
+ # Setup env for NDB
+ # ----------------------------------------------------
+ if ( ! $opt_skip_ndbcluster )
+ {
+ $ENV{'NDB_MGM'}= $exe_ndb_mgm;
+
+ $ENV{'NDBCLUSTER_PORT'}= $opt_ndbcluster_port;
+ $ENV{'NDBCLUSTER_PORT_SLAVE'}= $opt_ndbcluster_port_slave;
+
+ $ENV{'NDB_EXTRA_TEST'}= $opt_ndb_extra_test;
+
+ $ENV{'NDB_BACKUP_DIR'}= $clusters->[0]->{'data_dir'};
+ $ENV{'NDB_DATA_DIR'}= $clusters->[0]->{'data_dir'};
+ $ENV{'NDB_TOOLS_DIR'}= $path_ndb_tools_dir;
+ $ENV{'NDB_TOOLS_OUTPUT'}= $path_ndb_testrun_log;
+ $ENV{'NDB_CONNECTSTRING'}= $opt_ndbconnectstring;
+
+ if ( $mysql_version_id >= 50000 )
+ {
+ $ENV{'NDB_EXAMPLES_DIR'}= $path_ndb_examples_dir;
+ $ENV{'MY_NDB_EXAMPLES_BINARY'}= $exe_ndb_example;
+ }
+ $ENV{'NDB_EXAMPLES_OUTPUT'}= $path_ndb_testrun_log;
+ }
+
+ # ----------------------------------------------------
+ # Setup env for IM
+ # ----------------------------------------------------
+ if ( ! $opt_skip_im )
+ {
+ $ENV{'IM_EXE'}= $exe_im;
+ $ENV{'IM_PATH_PID'}= $instance_manager->{path_pid};
+ $ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid};
+ $ENV{'IM_PORT'}= $instance_manager->{port};
+ $ENV{'IM_DEFAULTS_PATH'}= $instance_manager->{defaults_file};
+ $ENV{'IM_PASSWORD_PATH'}= $instance_manager->{password_file};
+
+ $ENV{'IM_MYSQLD1_SOCK'}=
+ $instance_manager->{instances}->[0]->{path_sock};
+ $ENV{'IM_MYSQLD1_PORT'}=
+ $instance_manager->{instances}->[0]->{port};
+ $ENV{'IM_MYSQLD1_PATH_PID'}=
+ $instance_manager->{instances}->[0]->{path_pid};
+ $ENV{'IM_MYSQLD2_SOCK'}=
+ $instance_manager->{instances}->[1]->{path_sock};
+ $ENV{'IM_MYSQLD2_PORT'}=
+ $instance_manager->{instances}->[1]->{port};
+ $ENV{'IM_MYSQLD2_PATH_PID'}=
+ $instance_manager->{instances}->[1]->{path_pid};
+ }
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlcheck
+ # ----------------------------------------------------
+ my $cmdline_mysqlcheck=
+ "$exe_mysqlcheck --no-defaults -uroot " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} --password=";
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlcheck .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlcheck.trace";
+ }
+ $ENV{'MYSQL_CHECK'}= $cmdline_mysqlcheck;
+
+ # ----------------------------------------------------
+ # Setup env to childs can execute myqldump
+ # ----------------------------------------------------
+ my $cmdline_mysqldump= generate_cmdline_mysqldump($master->[0]);
+ my $cmdline_mysqldumpslave= generate_cmdline_mysqldump($slave->[0]);
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqldump .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqldump-master.trace";
+ $cmdline_mysqldumpslave .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqldump-slave.trace";
+ }
+ $ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
+ $ENV{'MYSQL_DUMP_SLAVE'}= $cmdline_mysqldumpslave;
+
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlslap
+ # ----------------------------------------------------
+ if ( $exe_mysqlslap )
+ {
+ my $cmdline_mysqlslap=
+ "$exe_mysqlslap -uroot " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} --password= " .
+ "--lock-directory=$opt_tmpdir";
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlslap .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlslap.trace";
+ }
+ $ENV{'MYSQL_SLAP'}= $cmdline_mysqlslap;
+ }
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlimport
+ # ----------------------------------------------------
+ my $cmdline_mysqlimport=
+ "$exe_mysqlimport -uroot " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} --password=";
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlimport .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlimport.trace";
+ }
+ $ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport;
+
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlshow
+ # ----------------------------------------------------
+ my $cmdline_mysqlshow=
+ "$exe_mysqlshow -uroot " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} --password=";
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlshow .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlshow.trace";
+ }
+ $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysqlbinlog
+ # ----------------------------------------------------
+ my $cmdline_mysqlbinlog=
+ "$exe_mysqlbinlog" .
+ " --no-defaults --local-load=$opt_tmpdir";
+ if ( $mysql_version_id >= 50000 )
+ {
+ $cmdline_mysqlbinlog .=" --character-sets-dir=$path_charsetsdir";
+ }
+
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlbinlog .=
+ " --debug=d:t:A,$path_vardir_trace/log/mysqlbinlog.trace";
+ }
+ $ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog;
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysql
+ # ----------------------------------------------------
+ my $cmdline_mysql=
+ "$exe_mysql --no-defaults --host=localhost --user=root --password= " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'} ".
+ "--character-sets-dir=$path_charsetsdir";
+
+ $ENV{'MYSQL'}= $cmdline_mysql;
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysql_client_test
+ # ----------------------------------------------------
+ $ENV{'MYSQL_CLIENT_TEST'}= mysql_client_test_arguments();
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute mysql_fix_system_tables
+ # ----------------------------------------------------
+ if ( ! $glob_win32 )
+ {
+ my $cmdline_mysql_fix_system_tables=
+ "$exe_mysql_fix_system_tables --no-defaults --host=localhost " .
+ "--user=root --password= " .
+ "--basedir=$glob_basedir --bindir=$path_client_bindir --verbose " .
+ "--port=$master->[0]->{'port'} " .
+ "--socket=$master->[0]->{'path_sock'}";
+ $ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables;
+ }
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute my_print_defaults
+ # ----------------------------------------------------
+ $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults;
+
+
+ # ----------------------------------------------------
+ # Setup env so childs can execute perror
+ # ----------------------------------------------------
+ $ENV{'MY_PERROR'}= $exe_perror;
+
+ # ----------------------------------------------------
+ # Add the path where mysqld will find udf_example.so
+ # ----------------------------------------------------
+ $ENV{'UDF_EXAMPLE_LIB'}=
+ ($lib_udf_example ? basename($lib_udf_example) : "");
+ $ENV{'LD_LIBRARY_PATH'}=
+ ($lib_udf_example ? dirname($lib_udf_example) : "") .
+ ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : "");
+
+
+ # ----------------------------------------------------
# We are nice and report a bit about our settings
- print "Using MTR_BUILD_THREAD = $ENV{MTR_BUILD_THREAD}\n";
- print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n";
- print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n";
- print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
- print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
- print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
- print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
- print "Using IM_PORT = $ENV{IM_PORT}\n";
- print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
- print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ # ----------------------------------------------------
+ if (!$opt_extern)
+ {
+ print "Using MTR_BUILD_THREAD = $ENV{MTR_BUILD_THREAD}\n";
+ print "Using MASTER_MYPORT = $ENV{MASTER_MYPORT}\n";
+ print "Using MASTER_MYPORT1 = $ENV{MASTER_MYPORT1}\n";
+ print "Using SLAVE_MYPORT = $ENV{SLAVE_MYPORT}\n";
+ print "Using SLAVE_MYPORT1 = $ENV{SLAVE_MYPORT1}\n";
+ print "Using SLAVE_MYPORT2 = $ENV{SLAVE_MYPORT2}\n";
+ if ( ! $opt_skip_ndbcluster )
+ {
+ print "Using NDBCLUSTER_PORT = $ENV{NDBCLUSTER_PORT}\n";
+ if ( ! $opt_skip_ndbcluster_slave )
+ {
+ print "Using NDBCLUSTER_PORT_SLAVE = $ENV{NDBCLUSTER_PORT_SLAVE}\n";
+ }
+ }
+ if ( ! $opt_skip_im )
+ {
+ print "Using IM_PORT = $ENV{IM_PORT}\n";
+ print "Using IM_MYSQLD1_PORT = $ENV{IM_MYSQLD1_PORT}\n";
+ print "Using IM_MYSQLD2_PORT = $ENV{IM_MYSQLD2_PORT}\n";
+ }
+ }
+
+ # Create an environment variable to make it possible
+ # to detect that valgrind is being used from test cases
+ $ENV{'VALGRIND_TEST'}= $opt_valgrind;
+
}
@@ -1308,7 +1936,7 @@ sub signal_setup () {
sub handle_int_signal () {
$SIG{INT}= 'DEFAULT'; # If we get a ^C again, we die...
mtr_warning("got INT signal, cleaning up.....");
- stop_masters_slaves();
+ stop_all_servers();
mtr_error("We die from ^C signal from user");
}
@@ -1319,16 +1947,16 @@ sub handle_int_signal () {
#
##############################################################################
-sub kill_running_server () {
+sub kill_running_servers () {
if ( $opt_fast or $glob_use_embedded_server )
{
# FIXME is embedded server really using PID files?!
- unlink($master->[0]->{'path_mypid'});
- unlink($master->[1]->{'path_mypid'});
- unlink($slave->[0]->{'path_mypid'});
- unlink($slave->[1]->{'path_mypid'});
- unlink($slave->[2]->{'path_mypid'});
+ unlink($master->[0]->{'path_pid'});
+ unlink($master->[1]->{'path_pid'});
+ unlink($slave->[0]->{'path_pid'});
+ unlink($slave->[1]->{'path_pid'});
+ unlink($slave->[2]->{'path_pid'});
}
else
{
@@ -1337,32 +1965,55 @@ sub kill_running_server () {
# started from this run of the script, this is terminating
# leftovers from previous runs.
+ if ( ! -d $opt_vardir )
+ {
+ if ( -l $opt_vardir and ! -d readlink($opt_vardir) )
+ {
+ mtr_report("Removing $opt_vardir symlink without destination");
+ unlink($opt_vardir);
+ }
+ # The "var" dir does not exist already
+ # the processes that mtr_kill_leftovers start will write
+ # their log files to var/log so it should be created
+ mkpath("$opt_vardir/log");
+ }
mtr_kill_leftovers();
-
- $using_ndbcluster_master= $opt_with_ndbcluster;
- ndbcluster_stop();
- $master->[0]->{'ndbcluster'}= 1;
- }
+ }
}
sub cleanup_stale_files () {
+ my $created_by_mem_file= "$glob_mysql_test_dir/var/created_by_mem";
+
mtr_report("Removing Stale Files");
- if ( $opt_vardir eq "$glob_mysql_test_dir/var" )
+ if ( $opt_vardir eq $default_vardir )
{
#
# Running with "var" in mysql-test dir
#
- if ( -l "$glob_mysql_test_dir/var" )
+ if ( -l $opt_vardir)
{
- # Some users creates a soft link in mysql-test/var to another area
- # - allow it
- mtr_report("WARNING: Using the 'mysql-test/var' symlink");
- rmtree("$opt_vardir/log");
- rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port");
- rmtree("$opt_vardir/run");
- rmtree("$opt_vardir/tmp");
+ # var is a symlink
+ if (-f $created_by_mem_file)
+ {
+ # Remove the directory which the link points at
+ rmtree(readlink($opt_vardir));
+ # Remove the entire "var" dir
+ rmtree("$opt_vardir/");
+ # Remove the "var" symlink
+ unlink($opt_vardir);
+ }
+ else
+ {
+ # Some users creates a soft link in mysql-test/var to another area
+ # - allow it
+ mtr_report("WARNING: Using the 'mysql-test/var' symlink");
+ rmtree("$opt_vardir/log");
+ rmtree("$opt_vardir/ndbcluster-$opt_ndbcluster_port");
+ rmtree("$opt_vardir/run");
+ rmtree("$opt_vardir/tmp");
+ }
}
else
{
@@ -1378,12 +2029,23 @@ sub cleanup_stale_files () {
# Remove the var/ dir in mysql-test dir if any
# this could be an old symlink that shouldn't be there
- rmtree("$glob_mysql_test_dir/var");
+ rmtree($default_vardir);
# Remove the "var" dir
rmtree("$opt_vardir/");
}
+ if ( $opt_mem )
+ {
+ # Runinng with var as a link to some "memory" location, normally tmpfs
+ rmtree($opt_mem);
+ mkpath($opt_mem);
+ mtr_report("Creating symlink from $opt_vardir to $opt_mem");
+ symlink($opt_mem, $opt_vardir);
+ # Put a small file to recognize this dir was created by --mem
+ mtr_tofile($created_by_mem_file, $opt_mem);
+ }
+
mkpath("$opt_vardir/log");
mkpath("$opt_vardir/run");
mkpath("$opt_vardir/tmp");
@@ -1414,6 +2076,12 @@ sub cleanup_stale_files () {
}
closedir(DIR);
}
+
+ # Remove old log files
+ foreach my $name (glob("r/*.progress r/*.log r/*.warnings"))
+ {
+ unlink($name);
+ }
}
@@ -1444,10 +2112,10 @@ sub check_running_as_root () {
}
+sub check_ssl_support ($) {
+ my $mysqld_variables= shift;
-sub check_ssl_support () {
-
- if ($opt_skip_ssl)
+ if ($opt_skip_ssl || $opt_extern)
{
mtr_report("Skipping SSL");
$opt_ssl_supported= 0;
@@ -1455,13 +2123,7 @@ sub check_ssl_support () {
return;
}
- # check ssl support by testing using a switch
- # that is only available in that case
- if ( mtr_run($exe_mysqld,
- ["--no-defaults",
- "--ssl",
- "--help"],
- "", "/dev/null", "/dev/null", "") != 0 )
+ if ( ! $mysqld_variables->{'ssl'} )
{
if ( $opt_ssl)
{
@@ -1478,120 +2140,333 @@ sub check_ssl_support () {
}
+sub check_debug_support ($) {
+ my $mysqld_variables= shift;
+
+ if ( ! $mysqld_variables->{'debug'} )
+ {
+ #mtr_report("Binaries are not debug compiled");
+ $debug_compiled_binaries= 0;
+
+ if ( $opt_debug )
+ {
+ mtr_error("Can't use --debug, binaries does not support it");
+ }
+ return;
+ }
+ mtr_report("Binaries are debug compiled");
+ $debug_compiled_binaries= 1;
+}
+
+##############################################################################
+#
+# Helper function to handle configuration-based subdirectories which Visual
+# Studio uses for storing binaries. If opt_vs_config is set, this returns
+# a path based on that setting; if not, it returns paths for the default
+# /release/ and /debug/ subdirectories.
+#
+# $exe can be undefined, if the directory itself will be used
+#
+###############################################################################
+
+sub vs_config_dirs ($$) {
+ my ($path_part, $exe) = @_;
+
+ $exe = "" if not defined $exe;
+
+ if ($opt_vs_config)
+ {
+ return ("$glob_basedir/$path_part/$opt_vs_config/$exe");
+ }
+
+ return ("$glob_basedir/$path_part/release/$exe",
+ "$glob_basedir/$path_part/debug/$exe");
+}
+
##############################################################################
#
# Start the ndb cluster
#
##############################################################################
-sub check_ndbcluster_support () {
+sub check_ndbcluster_support ($) {
+ my $mysqld_variables= shift;
if ($opt_skip_ndbcluster)
{
mtr_report("Skipping ndbcluster");
- $opt_with_ndbcluster= 0;
+ $opt_skip_ndbcluster_slave= 1;
return;
}
- if ($opt_with_ndbcluster)
+ if ( ! $mysqld_variables->{'ndb-connectstring'} )
{
- mtr_report("Using ndbcluster if necessary");
+ mtr_report("Skipping ndbcluster, mysqld not compiled with ndbcluster");
+ $opt_skip_ndbcluster= 1;
+ $opt_skip_ndbcluster_slave= 1;
return;
}
+ $glob_ndbcluster_supported= 1;
+ mtr_report("Using ndbcluster when necessary, mysqld supports it");
- # check ndbcluster support by testing using a switch
- # that is only available in that case
- if ( mtr_run($exe_mysqld,
- ["--no-defaults",
- "--ndb-use-exact-count",
- "--help"],
- "", "/dev/null", "/dev/null", "") != 0 )
+ if ( $mysql_version_id < 50100 )
{
- mtr_report("Skipping ndbcluster, mysqld not compiled with ndbcluster");
- $opt_with_ndbcluster= 0;
- return;
+ # Slave cluster is not supported until 5.1
+ $opt_skip_ndbcluster_slave= 1;
+
}
- mtr_report("Using ndbcluster if necessary, mysqld supports it");
- $opt_with_ndbcluster= 1;
+
return;
}
-sub ndbcluster_install () {
+sub ndbcluster_start_install ($) {
+ my $cluster= shift;
+
+ mtr_report("Installing $cluster->{'name'} Cluster");
+
+ mkdir($cluster->{'data_dir'});
+
+ # Create a config file from template
+ my $ndb_no_ord=512;
+ my $ndb_no_attr=2048;
+ my $ndb_con_op=105000;
+ my $ndb_dmem="80M";
+ my $ndb_imem="24M";
+ my $ndb_pbmem="32M";
+ my $nodes= $cluster->{'nodes'};
+ my $ndb_host= "localhost";
+ my $ndb_diskless= 0;
- if ( ! $opt_with_ndbcluster or $glob_use_running_ndbcluster )
+ if (!$opt_bench)
{
- return 0;
+ # Use a smaller configuration
+ if ( $mysql_version_id < 50100 )
+ {
+ # 4.1 and 5.0 is using a "larger" --small configuration
+ $ndb_no_ord=128;
+ $ndb_con_op=10000;
+ $ndb_dmem="40M";
+ $ndb_imem="12M";
+ }
+ else
+ {
+ $ndb_no_ord=32;
+ $ndb_con_op=5000;
+ $ndb_dmem="20M";
+ $ndb_imem="1M";
+ $ndb_pbmem="4M";
+ }
}
- mtr_report("Install ndbcluster");
- my $ndbcluster_opts= $opt_bench ? "" : "--small";
- if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
- ["--port=$opt_ndbcluster_port",
- "--data-dir=$opt_vardir",
- $ndbcluster_opts,
- "--initial"],
- "", "", "", "") )
+
+ my $config_file_template= "ndb/ndb_config_${nodes}_node.ini";
+ my $config_file= "$cluster->{'data_dir'}/config.ini";
+
+ open(IN, $config_file_template)
+ or mtr_error("Can't open $config_file_template: $!");
+ open(OUT, ">", $config_file)
+ or mtr_error("Can't write to $config_file: $!");
+ while (<IN>)
{
- return 1;
+ chomp;
+
+ s/CHOOSE_MaxNoOfAttributes/$ndb_no_attr/;
+ s/CHOOSE_MaxNoOfOrderedIndexes/$ndb_no_ord/;
+ s/CHOOSE_MaxNoOfConcurrentOperations/$ndb_con_op/;
+ s/CHOOSE_DataMemory/$ndb_dmem/;
+ s/CHOOSE_IndexMemory/$ndb_imem/;
+ s/CHOOSE_Diskless/$ndb_diskless/;
+ s/CHOOSE_HOSTNAME_.*/$ndb_host/;
+ s/CHOOSE_FILESYSTEM/$cluster->{'data_dir'}/;
+ s/CHOOSE_PORT_MGM/$cluster->{'port'}/;
+ if ( $mysql_version_id < 50000 )
+ {
+ my $base_port= $cluster->{'port'} + 1;
+ s/CHOOSE_PORT_TRANSPORTER/$base_port/;
+ }
+ s/CHOOSE_DiskPageBufferMemory/$ndb_pbmem/;
+
+ print OUT "$_ \n";
}
+ close OUT;
+ close IN;
+
+
+ # Start cluster with "--initial"
- $using_ndbcluster_master= 1;
- ndbcluster_stop();
- $master->[0]->{'ndbcluster'}= 1;
+ ndbcluster_start($cluster, "--initial");
return 0;
}
-sub ndbcluster_start ($) {
- my $use_ndbcluster= shift;
+sub ndbcluster_wait_started($$){
+ my $cluster= shift;
+ my $ndb_waiter_extra_opt= shift;
+ my $path_waiter_log= "$cluster->{'data_dir'}/ndb_waiter.log";
+ my $args;
+
+ mtr_init_args(\$args);
+
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--core");
+ mtr_add_arg($args, "--ndb-connectstring=%s", $cluster->{'connect_string'});
+ mtr_add_arg($args, "--timeout=60");
- if ( ! $use_ndbcluster )
+ if ($ndb_waiter_extra_opt)
{
- $using_ndbcluster_master= 0;
- return 0;
+ mtr_add_arg($args, "$ndb_waiter_extra_opt");
+ }
+
+ # Start the ndb_waiter which will connect to the ndb_mgmd
+ # and poll it for state of the ndbd's, will return when
+ # all nodes in the cluster is started
+ my $res= mtr_run($exe_ndb_waiter, $args,
+ "", $path_waiter_log, $path_waiter_log, "");
+ mtr_verbose("ndbcluster_wait_started, returns: $res") if $res;
+ return $res;
+}
+
+
+
+sub mysqld_wait_started($){
+ my $mysqld= shift;
+
+ my $res= sleep_until_file_created($mysqld->{'path_pid'},
+ $mysqld->{'start_timeout'},
+ $mysqld->{'pid'});
+ return $res == 0;
+}
+
+
+sub ndb_mgmd_wait_started($) {
+ my ($cluster)= @_;
+
+ my $retries= 100;
+ while (ndbcluster_wait_started($cluster, "--no-contact") and
+ $retries)
+ {
+ # Millisceond sleep emulated with select
+ select(undef, undef, undef, (0.1));
+
+ $retries--;
+ }
+
+ return $retries == 0;
+
+}
+
+sub ndb_mgmd_start ($) {
+ my $cluster= shift;
+
+ my $args; # Arg vector
+ my $pid= -1;
+
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--core");
+ mtr_add_arg($args, "--nodaemon");
+ mtr_add_arg($args, "--config-file=%s", "$cluster->{'data_dir'}/config.ini");
+
+
+ my $path_ndb_mgmd_log= "$cluster->{'data_dir'}/\l$cluster->{'name'}_ndb_mgmd.log";
+ $pid= mtr_spawn($exe_ndb_mgmd, $args, "",
+ $path_ndb_mgmd_log,
+ $path_ndb_mgmd_log,
+ "",
+ { append_log_file => 1 });
+
+ # FIXME Should not be needed
+ # Unfortunately the cluster nodes will fail to start
+ # if ndb_mgmd has not started properly
+ if (ndb_mgmd_wait_started($cluster))
+ {
+ mtr_error("Failed to wait for start of ndb_mgmd");
}
+
+ # Remember pid of ndb_mgmd
+ $cluster->{'pid'}= $pid;
+
+ mtr_verbose("ndb_mgmd_start, pid: $pid");
+
+ return $pid;
+}
+
+
+sub ndbd_start ($$$) {
+ my $cluster= shift;
+ my $idx= shift;
+ my $extra_args= shift;
+
+ my $args; # Arg vector
+ my $pid= -1;
+
+ mtr_init_args(\$args);
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--core");
+ mtr_add_arg($args, "--ndb-connectstring=%s", "$cluster->{'connect_string'}");
+ if ( $mysql_version_id >= 50000)
+ {
+ mtr_add_arg($args, "--character-sets-dir=%s", "$path_charsetsdir");
+ }
+ mtr_add_arg($args, "--nodaemon");
+ mtr_add_arg($args, "$extra_args");
+
+ my $nodeid= $cluster->{'ndbds'}->[$idx]->{'nodeid'};
+ my $path_ndbd_log= "$cluster->{'data_dir'}/ndb_${nodeid}.log";
+ $pid= mtr_spawn($exe_ndbd, $args, "",
+ $path_ndbd_log,
+ $path_ndbd_log,
+ "",
+ { append_log_file => 1 });
+
+ # Add pid to list of pids for this cluster
+ $cluster->{'ndbds'}->[$idx]->{'pid'}= $pid;
+
+ # Rememeber options used when starting
+ $cluster->{'ndbds'}->[$idx]->{'start_extra_args'}= $extra_args;
+ $cluster->{'ndbds'}->[$idx]->{'idx'}= $idx;
+
+ mtr_verbose("ndbd_start, pid: $pid");
+
+ return $pid;
+}
+
+
+sub ndbcluster_start ($$) {
+ my $cluster= shift;
+ my $extra_args= shift;
+
+ mtr_verbose("ndbcluster_start '$cluster->{'name'}'");
+
if ( $glob_use_running_ndbcluster )
{
- $using_ndbcluster_master= 1;
return 0;
}
- if ( $using_ndbcluster_master )
+
+ if ( $cluster->{'pid'} )
{
- # Master already started
- return 0;
+ mtr_error("Cluster '$cluster->{'name'}' already started");
}
- # FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
- if ( mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
- ["--port=$opt_ndbcluster_port",
- "--data-dir=$opt_vardir",
- "--character-sets-dir=$path_charsetsdir"],
- "", "/dev/null", "", "") )
+
+ ndb_mgmd_start($cluster);
+
+ for ( my $idx= 0; $idx < $cluster->{'nodes'}; $idx++ )
{
- mtr_error("Error ndbcluster_start");
- return 1;
+ ndbd_start($cluster, $idx, $extra_args);
}
- $using_ndbcluster_master= 1;
return 0;
}
-sub ndbcluster_stop () {
- if ( ! $using_ndbcluster_master or $glob_use_running_ndbcluster )
+sub rm_ndbcluster_tables ($) {
+ my $dir= shift;
+ foreach my $bin ( glob("$dir/mysql/apply_status*"),
+ glob("$dir/mysql/schema*"))
{
- $using_ndbcluster_master= 0;
- return;
+ unlink($bin);
}
- # FIXME, we want to _append_ output to file $file_ndb_testrun_log instead of /dev/null
- mtr_run("$glob_mysql_test_dir/ndb/ndbcluster",
- ["--port=$opt_ndbcluster_port",
- "--data-dir=$opt_vardir",
- "--stop"],
- "", "/dev/null", "", "");
-
- $using_ndbcluster_master= 0;
- return;
}
@@ -1606,10 +2481,9 @@ sub run_benchmarks ($) {
my $args;
- if ( ! $glob_use_embedded_server and ! $opt_local_master )
+ if ( ! $glob_use_embedded_server )
{
- $master->[0]->{'pid'}= mysqld_start('master',0,[],[],
- $using_ndbcluster_master);
+ mysqld_start($master->[0],[],[]);
if ( ! $master->[0]->{'pid'} )
{
mtr_error("Can't start the mysqld server");
@@ -1618,7 +2492,7 @@ sub run_benchmarks ($) {
mtr_init_args(\$args);
- mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
+ mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'});
mtr_add_arg($args, "--user=%s", $opt_user);
if ( $opt_small_bench )
@@ -1632,10 +2506,8 @@ sub run_benchmarks ($) {
mtr_add_arg($args, "--create-options=TYPE=ndb");
}
- my $benchdir= "$glob_basedir/sql-bench";
- chdir($benchdir); # FIXME check error
-
- # FIXME write shorter....
+ chdir($glob_mysql_bench_dir)
+ or mtr_error("Couldn't chdir to '$glob_mysql_bench_dir': $!");
if ( ! $benchmark )
{
@@ -1668,24 +2540,26 @@ sub run_benchmarks ($) {
#
##############################################################################
-# FIXME how to specify several suites to run? Comma separated list?
-
-
sub run_suite () {
my ($suite, $tests)= @_;
mtr_print_thick_line();
- mtr_report("Finding Tests in the '$suite' suite");
-
mtr_timer_start($glob_timers,"suite", 60 * $opt_suite_timeout);
mtr_report("Starting Tests in the '$suite' suite");
+ mtr_report_tests_not_skipped_though_disabled($tests);
+
mtr_print_header();
foreach my $tinfo ( @$tests )
{
+ if (run_testcase_check_skip_test($tinfo))
+ {
+ next;
+ }
+
mtr_timer_start($glob_timers,"testcase", 60 * $opt_testcase_timeout);
run_testcase($tinfo);
mtr_timer_stop($glob_timers,"testcase");
@@ -1697,7 +2571,7 @@ sub run_suite () {
! $glob_use_running_server and
! $glob_use_embedded_server )
{
- stop_masters_slaves();
+ stop_all_servers();
}
if ( $opt_gcov )
@@ -1722,11 +2596,14 @@ sub run_suite () {
##############################################################################
sub initialize_servers () {
+
+ datadir_setup();
+
if ( ! $glob_use_running_server )
{
- kill_running_server();
+ kill_running_servers();
- unless ( $opt_start_dirty )
+ if ( ! $opt_start_dirty )
{
cleanup_stale_files();
mysql_install_db();
@@ -1741,8 +2618,10 @@ sub initialize_servers () {
sub mysql_install_db () {
- install_db('master1', $master->[0]->{'path_myddir'});
- copy_install_db('master2', $master->[1]->{'path_myddir'});
+ install_db('master', $master->[0]->{'path_myddir'});
+
+ # FIXME check if testcase really is using second master
+ copy_install_db('master', $master->[1]->{'path_myddir'});
# Install the number of slave databses needed
for (my $idx= 0; $idx < $max_slave_num; $idx++)
@@ -1755,21 +2634,57 @@ sub mysql_install_db () {
im_prepare_env($instance_manager);
}
- if ( ndbcluster_install() )
+ my $cluster_started_ok= 1; # Assume it can be started
+
+ if ($opt_skip_ndbcluster || $glob_use_running_ndbcluster ||
+ $clusters->[0]->{executable_setup_failed})
{
- if ( $opt_force)
+ # Don't install master cluster
+ }
+ elsif (ndbcluster_start_install($clusters->[0]))
+ {
+ mtr_warning("Failed to start install of $clusters->[0]->{name}");
+ $cluster_started_ok= 0;
+ }
+
+ if ($max_slave_num == 0 ||
+ $opt_skip_ndbcluster_slave || $glob_use_running_ndbcluster_slave ||
+ $clusters->[1]->{executable_setup_failed})
+ {
+ # Don't install slave cluster
+ }
+ elsif (ndbcluster_start_install($clusters->[1]))
+ {
+ mtr_warning("Failed to start install of $clusters->[1]->{name}");
+ $cluster_started_ok= 0;
+ }
+
+ foreach my $cluster (@{$clusters})
+ {
+
+ next if !$cluster->{'pid'};
+
+ $cluster->{'installed_ok'}= 1; # Assume install suceeds
+
+ if (ndbcluster_wait_started($cluster, ""))
{
# failed to install, disable usage and flag that its no ok
- mtr_report("ndbcluster_install failed, continuing without cluster");
- $opt_with_ndbcluster= 0;
- $flag_ndb_status_ok= 0;
- $ENV{'NDB_STATUS_OK'}= "NO";
+ mtr_report("ndbcluster_install of $cluster->{'name'} failed");
+ $cluster->{"installed_ok"}= 0;
+
+ $cluster_started_ok= 0;
+ }
+ }
+
+ if ( ! $cluster_started_ok )
+ {
+ if ( $opt_force)
+ {
+ # Continue without cluster
}
else
{
- print "Aborting: Failed to install ndb cluster\n";
- print "To continue, re-run with '--force'.\n";
- mtr_exit(1);
+ mtr_error("To continue, re-run with '--force'.");
}
}
@@ -1788,6 +2703,7 @@ sub copy_install_db ($$) {
}
+
sub install_db ($$) {
my $type= shift;
my $data_dir= shift;
@@ -1832,15 +2748,16 @@ sub install_db ($$) {
mtr_add_arg($args, "--datadir=%s", $data_dir);
mtr_add_arg($args, "--skip-innodb");
mtr_add_arg($args, "--skip-ndbcluster");
- mtr_add_arg($args, "--skip-bdb");
+ mtr_add_arg($args, "--tmpdir=.");
+ mtr_add_arg($args, "--core-file");
if ( $opt_debug )
{
mtr_add_arg($args, "--debug=d:t:i:A,%s/log/bootstrap_%s.trace",
- $opt_vardir_trace, $type);
+ $path_vardir_trace, $type);
}
- if ( ! $opt_netware )
+ if ( ! $glob_netware )
{
mtr_add_arg($args, "--language=%s", $path_language);
mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
@@ -1930,12 +2847,18 @@ basedir = $path_my_basedir
server_id = $server_id
skip-stack-trace
skip-innodb
-skip-bdb
skip-ndbcluster
EOF
;
-
+ if ( $mysql_version_id < 50100 )
+ {
+ print OUT "skip-bdb\n";
+ }
print OUT "nonguarded\n" if $instance->{'nonguarded'};
+ if ( $mysql_version_id >= 50100 )
+ {
+ print OUT "log-output=FILE\n" if $instance->{'old_log_format'};
+ }
print OUT "\n";
}
@@ -1955,16 +2878,17 @@ sub im_prepare_data_dir($) {
}
+
#
# Restore snapshot of the installed slave databases
# if the snapshot exists
#
-sub restore_slave_databases () {
+sub restore_slave_databases ($) {
+ my ($num_slaves)= @_;
if ( -d $path_snapshot)
{
- # Restore the number of slave databases being used
- for (my $idx= 0; $idx < $max_slave_num; $idx++)
+ for (my $idx= 0; $idx < $num_slaves; $idx++)
{
my $data_dir= $slave->[$idx]->{'path_myddir'};
my $name= basename($data_dir);
@@ -1975,31 +2899,9 @@ sub restore_slave_databases () {
}
-##############################################################################
-#
-# Run a single test case
-#
-##############################################################################
-
-# When we get here, we have already filtered out test cases that doesn't
-# apply to the current setup, for example if we use a running server, test
-# cases that restart the server are dropped. So this function should mostly
-# be about doing things, not a lot of logic.
-
-# We don't start and kill the servers for each testcase. But some
-# testcases needs a restart, because they specify options to start
-# mysqld with. After that testcase, we need to restart again, to set
-# back the normal options.
-
-sub run_testcase ($) {
- my $tinfo= shift;
-
- my $tname= $tinfo->{'name'};
-
- mtr_tonewfile($path_current_test_log,"$tname\n"); # Always tell where we are
-
- # output current test to ndbcluster log file to enable diagnostics
- mtr_tofile($file_ndb_testrun_log,"CURRENT TEST $tname\n");
+sub run_testcase_check_skip_test($)
+{
+ my ($tinfo)= @_;
# ----------------------------------------------------------------------
# If marked to skip, just print out and return.
@@ -2012,194 +2914,241 @@ sub run_testcase ($) {
{
mtr_report_test_name($tinfo);
mtr_report_test_skipped($tinfo);
- return;
+ return 1;
}
- if ( $tinfo->{'ndb_test'} and ! $flag_ndb_status_ok )
+ if ($tinfo->{'ndb_test'})
{
- mtr_report_test_name($tinfo);
- mtr_report_test_failed($tinfo);
- return;
- }
+ foreach my $cluster (@{$clusters})
+ {
+ last if ($opt_skip_ndbcluster_slave and
+ $cluster->{'name'} eq 'Slave');
- # ----------------------------------------------------------------------
- # If not using a running servers we may need to stop and restart.
- # We restart in the case we have initiation scripts, server options
- # etc to run. But we also restart again after the test first restart
- # and test is run, to get back to normal server settings.
- #
- # To make the code a bit more clean, we actually only stop servers
- # here, and mark this to be done. Then a generic "start" part will
- # start up the needed servers again.
- # ----------------------------------------------------------------------
+ # If test needs this cluster, check binaries was found ok
+ if ( $cluster->{'executable_setup_failed'} )
+ {
+ mtr_report_test_name($tinfo);
+ $tinfo->{comment}=
+ "Failed to find cluster binaries";
+ mtr_report_test_failed($tinfo);
+ return 1;
+ }
- if ( ! $glob_use_running_server and ! $glob_use_embedded_server )
- {
- # We try to find out if we are to restart the server
- my $do_restart= 0; # Assumes we don't have to
+ # If test needs this cluster, check it was installed ok
+ if ( !$cluster->{'installed_ok'} )
+ {
+ mtr_report_test_name($tinfo);
+ $tinfo->{comment}=
+ "Cluster $cluster->{'name'} was not installed ok";
+ mtr_report_test_failed($tinfo);
+ return 1;
+ }
- if ( $tinfo->{'master_sh'} )
- {
- $do_restart= 1; # Always restart if script to run
- }
- elsif ( $opt_with_ndbcluster and $tinfo->{'ndb_test'} != $using_ndbcluster_master )
- {
- $do_restart= 1; # Restart without cluster
- }
- elsif ( $master->[0]->{'running_master_is_special'} and
- $master->[0]->{'running_master_is_special'}->{'timezone'} eq
- $tinfo->{'timezone'} and
- mtr_same_opts($master->[0]->{'running_master_is_special'}->{'master_opt'},
- $tinfo->{'master_opt'}) )
- {
- # If running master was started with special settings, but
- # the current test requuires the same ones, we *don't* restart.
- $do_restart= 0;
- }
- elsif ( $tinfo->{'master_restart'} or
- $master->[0]->{'running_master_is_special'} )
- {
- $do_restart= 1;
}
+ }
- if ( $do_restart )
+ if ( $tinfo->{'component_id'} eq 'im' )
+ {
+ # If test needs im, check binaries was found ok
+ if ( $instance_manager->{'executable_setup_failed'} )
{
- stop_masters();
- delete $master->[0]->{'running_master_is_special'}; # Forget history
+ mtr_report_test_name($tinfo);
+ $tinfo->{comment}=
+ "Failed to find MySQL manager binaries";
+ mtr_report_test_failed($tinfo);
+ return 1;
}
+ }
- # ----------------------------------------------------------------------
- # Always terminate all slaves, if any. Else we may have useless
- # reconnection attempts and error messages in case the slave and
- # master servers restart.
- # ----------------------------------------------------------------------
+ return 0;
+}
- stop_slaves();
- restore_slave_databases();
- }
- # ----------------------------------------------------------------------
- # Prepare to start masters. Even if we use embedded, we want to run
- # the preparation.
- # ----------------------------------------------------------------------
+sub do_before_run_mysqltest($)
+{
+ my $tinfo= shift;
+ my $tname= $tinfo->{'name'};
- $ENV{'TZ'}= $tinfo->{'timezone'};
+ # Remove old files produced by mysqltest
+ my $result_dir= "r";
+ if ( $opt_suite ne "main" )
+ {
+ $result_dir= "suite/$opt_suite/r";
+ }
+ unlink("$result_dir/$tname.reject");
+ unlink("$result_dir/$tname.progress");
+ unlink("$result_dir/$tname.log");
+ unlink("$result_dir/$tname.warnings");
- mtr_report_test_name($tinfo);
+ mtr_tonewfile($path_current_test_log,"$tname\n"); # Always tell where we are
+
+ # output current test to ndbcluster log file to enable diagnostics
+ mtr_tofile($path_ndb_testrun_log,"CURRENT TEST $tname\n");
mtr_tofile($master->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n");
+ if ( $master->[1]->{'pid'} )
+ {
+ mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n");
+ }
+
+ if ( $mysql_version_id < 50000 )
+ {
+ # Set envirnoment variable NDB_STATUS_OK to 1
+ # if script decided to run mysqltest cluster _is_ installed ok
+ $ENV{'NDB_STATUS_OK'} = "1";
+ }
+ elsif ( $mysql_version_id < 50100 )
+ {
+ # Set envirnoment variable NDB_STATUS_OK to YES
+ # if script decided to run mysqltest cluster _is_ installed ok
+ $ENV{'NDB_STATUS_OK'} = "YES";
+ }
+}
- # FIXME test cases that depend on each other, prevent this from
- # being at this location.
- # do_before_start_master($tname,$tinfo->{'master_sh'});
+sub do_after_run_mysqltest($)
+{
+ my $tinfo= shift;
+ my $tname= $tinfo->{'name'};
- # ----------------------------------------------------------------------
- # If any mysqld servers running died, we have to know
- # ----------------------------------------------------------------------
+ mtr_tofile($path_mysqltest_log,"CURRENT TEST $tname\n");
- mtr_record_dead_children();
+ # Save info from this testcase run to mysqltest.log
+ mtr_appendfile_to_file($path_timefile, $path_mysqltest_log)
+ if -f $path_timefile;
- # ----------------------------------------------------------------------
- # Start masters
- # ----------------------------------------------------------------------
+ # Remove the file that mysqltest writes info to
+ unlink($path_timefile);
- if ( ! $glob_use_running_server and ! $glob_use_embedded_server )
- {
- # FIXME give the args to the embedded server?!
- # FIXME what does $opt_local_master mean?!
- # FIXME split up start and check that started so that can do
- # starts in parallel, masters and slaves at the same time.
+}
- if ( $tinfo->{'component_id'} eq 'mysqld' and ! $opt_local_master )
- {
- if ( $opt_with_ndbcluster and $master->[0]->{'ndbcluster'} )
- {
- # Cluster is not started
- # Call ndbcluster_start to check if test case needs cluster
- # Start it if not already started
- $master->[0]->{'ndbcluster'}= ndbcluster_start($tinfo->{'ndb_test'});
- if ( $master->[0]->{'ndbcluster'} )
- {
- report_failure_and_restart($tinfo);
- return;
- }
- }
- if ( ! $master->[0]->{'pid'} )
- {
- # FIXME not correct location for do_before_start_master()
- do_before_start_master($tname,$tinfo->{'master_sh'});
- $master->[0]->{'pid'}=
- mysqld_start('master',0,$tinfo->{'master_opt'},[],
- $using_ndbcluster_master);
- if ( ! $master->[0]->{'pid'} )
- {
- report_failure_and_restart($tinfo);
- return;
- }
- }
- if ( $using_ndbcluster_master and ! $master->[1]->{'pid'} )
- {
- # Test needs cluster, start an extra mysqld connected to cluster
- $master->[1]->{'pid'}=
- mysqld_start('master',1,$tinfo->{'master_opt'},[],
- $using_ndbcluster_master);
- if ( ! $master->[1]->{'pid'} )
- {
- report_failure_and_restart($tinfo);
- return;
- }
- }
+sub find_testcase_skipped_reason($)
+{
+ my ($tinfo)= @_;
- if ( $tinfo->{'master_restart'} )
- {
- # Save this test case information, so next can examine it
- $master->[0]->{'running_master_is_special'}= $tinfo;
- }
- }
- elsif ( ! $opt_skip_im and $tinfo->{'component_id'} eq 'im' )
+ # Open mysqltest-time
+ my $F= IO::File->new($path_timefile) or
+ mtr_error("can't open file \"$path_timefile\": $!");
+ my $reason;
+
+ while ( my $line= <$F> )
+ {
+ # Look for "reason: <reason for skipping test>"
+ if ( $line =~ /reason: (.*)/ )
{
- # We have to create defaults file every time, in order to ensure that it
- # will be the same for each test. The problem is that test can change the
- # file (by SET/UNSET commands), so w/o recreating the file, execution of
- # one test can affect the other.
+ $reason= $1;
+ }
+ }
+
+ if ( ! $reason )
+ {
+ mtr_warning("Could not find reason for skipping test in $path_timefile");
+ $reason= "Detected by testcase(reason unknown) ";
+ }
+ $tinfo->{'comment'}= $reason;
+}
+
+
+sub analyze_testcase_failure_sync_with_master($)
+{
+ my ($tinfo)= @_;
+
+ my $args;
+ mtr_init_args(\$args);
+
+ mtr_add_arg($args, "--no-defaults");
+ mtr_add_arg($args, "--silent");
+ mtr_add_arg($args, "--skip-safemalloc");
+ mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
+ mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
+
+ mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'});
+ mtr_add_arg($args, "--port=%d", $master->[0]->{'port'});
+ mtr_add_arg($args, "--database=test");
+ mtr_add_arg($args, "--user=%s", $opt_user);
+ mtr_add_arg($args, "--password=");
- im_create_defaults_file($instance_manager);
+ # Run the test file and append output to log file
+ mtr_run_test($exe_mysqltest,$args,
+ "include/analyze_failure_sync_with_master.test",
+ "$path_timefile", "$path_timefile","",
+ { append_log_file => 1 });
+
+}
- unless ( mtr_im_start($instance_manager, $tinfo->{im_opts}) )
+sub analyze_testcase_failure($)
+{
+ my ($tinfo)= @_;
+
+ # Open mysqltest.log
+ my $F= IO::File->new($path_timefile) or
+ mtr_error("can't open file \"$path_timefile\": $!");
+
+ while ( my $line= <$F> )
+ {
+ # Look for "mysqltest: At line nnn: <error>
+ if ( $line =~ /mysqltest: At line [0-9]*: (.*)/ )
+ {
+ my $error= $1;
+ # Look for "could not sync with master"
+ if ( $error =~ /could not sync with master/ )
{
- report_failure_and_restart($tinfo);
- mtr_report("Failed to start Instance Manager. " .
- "The test '$tname' is marked as failed.");
- return;
+ analyze_testcase_failure_sync_with_master($tinfo);
}
}
+ }
+}
- # ----------------------------------------------------------------------
- # Start slaves - if needed
- # ----------------------------------------------------------------------
+##############################################################################
+#
+# Run a single test case
+#
+##############################################################################
- if ( $tinfo->{'slave_num'} )
- {
- mtr_tofile($slave->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n");
+# When we get here, we have already filtered out test cases that doesn't
+# apply to the current setup, for example if we use a running server, test
+# cases that restart the server are dropped. So this function should mostly
+# be about doing things, not a lot of logic.
+
+# We don't start and kill the servers for each testcase. But some
+# testcases needs a restart, because they specify options to start
+# mysqld with. After that testcase, we need to restart again, to set
+# back the normal options.
- do_before_start_slave($tname,$tinfo->{'slave_sh'});
+sub run_testcase ($) {
+ my $tinfo= shift;
- for ( my $idx= 0; $idx < $tinfo->{'slave_num'}; $idx++ )
- {
- if ( ! $slave->[$idx]->{'pid'} )
- {
- $slave->[$idx]->{'pid'}=
- mysqld_start('slave',$idx,
- $tinfo->{'slave_opt'}, $tinfo->{'slave_mi'},
- 0);
- if ( ! $slave->[$idx]->{'pid'} )
- {
- report_failure_and_restart($tinfo);
- return;
- }
- }
- }
+ # -------------------------------------------------------
+ # Init variables that can change between each test case
+ # -------------------------------------------------------
+
+ $ENV{'TZ'}= $tinfo->{'timezone'};
+ mtr_verbose("Starting server with timezone: $tinfo->{'timezone'}");
+
+ my $master_restart= run_testcase_need_master_restart($tinfo);
+ my $slave_restart= run_testcase_need_slave_restart($tinfo);
+
+ if ($master_restart or $slave_restart)
+ {
+ # Can't restart a running server that may be in use
+ if ( $glob_use_running_server )
+ {
+ mtr_report_test_name($tinfo);
+ $tinfo->{comment}= "Can't restart a running server";
+ mtr_report_test_skipped($tinfo);
+ return;
+ }
+
+ run_testcase_stop_servers($tinfo, $master_restart, $slave_restart);
+ }
+ my $died= mtr_record_dead_children();
+ if ($died or $master_restart or $slave_restart)
+ {
+ if (run_testcase_start_servers($tinfo))
+ {
+ mtr_report_test_name($tinfo);
+ report_failure_and_restart($tinfo);
+ return 1;
}
}
@@ -2207,31 +3156,18 @@ sub run_testcase ($) {
# If --start-and-exit or --start-dirty given, stop here to let user manually
# run tests
# ----------------------------------------------------------------------
-
if ( $opt_start_and_exit or $opt_start_dirty )
{
+ mtr_timer_stop_all($glob_timers);
mtr_report("\nServers started, exiting");
exit(0);
}
- # ----------------------------------------------------------------------
- # Run the test case
- # ----------------------------------------------------------------------
-
{
- # remove the old reject file
- if ( $opt_suite eq "main" )
- {
- unlink("r/$tname.reject");
- }
- else
- {
- unlink("suite/$opt_suite/r/$tname.reject");
- }
- unlink($path_timefile);
+ do_before_run_mysqltest($tinfo);
my $res= run_mysqltest($tinfo);
-
+ mtr_report_test_name($tinfo);
if ( $res == 0 )
{
mtr_report_test_passed($tinfo);
@@ -2239,6 +3175,9 @@ sub run_testcase ($) {
elsif ( $res == 62 )
{
# Testcase itself tell us to skip this one
+
+ # Try to get reason from mysqltest.log
+ find_testcase_skipped_reason($tinfo);
mtr_report_test_skipped($tinfo);
}
elsif ( $res == 63 )
@@ -2246,33 +3185,33 @@ sub run_testcase ($) {
$tinfo->{'timeout'}= 1; # Mark as timeout
report_failure_and_restart($tinfo);
}
- else
+ elsif ( $res == 1 )
{
- # Test case failed, if in control mysqltest returns 1
- if ( $res != 1 )
+ if ( $opt_force )
{
- mtr_tofile($path_timefile,
- "mysqltest returned unexpected code $res, " .
- "it has probably crashed");
+ analyze_testcase_failure($tinfo);
}
+ # Test case failure reported by mysqltest
+ report_failure_and_restart($tinfo);
+ }
+ else
+ {
+ # mysqltest failed, probably crashed
+ $tinfo->{comment}=
+ "mysqltest returned unexpected code $res, it has probably crashed";
report_failure_and_restart($tinfo);
}
- # Save info from this testcase run to mysqltest.log
- my $testcase_log= mtr_fromfile($path_timefile) if -f $path_timefile;
- mtr_tofile($path_mysqltest_log,"CURRENT TEST $tname\n");
- mtr_tofile($path_mysqltest_log, $testcase_log);
+
+ do_after_run_mysqltest($tinfo);
}
# ----------------------------------------------------------------------
# Stop Instance Manager if we are processing an IM-test case.
# ----------------------------------------------------------------------
-
- if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' )
+ if ( $tinfo->{'component_id'} eq 'im' and
+ !mtr_im_stop($instance_manager, $tinfo->{'name'}) )
{
- unless ( mtr_im_stop($instance_manager) )
- {
- mtr_error("Failed to stop Instance Manager.")
- }
+ mtr_error("Failed to stop Instance Manager.")
}
}
@@ -2323,8 +3262,6 @@ sub restore_installed_db ($) {
if ( -d $path_snapshot)
{
- kill_running_server ();
-
mtr_report("Restoring snapshot of databases");
foreach my $data_dir (@data_dir_lst)
@@ -2334,21 +3271,24 @@ sub restore_installed_db ($) {
rmtree("$data_dir");
mtr_copy_dir("$path_snapshot/$name", "$data_dir");
}
- if ($opt_with_ndbcluster)
+
+ # Remove the ndb_*_fs dirs for all ndbd nodes
+ # forcing a clean start of ndb
+ foreach my $cluster (@{$clusters})
{
- # Remove the ndb_*_fs dirs, forcing a clean start of ndb
- rmtree("$path_ndb_data_dir/ndb_1_fs");
- rmtree("$path_ndb_data_dir/ndb_2_fs");
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ rmtree("$ndbd->{'path_fs'}" );
+ }
}
}
else
{
- # No snapshot existed, just stop all processes
- stop_masters_slaves();
+ # No snapshot existed
+ mtr_error("No snapshot existed");
}
}
-
sub report_failure_and_restart ($) {
my $tinfo= shift;
@@ -2357,6 +3297,9 @@ sub report_failure_and_restart ($) {
print "\n";
if ( $opt_force )
{
+ # Stop all servers that are known to be running
+ stop_all_servers();
+
# Restore the snapshot of the installed test db
restore_installed_db($tinfo->{'name'});
print "Resuming Tests\n\n";
@@ -2370,7 +3313,7 @@ sub report_failure_and_restart ($) {
! $glob_use_running_server and
! $glob_use_embedded_server )
{
- stop_masters_slaves();
+ stop_all_servers();
}
mtr_exit(1);
@@ -2384,24 +3327,17 @@ sub report_failure_and_restart ($) {
##############################################################################
-# The embedded server needs the cleanup so we do some of the start work
-# but stop before actually running mysqld or anything.
-sub do_before_start_master ($$) {
- my $tname= shift;
- my $init_script= shift;
+sub do_before_start_master ($) {
+ my ($tinfo)= @_;
+
+ my $tname= $tinfo->{'name'};
+ my $init_script= $tinfo->{'master_sh'};
# FIXME what about second master.....
- # Remove stale binary logs except for 2 tests which need them FIXME here????
- if ( $tname ne "rpl_crash_binlog_ib_1b" and
- $tname ne "rpl_crash_binlog_ib_2b" and
- $tname ne "rpl_crash_binlog_ib_3b")
+ foreach my $bin ( glob("$opt_vardir/log/master*-bin*") )
{
- # FIXME we really want separate dir for binlogs
- foreach my $bin ( glob("$opt_vardir/log/master*-bin*") )
- {
- unlink($bin);
- }
+ unlink($bin);
}
# FIXME only remove the ones that are tied to this master
@@ -2421,31 +3357,23 @@ sub do_before_start_master ($$) {
# mtr_warning("$init_script exited with code $ret");
}
}
- # for gcov FIXME needed? If so we need more absolute paths
- # chdir($glob_basedir);
}
-sub do_before_start_slave ($$) {
- my $tname= shift;
- my $init_script= shift;
+sub do_before_start_slave ($) {
+ my ($tinfo)= @_;
+
+ my $tname= $tinfo->{'name'};
+ my $init_script= $tinfo->{'master_sh'};
- # Remove stale binary logs and old master.info files
- # except for too tests which need them
- if ( $tname ne "rpl_crash_binlog_ib_1b" and
- $tname ne "rpl_crash_binlog_ib_2b" and
- $tname ne "rpl_crash_binlog_ib_3b" )
+ foreach my $bin ( glob("$opt_vardir/log/slave*-bin*") )
{
- # FIXME we really want separate dir for binlogs
- foreach my $bin ( glob("$opt_vardir/log/slave*-bin*") )
- {
- unlink($bin);
- }
- # FIXME really master?!
- unlink("$slave->[0]->{'path_myddir'}/master.info");
- unlink("$slave->[0]->{'path_myddir'}/relay-log.info");
+ unlink($bin);
}
+ unlink("$slave->[0]->{'path_myddir'}/master.info");
+ unlink("$slave->[0]->{'path_myddir'}/relay-log.info");
+
# Run slave initialization shell script if one exists
if ( $init_script )
{
@@ -2464,18 +3392,17 @@ sub do_before_start_slave ($$) {
}
-sub mysqld_arguments ($$$$$$) {
+sub mysqld_arguments ($$$$$) {
my $args= shift;
- my $type= shift; # master/slave
+ my $type= shift;
my $idx= shift;
my $extra_opt= shift;
my $slave_master_info= shift;
- my $using_ndbcluster= shift;
my $sidx= ""; # Index as string, 0 is empty string
if ( $idx > 0 )
{
- $sidx= sprintf("%d", $idx); # sprintf not needed in Perl for this
+ $sidx= "$idx";
}
my $prefix= ""; # If mysqltest server arg
@@ -2485,14 +3412,18 @@ sub mysqld_arguments ($$$$$$) {
$prefix= "--server-arg=";
} else {
# We can't pass embedded server --no-defaults
- mtr_add_arg($args, "%s--no-defaults", $prefix);
+ mtr_add_arg($args, "--no-defaults");
}
mtr_add_arg($args, "%s--console", $prefix);
mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir);
mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir);
- mtr_add_arg($args, "%s--core", $prefix);
- mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
+
+ if ( $mysql_version_id >= 50000 )
+ {
+ mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
+ }
+
mtr_add_arg($args, "%s--default-character-set=latin1", $prefix);
mtr_add_arg($args, "%s--language=%s", $prefix, $path_language);
mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix);
@@ -2500,7 +3431,11 @@ sub mysqld_arguments ($$$$$$) {
if ( $opt_valgrind_mysqld )
{
mtr_add_arg($args, "%s--skip-safemalloc", $prefix);
- mtr_add_arg($args, "%s--skip-bdb", $prefix);
+
+ if ( $mysql_version_id < 50100 )
+ {
+ mtr_add_arg($args, "%s--skip-bdb", $prefix);
+ }
}
my $pidfile;
@@ -2509,26 +3444,31 @@ sub mysqld_arguments ($$$$$$) {
{
my $id= $idx > 0 ? $idx + 101 : 1;
- mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix,
- $opt_vardir, $sidx);
+ if (! $opt_skip_master_binlog)
+ {
+ mtr_add_arg($args, "%s--log-bin=%s/log/master-bin%s", $prefix,
+ $opt_vardir, $sidx);
+ }
mtr_add_arg($args, "%s--pid-file=%s", $prefix,
- $master->[$idx]->{'path_mypid'});
+ $master->[$idx]->{'path_pid'});
mtr_add_arg($args, "%s--port=%d", $prefix,
- $master->[$idx]->{'path_myport'});
+ $master->[$idx]->{'port'});
mtr_add_arg($args, "%s--server-id=%d", $prefix, $id);
mtr_add_arg($args, "%s--socket=%s", $prefix,
- $master->[$idx]->{'path_mysock'});
- mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:128M:autoextend", $prefix);
+ $master->[$idx]->{'path_sock'});
+ mtr_add_arg($args, "%s--innodb_data_file_path=ibdata1:10M:autoextend", $prefix);
mtr_add_arg($args, "%s--local-infile", $prefix);
mtr_add_arg($args, "%s--datadir=%s", $prefix,
$master->[$idx]->{'path_myddir'});
- if ( $idx > 0 )
+ if ( $idx > 0 or !$use_innodb)
{
mtr_add_arg($args, "%s--skip-innodb", $prefix);
}
- if ( $opt_skip_ndbcluster || !$using_ndbcluster)
+ my $cluster= $clusters->[$master->[$idx]->{'cluster'}];
+ if ( $opt_skip_ndbcluster ||
+ !$cluster->{'pid'})
{
mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
}
@@ -2536,7 +3476,11 @@ sub mysqld_arguments ($$$$$$) {
{
mtr_add_arg($args, "%s--ndbcluster", $prefix);
mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
- $opt_ndbconnectstring);
+ $cluster->{'connect_string'});
+ if ( $mysql_version_id >= 50100 )
+ {
+ mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
+ }
}
}
@@ -2547,25 +3491,26 @@ sub mysqld_arguments ($$$$$$) {
mtr_add_arg($args, "%s--datadir=%s", $prefix,
$slave->[$idx]->{'path_myddir'});
- # FIXME slave get this option twice?!
- mtr_add_arg($args, "%s--exit-info=256", $prefix);
mtr_add_arg($args, "%s--init-rpl-role=slave", $prefix);
- mtr_add_arg($args, "%s--log-bin=%s/log/slave%s-bin", $prefix,
- $opt_vardir, $sidx); # FIXME use own dir for binlogs
- mtr_add_arg($args, "%s--log-slave-updates", $prefix);
- # FIXME option duplicated for slave
+ if (! $opt_skip_slave_binlog)
+ {
+ mtr_add_arg($args, "%s--log-bin=%s/log/slave%s-bin", $prefix,
+ $opt_vardir, $sidx); # FIXME use own dir for binlogs
+ mtr_add_arg($args, "%s--log-slave-updates", $prefix);
+ }
+
mtr_add_arg($args, "%s--log=%s", $prefix,
$slave->[$idx]->{'path_mylog'});
mtr_add_arg($args, "%s--master-retry-count=10", $prefix);
mtr_add_arg($args, "%s--pid-file=%s", $prefix,
- $slave->[$idx]->{'path_mypid'});
+ $slave->[$idx]->{'path_pid'});
mtr_add_arg($args, "%s--port=%d", $prefix,
- $slave->[$idx]->{'path_myport'});
+ $slave->[$idx]->{'port'});
mtr_add_arg($args, "%s--relay-log=%s/log/slave%s-relay-bin", $prefix,
$opt_vardir, $sidx);
mtr_add_arg($args, "%s--report-host=127.0.0.1", $prefix);
mtr_add_arg($args, "%s--report-port=%d", $prefix,
- $slave->[$idx]->{'path_myport'});
+ $slave->[$idx]->{'port'});
mtr_add_arg($args, "%s--report-user=root", $prefix);
mtr_add_arg($args, "%s--skip-innodb", $prefix);
mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
@@ -2574,10 +3519,11 @@ sub mysqld_arguments ($$$$$$) {
# Directory where slaves find the dumps generated by "load data"
# on the server. The path need to have constant length otherwise
# test results will vary, thus a relative path is used.
+ my $slave_load_path= "../tmp";
mtr_add_arg($args, "%s--slave-load-tmpdir=%s", $prefix,
- "../tmp");
+ $slave_load_path);
mtr_add_arg($args, "%s--socket=%s", $prefix,
- $slave->[$idx]->{'path_mysock'});
+ $slave->[$idx]->{'path_sock'});
mtr_add_arg($args, "%s--set-variable=slave_net_timeout=10", $prefix);
if ( @$slave_master_info )
@@ -2594,10 +3540,27 @@ sub mysqld_arguments ($$$$$$) {
mtr_add_arg($args, "%s--master-host=127.0.0.1", $prefix);
mtr_add_arg($args, "%s--master-password=", $prefix);
mtr_add_arg($args, "%s--master-port=%d", $prefix,
- $master->[0]->{'path_myport'}); # First master
+ $master->[0]->{'port'}); # First master
mtr_add_arg($args, "%s--server-id=%d", $prefix, $slave_server_id);
mtr_add_arg($args, "%s--rpl-recovery-rank=%d", $prefix, $slave_rpl_rank);
}
+
+ if ( $opt_skip_ndbcluster_slave ||
+ $slave->[$idx]->{'cluster'} == -1 ||
+ !$clusters->[$slave->[$idx]->{'cluster'}]->{'pid'} )
+ {
+ mtr_add_arg($args, "%s--skip-ndbcluster", $prefix);
+ }
+ else
+ {
+ mtr_add_arg($args, "%s--ndbcluster", $prefix);
+ mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix,
+ $clusters->[$slave->[$idx]->{'cluster'}]->{'connect_string'});
+ if ( $mysql_version_id >= 50100 )
+ {
+ mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
+ }
+ }
} # end slave
if ( $opt_debug )
@@ -2605,12 +3568,12 @@ sub mysqld_arguments ($$$$$$) {
if ( $type eq 'master' )
{
mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/master%s.trace",
- $prefix, $opt_vardir_trace, $sidx);
+ $prefix, $path_vardir_trace, $sidx);
}
if ( $type eq 'slave' )
{
mtr_add_arg($args, "%s--debug=d:t:i:A,%s/log/slave%s.trace",
- $prefix, $opt_vardir_trace, $sidx);
+ $prefix, $path_vardir_trace, $sidx);
}
}
@@ -2618,7 +3581,6 @@ sub mysqld_arguments ($$$$$$) {
mtr_add_arg($args, "%s--key_buffer_size=1M", $prefix);
mtr_add_arg($args, "%s--sort_buffer=256K", $prefix);
mtr_add_arg($args, "%s--max_heap_table_size=1M", $prefix);
- mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);
if ( $opt_ssl_supported )
{
@@ -2649,27 +3611,22 @@ sub mysqld_arguments ($$$$$$) {
mtr_add_arg($args, "%s--user=root", $prefix);
}
- if ( $type eq 'master' )
+ my $found_skip_core= 0;
+ foreach my $arg ( @opt_extra_mysqld_opt, @$extra_opt )
{
-
- if ( ! $opt_old_master )
+ # Allow --skip-core-file to be set in master.opt file
+ if ($arg eq "--skip-core-file")
{
- mtr_add_arg($args, "%s--rpl-recovery-rank=1", $prefix);
- mtr_add_arg($args, "%s--init-rpl-role=master", $prefix);
+ $found_skip_core= 1;
}
-
- # FIXME strange,.....
- # FIXME MYSQL_MYPORT is not set anythere?!
- if ( $opt_local_master )
+ else
{
- mtr_add_arg($args, "%s--host=127.0.0.1", $prefix);
- mtr_add_arg($args, "%s--port=%s", $prefix, $ENV{'MYSQL_MYPORT'});
+ mtr_add_arg($args, "%s%s", $prefix, $arg);
}
}
-
- foreach my $arg ( @opt_extra_mysqld_opt, @$extra_opt )
+ if ( !$found_skip_core )
{
- mtr_add_arg($args, "%s%s", $prefix, $arg);
+ mtr_add_arg($args, "%s%s", $prefix, "--core-file");
}
if ( $opt_bench )
@@ -2679,7 +3636,6 @@ sub mysqld_arguments ($$$$$$) {
}
elsif ( $type eq 'master' )
{
- mtr_add_arg($args, "%s--exit-info=256", $prefix);
mtr_add_arg($args, "%s--open-files-limit=1024", $prefix);
mtr_add_arg($args, "%s--log=%s", $prefix, $master->[0]->{'path_mylog'});
}
@@ -2694,17 +3650,21 @@ sub mysqld_arguments ($$$$$$) {
#
##############################################################################
-sub mysqld_start ($$$$$) {
- my $type= shift; # master/slave
- my $idx= shift;
+sub mysqld_start ($$$) {
+ my $mysqld= shift;
my $extra_opt= shift;
my $slave_master_info= shift;
- my $using_ndbcluster= shift;
-
my $args; # Arg vector
my $exe;
my $pid= -1;
+ my $wait_for_pid_file= 1;
+
+ my $type= $mysqld->{'type'};
+ my $idx= $mysqld->{'idx'};
+
+ mtr_error("Internal error: mysqld should never be started for embedded")
+ if $glob_use_embedded_server;
if ( $type eq 'master' )
{
@@ -2716,7 +3676,7 @@ sub mysqld_start ($$$$$) {
}
else
{
- mtr_error("Unknown 'type' passed to mysqld_start");
+ mtr_error("Unknown 'type' \"$type\" passed to mysqld_start");
}
mtr_init_args(\$args);
@@ -2726,8 +3686,7 @@ sub mysqld_start ($$$$$) {
valgrind_arguments($args, \$exe);
}
- mysqld_arguments($args,$type,$idx,$extra_opt,$slave_master_info,
- $using_ndbcluster);
+ mysqld_arguments($args,$type,$idx,$extra_opt,$slave_master_info);
if ( $opt_gdb || $opt_manual_gdb)
{
@@ -2752,118 +3711,516 @@ sub mysqld_start ($$$$$) {
# Indicate the exe should not be started
$exe= undef;
}
+ else
+ {
+ # Default to not wait until pid file has been created
+ $wait_for_pid_file= 0;
+ }
- if ($exe_libtool and $opt_valgrind)
+ if ( defined $exe )
{
- # Add "libtool --mode-execute"
- # if running in valgrind(to avoid valgrinding bash)
- unshift(@$args, "--mode=execute", $exe);
- $exe= $exe_libtool;
+ $pid= mtr_spawn($exe, $args, "",
+ $mysqld->{'path_myerr'},
+ $mysqld->{'path_myerr'},
+ "",
+ { append_log_file => 1 });
}
- if ( $type eq 'master' )
+ if ( $wait_for_pid_file && !sleep_until_file_created($mysqld->{'path_pid'},
+ $mysqld->{'start_timeout'},
+ $pid))
+ {
+
+ mtr_error("Failed to start mysqld $mysqld->{'type'}");
+ }
+
+
+ # Remember pid of the started process
+ $mysqld->{'pid'}= $pid;
+
+ # Remember options used when starting
+ $mysqld->{'start_opts'}= $extra_opt;
+ $mysqld->{'start_slave_master_info'}= $slave_master_info;
+
+ mtr_verbose("mysqld pid: $pid");
+ return $pid;
+}
+
+
+sub stop_all_servers () {
+
+ print "Stopping All Servers\n";
+
+ if ( ! $opt_skip_im )
{
- if ( ! defined $exe or
- $pid= mtr_spawn($exe, $args, "",
- $master->[$idx]->{'path_myerr'},
- $master->[$idx]->{'path_myerr'},
- "",
- { append_log_file => 1 }) )
+ print "Shutting-down Instance Manager\n";
+ unless (mtr_im_stop($instance_manager, "stop_all_servers"))
{
- return sleep_until_file_created($master->[$idx]->{'path_mypid'},
- $master->[$idx]->{'start_timeout'},
- $pid);
+ mtr_error("Failed to stop Instance Manager.")
}
}
- if ( $type eq 'slave' )
+ my %admin_pids; # hash of admin processes that requests shutdown
+ my @kill_pids; # list of processes to shutdown/kill
+ my $pid;
+
+ # Start shutdown of all started masters
+ foreach my $mysqld (@{$master}, @{$slave})
{
- if ( ! defined $exe or
- $pid= mtr_spawn($exe, $args, "",
- $slave->[$idx]->{'path_myerr'},
- $slave->[$idx]->{'path_myerr'},
- "",
- { append_log_file => 1 }) )
+ if ( $mysqld->{'pid'} )
{
- return sleep_until_file_created($slave->[$idx]->{'path_mypid'},
- $master->[$idx]->{'start_timeout'},
- $pid);
+ $pid= mtr_mysqladmin_start($mysqld, "shutdown", 70);
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $mysqld->{'pid'},
+ pidfile => $mysqld->{'path_pid'},
+ sockfile => $mysqld->{'path_sock'},
+ port => $mysqld->{'port'},
+ });
+
+ $mysqld->{'pid'}= 0; # Assume we are done with it
}
}
- return 0;
+ # Start shutdown of clusters
+ foreach my $cluster (@{$clusters})
+ {
+ if ( $cluster->{'pid'} )
+ {
+ $pid= mtr_ndbmgm_start($cluster, "shutdown");
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
+ });
+
+ $cluster->{'pid'}= 0; # Assume we are done with it
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ if ( $ndbd->{'pid'} )
+ {
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0;
+ }
+ }
+ }
+ }
+
+ # Wait blocking until all shutdown processes has completed
+ mtr_wait_blocking(\%admin_pids);
+
+ # Make sure that process has shutdown else try to kill them
+ mtr_check_stop_servers(\@kill_pids);
+
+ foreach my $mysqld (@{$master}, @{$slave})
+ {
+ rm_ndbcluster_tables($mysqld->{'path_myddir'});
+ }
}
-sub stop_masters_slaves () {
+sub run_testcase_need_master_restart($)
+{
+ my ($tinfo)= @_;
- print "Ending Tests\n";
+ # We try to find out if we are to restart the master(s)
+ my $do_restart= 0; # Assumes we don't have to
- print "Shutting-down Instance Manager\n";
- unless ( mtr_im_stop($instance_manager) )
+ if ( $glob_use_embedded_server )
{
- mtr_error("Failed to stop Instance Manager.")
+ mtr_verbose("Never start or restart for embedded server");
+ return $do_restart;
+ }
+ elsif ( $tinfo->{'master_sh'} )
+ {
+ $do_restart= 1; # Always restart if script to run
+ mtr_verbose("Restart master: Always restart if script to run");
+ }
+ if ( $tinfo->{'force_restart'} )
+ {
+ $do_restart= 1; # Always restart if --force-restart in -opt file
+ mtr_verbose("Restart master: Restart forced with --force-restart");
+ }
+ elsif ( ! $opt_skip_ndbcluster and
+ !$tinfo->{'ndb_test'} and
+ $clusters->[0]->{'pid'} != 0 )
+ {
+ $do_restart= 1; # Restart without cluster
+ mtr_verbose("Restart master: Test does not need cluster");
+ }
+ elsif ( ! $opt_skip_ndbcluster and
+ $tinfo->{'ndb_test'} and
+ $clusters->[0]->{'pid'} == 0 )
+ {
+ $do_restart= 1; # Restart with cluster
+ mtr_verbose("Restart master: Test need cluster");
+ }
+ elsif( $tinfo->{'component_id'} eq 'im' )
+ {
+ $do_restart= 1;
+ mtr_verbose("Restart master: Always restart for im tests");
+ }
+ elsif ( $master->[0]->{'running_master_options'} and
+ $master->[0]->{'running_master_options'}->{'timezone'} ne
+ $tinfo->{'timezone'})
+ {
+ $do_restart= 1;
+ mtr_verbose("Restart master: Different timezone");
+ }
+ # Check that running master was started with same options
+ # as the current test requires
+ elsif (! mtr_same_opts($master->[0]->{'start_opts'},
+ $tinfo->{'master_opt'}) )
+ {
+ $do_restart= 1;
+ mtr_verbose("Restart master: running with different options '" .
+ join(" ", @{$tinfo->{'master_opt'}}) . "' != '" .
+ join(" ", @{$master->[0]->{'start_opts'}}) . "'" );
+ }
+ elsif( ! $master->[0]->{'pid'} )
+ {
+ $do_restart= 1;
+ mtr_verbose("Restart master: master is not started");
}
- print "Shutting-down MySQL daemon\n\n";
- stop_masters();
- print "Master(s) shutdown finished\n";
- stop_slaves();
- print "Slave(s) shutdown finished\n";
+ return $do_restart;
}
+sub run_testcase_need_slave_restart($)
+{
+ my ($tinfo)= @_;
+
+ # We try to find out if we are to restart the slaves
+ my $do_slave_restart= 0; # Assumes we don't have to
-sub stop_masters () {
+ if ( $glob_use_embedded_server )
+ {
+ mtr_verbose("Never start or restart for embedded server");
+ return $do_slave_restart;
+ }
+ elsif ( $max_slave_num == 0)
+ {
+ mtr_verbose("Skip slave restart: No testcase use slaves");
+ }
+ else
+ {
- my @args;
+ # Check if any slave is currently started
+ my $any_slave_started= 0;
+ foreach my $mysqld (@{$slave})
+ {
+ if ( $mysqld->{'pid'} )
+ {
+ $any_slave_started= 1;
+ last;
+ }
+ }
+
+ if ($any_slave_started)
+ {
+ mtr_verbose("Restart slave: Slave is started, always restart");
+ $do_slave_restart= 1;
+ }
+ elsif ( $tinfo->{'slave_num'} )
+ {
+ mtr_verbose("Restart slave: Test need slave");
+ $do_slave_restart= 1;
+ }
+ }
- for ( my $idx= 0; $idx < 2; $idx++ )
+ return $do_slave_restart;
+
+}
+
+# ----------------------------------------------------------------------
+# If not using a running servers we may need to stop and restart.
+# We restart in the case we have initiation scripts, server options
+# etc to run. But we also restart again after the test first restart
+# and test is run, to get back to normal server settings.
+#
+# To make the code a bit more clean, we actually only stop servers
+# here, and mark this to be done. Then a generic "start" part will
+# start up the needed servers again.
+# ----------------------------------------------------------------------
+
+sub run_testcase_stop_servers($$$) {
+ my ($tinfo, $do_restart, $do_slave_restart)= @_;
+ my $pid;
+ my %admin_pids; # hash of admin processes that requests shutdown
+ my @kill_pids; # list of processes to shutdown/kill
+
+ # Remember if we restarted for this test case (count restarts)
+ $tinfo->{'restarted'}= $do_restart;
+
+ if ( $do_restart )
{
- # FIXME if we hit ^C before fully started, this test will prevent
- # the mysqld process from being killed
- if ( $master->[$idx]->{'pid'} )
+ delete $master->[0]->{'running_master_options'}; # Forget history
+
+ # Start shutdown of all started masters
+ foreach my $mysqld (@{$master})
+ {
+ if ( $mysqld->{'pid'} )
+ {
+ $pid= mtr_mysqladmin_start($mysqld, "shutdown", 70);
+
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $mysqld->{'pid'},
+ pidfile => $mysqld->{'path_pid'},
+ sockfile => $mysqld->{'path_sock'},
+ port => $mysqld->{'port'},
+ });
+
+ $mysqld->{'pid'}= 0; # Assume we are done with it
+ }
+ }
+
+ # Start shutdown of master cluster
+ my $cluster= $clusters->[0];
+ if ( $cluster->{'pid'} )
{
- push(@args,{
- pid => $master->[$idx]->{'pid'},
- pidfile => $master->[$idx]->{'path_mypid'},
- sockfile => $master->[$idx]->{'path_mysock'},
- port => $master->[$idx]->{'path_myport'},
- });
- $master->[$idx]->{'pid'}= 0; # Assume we are done with it
+ $pid= mtr_ndbmgm_start($cluster, "shutdown");
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
+ });
+
+ $cluster->{'pid'}= 0; # Assume we are done with it
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}})
+ {
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0; # Assume we are done with it
+ }
}
}
- if ( ! $master->[0]->{'ndbcluster'} )
+ if ( $do_restart || $do_slave_restart )
{
- ndbcluster_stop();
- $master->[0]->{'ndbcluster'}= 1;
+
+ delete $slave->[0]->{'running_slave_options'}; # Forget history
+
+ # Start shutdown of all started slaves
+ foreach my $mysqld (@{$slave})
+ {
+ if ( $mysqld->{'pid'} )
+ {
+ $pid= mtr_mysqladmin_start($mysqld, "shutdown", 70);
+
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $mysqld->{'pid'},
+ pidfile => $mysqld->{'path_pid'},
+ sockfile => $mysqld->{'path_sock'},
+ port => $mysqld->{'port'},
+ });
+
+
+ $mysqld->{'pid'}= 0; # Assume we are done with it
+ }
+ }
+
+ # Start shutdown of slave cluster
+ my $cluster= $clusters->[1];
+ if ( $cluster->{'pid'} )
+ {
+ $pid= mtr_ndbmgm_start($cluster, "shutdown");
+
+ $admin_pids{$pid}= 1;
+
+ push(@kill_pids,{
+ pid => $cluster->{'pid'},
+ pidfile => $cluster->{'path_pid'}
+ });
+
+ $cluster->{'pid'}= 0; # Assume we are done with it
+
+ foreach my $ndbd (@{$cluster->{'ndbds'}} )
+ {
+ push(@kill_pids,{
+ pid => $ndbd->{'pid'},
+ pidfile => $ndbd->{'path_pid'},
+ });
+ $ndbd->{'pid'}= 0; # Assume we are done with it
+ }
+ }
}
- mtr_stop_mysqld_servers(\@args);
+ # ----------------------------------------------------------------------
+ # Shutdown has now been started and lists for the shutdown processes
+ # and the processes to be killed has been created
+ # ----------------------------------------------------------------------
+
+ # Wait blocking until all shutdown processes has completed
+ mtr_wait_blocking(\%admin_pids);
+
+
+ # Make sure that process has shutdown else try to kill them
+ mtr_check_stop_servers(\@kill_pids);
+
+ foreach my $mysqld (@{$master}, @{$slave})
+ {
+ if ( ! $mysqld->{'pid'} )
+ {
+ # Remove ndbcluster tables if server is stopped
+ rm_ndbcluster_tables($mysqld->{'path_myddir'});
+ }
+ }
}
-sub stop_slaves () {
- my $force= shift;
+#
+# run_testcase_start_servers
+#
+# Start the servers needed by this test case
+#
+# RETURN
+# 0 OK
+# 1 Start failed
+#
+
+sub run_testcase_start_servers($) {
+ my $tinfo= shift;
+ my $tname= $tinfo->{'name'};
+
+ if ( $tinfo->{'component_id'} eq 'mysqld' )
+ {
+ if ( ! $opt_skip_ndbcluster and
+ !$clusters->[0]->{'pid'} and
+ $tinfo->{'ndb_test'} )
+ {
+ # Test need cluster, cluster is not started, start it
+ ndbcluster_start($clusters->[0], "");
+ }
+
+ if ( !$master->[0]->{'pid'} )
+ {
+ # Master mysqld is not started
+ do_before_start_master($tinfo);
+
+ mysqld_start($master->[0],$tinfo->{'master_opt'},[]);
+
+ }
+
+ if ( $clusters->[0]->{'pid'} and ! $master->[1]->{'pid'} )
+ {
+ # Test needs cluster, start an extra mysqld connected to cluster
+
+ if ( $mysql_version_id >= 50100 )
+ {
+ # First wait for first mysql server to have created ndb system
+ # tables ok FIXME This is a workaround so that only one mysqld
+ # create the tables
+ if ( ! sleep_until_file_created(
+ "$master->[0]->{'path_myddir'}/mysql/apply_status.ndb",
+ $master->[0]->{'start_timeout'},
+ $master->[0]->{'pid'}))
+ {
+
+ $tinfo->{'comment'}= "Failed to create 'mysql/apply_status' table";
+ return 1;
+ }
+ }
+ mtr_tofile($master->[1]->{'path_myerr'},"CURRENT_TEST: $tname\n");
+
+ mysqld_start($master->[1],$tinfo->{'master_opt'},[]);
+ }
+
+ # Save this test case information, so next can examine it
+ $master->[0]->{'running_master_options'}= $tinfo;
+ }
+ elsif ( ! $opt_skip_im and $tinfo->{'component_id'} eq 'im' )
+ {
+ # We have to create defaults file every time, in order to ensure that it
+ # will be the same for each test. The problem is that test can change the
+ # file (by SET/UNSET commands), so w/o recreating the file, execution of
+ # one test can affect the other.
+
+ im_create_defaults_file($instance_manager);
+
+ if ( ! mtr_im_start($instance_manager, $tinfo->{im_opts}) )
+ {
+ $tinfo->{'comment'}= "Failed to start Instance Manager. ";
+ return 1;
+ }
+ }
+
+ # ----------------------------------------------------------------------
+ # Start slaves - if needed
+ # ----------------------------------------------------------------------
+ if ( $tinfo->{'slave_num'} )
+ {
+ mtr_tofile($slave->[0]->{'path_myerr'},"CURRENT_TEST: $tname\n");
+
+ restore_slave_databases($tinfo->{'slave_num'});
+
+ do_before_start_slave($tinfo);
+
+ if ( ! $opt_skip_ndbcluster_slave and
+ !$clusters->[1]->{'pid'} and
+ $tinfo->{'ndb_test'} )
+ {
+ # Test need slave cluster, cluster is not started, start it
+ ndbcluster_start($clusters->[1], "");
+ }
+
+ for ( my $idx= 0; $idx < $tinfo->{'slave_num'}; $idx++ )
+ {
+ if ( ! $slave->[$idx]->{'pid'} )
+ {
+ mysqld_start($slave->[$idx],$tinfo->{'slave_opt'},
+ $tinfo->{'slave_mi'});
+
+ }
+ }
- my @args;
+ # Save this test case information, so next can examine it
+ $slave->[0]->{'running_slave_options'}= $tinfo;
+ }
- for ( my $idx= 0; $idx < $max_slave_num; $idx++ )
+ # Wait for clusters to start
+ foreach my $cluster (@{$clusters})
{
- if ( $slave->[$idx]->{'pid'} )
+
+ next if !$cluster->{'pid'};
+
+ if (ndbcluster_wait_started($cluster, ""))
{
- push(@args,{
- pid => $slave->[$idx]->{'pid'},
- pidfile => $slave->[$idx]->{'path_mypid'},
- sockfile => $slave->[$idx]->{'path_mysock'},
- port => $slave->[$idx]->{'path_myport'},
- });
- $slave->[$idx]->{'pid'}= 0; # Assume we are done with it
+ # failed to start
+ $tinfo->{'comment'}= "Start of $cluster->{'name'} cluster failed";
+ return 1;
}
}
- mtr_stop_mysqld_servers(\@args);
+ # Wait for mysqld's to start
+ foreach my $mysqld (@{$master},@{$slave})
+ {
+
+ next if !$mysqld->{'pid'};
+
+ if (mysqld_wait_started($mysqld))
+ {
+ # failed to start
+ $tinfo->{'comment'}=
+ "Failed to start $mysqld->{'type'} mysqld $mysqld->{'idx'}";
+ return 1;
+ }
+ }
+ return 0;
}
#
@@ -2871,27 +4228,34 @@ sub stop_slaves () {
# Before a testcase, run in record mode, save result file to var
# After testcase, run and compare with the recorded file, they should be equal!
#
-sub run_check_testcase ($) {
+# RETURN VALUE
+# 0 OK
+# 1 Check failed
+#
+sub run_check_testcase ($$) {
my $mode= shift;
+ my $mysqld= shift;
+
+ my $name= "check-" . $mysqld->{'type'} . $mysqld->{'idx'};
my $args;
mtr_init_args(\$args);
mtr_add_arg($args, "--no-defaults");
mtr_add_arg($args, "--silent");
- mtr_add_arg($args, "-v");
mtr_add_arg($args, "--skip-safemalloc");
mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
+ mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
- mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
- mtr_add_arg($args, "--port=%d", $master->[0]->{'path_myport'});
+ mtr_add_arg($args, "--socket=%s", $mysqld->{'path_sock'});
+ mtr_add_arg($args, "--port=%d", $mysqld->{'port'});
mtr_add_arg($args, "--database=test");
mtr_add_arg($args, "--user=%s", $opt_user);
mtr_add_arg($args, "--password=");
mtr_add_arg($args, "-R");
- mtr_add_arg($args, "$opt_vardir/tmp/check-testcase.result");
+ mtr_add_arg($args, "$opt_vardir/tmp/$name.result");
if ( $mode eq "before" )
{
@@ -2901,116 +4265,61 @@ sub run_check_testcase ($) {
my $res = mtr_run_test($exe_mysqltest,$args,
"include/check-testcase.test", "", "", "");
- if ( $res == 1 and $mode = "after")
+ if ( $res == 1 and $mode eq "after")
{
mtr_run("diff",["-u",
- "$opt_vardir/tmp/check-testcase.result",
- "$opt_vardir/tmp/check-testcase.reject"],
+ "$opt_vardir/tmp/$name.result",
+ "$opt_vardir/tmp/$name.reject"],
"", "", "", "");
}
elsif ( $res )
{
mtr_error("Could not execute 'check-testcase' $mode testcase");
}
+ return $res;
}
+##############################################################################
+#
+# Report the features that were compiled in
+#
+##############################################################################
-sub run_mysqltest ($) {
- my $tinfo= shift;
-
- my $cmdline_mysqlcheck= "$exe_mysqlcheck --no-defaults -uroot " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'} --password=";
- if ( $opt_debug )
- {
- $cmdline_mysqlcheck .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlcheck.trace";
- }
-
- my $cmdline_mysqldump= "$exe_mysqldump --no-defaults -uroot " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'} --password=";
- if ( $opt_debug )
- {
- $cmdline_mysqldump .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqldump.trace";
- }
- my $cmdline_mysqlimport= "$exe_mysqlimport -uroot " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'} --password=";
- if ( $opt_debug )
- {
- $cmdline_mysqlimport .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlimport.trace";
- }
-
- my $cmdline_mysqlshow= "$exe_mysqlshow -uroot " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'} --password=";
- if ( $opt_debug )
- {
- $cmdline_mysqlshow .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlshow.trace";
- }
-
- my $cmdline_mysqlbinlog=
- "$exe_mysqlbinlog" .
- " --no-defaults --local-load=$opt_tmpdir" .
- " --character-sets-dir=$path_charsetsdir";
+sub run_report_features () {
+ my $args;
- if ( $opt_debug )
+ if ( ! $glob_use_embedded_server )
{
- $cmdline_mysqlbinlog .=
- " --debug=d:t:A,$opt_vardir_trace/log/mysqlbinlog.trace";
- }
-
- my $cmdline_mysql=
- "$exe_mysql --host=localhost --user=root --password= " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'} ".
- "--character-sets-dir=$path_charsetsdir";
-
- my $cmdline_mysql_client_test=
- "$exe_mysql_client_test --no-defaults --testcase --user=root --silent " .
- "--port=$master->[0]->{'path_myport'} " .
- "--vardir=$opt_vardir " .
- "--socket=$master->[0]->{'path_mysock'}";
+ mysqld_start($master->[0],[],[]);
+ if ( ! $master->[0]->{'pid'} )
+ {
+ mtr_error("Can't start the mysqld server");
+ }
+ mysqld_wait_started($master->[0]);
+ }
+
+ my $tinfo = {};
+ $tinfo->{'name'} = 'report features';
+ $tinfo->{'result_file'} = undef;
+ $tinfo->{'component_id'} = 'mysqld';
+ $tinfo->{'path'} = 'include/report-features.test';
+ $tinfo->{'timezone'}= "GMT-3";
+ $tinfo->{'slave_num'} = 0;
+ $tinfo->{'master_opt'} = [];
+ $tinfo->{'slave_opt'} = [];
+ $tinfo->{'slave_mi'} = [];
+ $tinfo->{'comment'} = 'report server features';
+ run_mysqltest($tinfo);
- if ( $glob_use_embedded_server )
+ if ( ! $glob_use_embedded_server )
{
- $cmdline_mysql_client_test.=
- " -A --language=$path_language" .
- " -A --datadir=$slave->[0]->{'path_myddir'}" .
- " -A --character-sets-dir=$path_charsetsdir";
+ stop_all_servers();
}
+}
- my $cmdline_mysql_fix_system_tables=
- "$exe_mysql_fix_system_tables --no-defaults --host=localhost --user=root --password= " .
- "--basedir=$glob_basedir --bindir=$path_client_bindir --verbose " .
- "--port=$master->[0]->{'path_myport'} " .
- "--socket=$master->[0]->{'path_mysock'}";
-
- $ENV{'MYSQL'}= $cmdline_mysql;
- $ENV{'MYSQL_CHECK'}= $cmdline_mysqlcheck;
- $ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
- $ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport;
- $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
- $ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog;
- $ENV{'MYSQL_FIX_SYSTEM_TABLES'}= $cmdline_mysql_fix_system_tables;
- $ENV{'MYSQL_CLIENT_TEST'}= $cmdline_mysql_client_test;
- $ENV{'CHARSETSDIR'}= $path_charsetsdir;
- $ENV{'MYSQL_MY_PRINT_DEFAULTS'}= $exe_my_print_defaults;
- $ENV{'UDF_EXAMPLE_LIB'}=
- ($lib_udf_example ? basename($lib_udf_example) : "");
- $ENV{'MY_PERROR'}= $exe_perror;
-
- $ENV{'NDB_MGM'}= $exe_ndb_mgm;
- $ENV{'NDB_BACKUP_DIR'}= $path_ndb_data_dir;
- $ENV{'NDB_DATA_DIR'}= $path_ndb_data_dir;
- $ENV{'NDB_TOOLS_DIR'}= $path_ndb_tools_dir;
- $ENV{'NDB_TOOLS_OUTPUT'}= $file_ndb_testrun_log;
- $ENV{'NDB_CONNECTSTRING'}= $opt_ndbconnectstring;
+sub run_mysqltest ($) {
+ my ($tinfo)= @_;
my $exe= $exe_mysqltest;
my $args;
@@ -3018,9 +4327,9 @@ sub run_mysqltest ($) {
mtr_add_arg($args, "--no-defaults");
mtr_add_arg($args, "--silent");
- mtr_add_arg($args, "-v");
mtr_add_arg($args, "--skip-safemalloc");
mtr_add_arg($args, "--tmpdir=%s", $opt_tmpdir);
+ mtr_add_arg($args, "--character-sets-dir=%s", $path_charsetsdir);
if ($tinfo->{'component_id'} eq 'im')
{
@@ -3031,8 +4340,8 @@ sub run_mysqltest ($) {
}
else # component_id == mysqld
{
- mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_mysock'});
- mtr_add_arg($args, "--port=%d", $master->[0]->{'path_myport'});
+ mtr_add_arg($args, "--socket=%s", $master->[0]->{'path_sock'});
+ mtr_add_arg($args, "--port=%d", $master->[0]->{'port'});
mtr_add_arg($args, "--database=test");
mtr_add_arg($args, "--user=%s", $opt_user);
mtr_add_arg($args, "--password=");
@@ -3088,7 +4397,8 @@ sub run_mysqltest ($) {
if ( $opt_debug )
{
- mtr_add_arg($args, "--debug=d:t:A,%s/log/mysqltest.trace", $opt_vardir_trace);
+ mtr_add_arg($args, "--debug=d:t:A,%s/log/mysqltest.trace",
+ $path_vardir_trace);
}
if ( $opt_ssl_supported )
@@ -3101,16 +4411,14 @@ sub run_mysqltest ($) {
$glob_mysql_test_dir);
}
- # Turn on SSL for all test cases
if ( $opt_ssl )
{
- mtr_add_arg($args, "--ssl",
- $glob_mysql_test_dir);
+ # Turn on SSL for _all_ test cases if option --ssl was used
+ mtr_add_arg($args, "--ssl");
}
elsif ( $opt_ssl_supported )
{
- mtr_add_arg($args, "--skip-ssl",
- $glob_mysql_test_dir);
+ mtr_add_arg($args, "--skip-ssl");
}
# ----------------------------------------------------------------------
@@ -3119,7 +4427,7 @@ sub run_mysqltest ($) {
if ( $glob_use_embedded_server )
{
- mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[],0);
+ mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[]);
}
# ----------------------------------------------------------------------
@@ -3145,8 +4453,10 @@ sub run_mysqltest ($) {
mtr_add_arg($args, "--test-file");
mtr_add_arg($args, $tinfo->{'path'});
- mtr_add_arg($args, "--result-file");
- mtr_add_arg($args, $tinfo->{'result_file'});
+ if ( defined $tinfo->{'result_file'} ) {
+ mtr_add_arg($args, "--result-file");
+ mtr_add_arg($args, $tinfo->{'result_file'});
+ }
if ( $opt_record )
{
@@ -3166,24 +4476,32 @@ sub run_mysqltest ($) {
debugger_arguments(\$args, \$exe, "client");
}
- if ($exe_libtool and $opt_valgrind)
- {
- # Add "libtool --mode-execute" before the test to execute
- # if running in valgrind(to avoid valgrinding bash)
- unshift(@$args, "--mode=execute", $exe);
- $exe= $exe_libtool;
- }
-
if ( $opt_check_testcases )
{
- run_check_testcase("before");
+ foreach my $mysqld (@{$master}, @{$slave})
+ {
+ if ($mysqld->{'pid'})
+ {
+ run_check_testcase("before", $mysqld);
+ }
+ }
}
my $res = mtr_run_test($exe,$args,"","",$path_timefile,"");
if ( $opt_check_testcases )
{
- run_check_testcase("after");
+ foreach my $mysqld (@{$master}, @{$slave})
+ {
+ if ($mysqld->{'pid'})
+ {
+ if (run_check_testcase("after", $mysqld))
+ {
+ # Check failed, mark the test case with that info
+ $tinfo->{'check_testcase_failed'}= 1;
+ }
+ }
+ }
}
return $res;
@@ -3362,12 +4680,20 @@ sub valgrind_arguments {
my $args= shift;
my $exe= shift;
- mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option
- mtr_add_arg($args, "--alignment=8");
- mtr_add_arg($args, "--leak-check=yes");
- mtr_add_arg($args, "--num-callers=16");
- mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir)
- if -f "$glob_mysql_test_dir/valgrind.supp";
+ if ( $opt_callgrind)
+ {
+ mtr_add_arg($args, "--tool=callgrind");
+ mtr_add_arg($args, "--base=$opt_vardir/log");
+ }
+ else
+ {
+ mtr_add_arg($args, "--tool=memcheck"); # From >= 2.1.2 needs this option
+ mtr_add_arg($args, "--alignment=8");
+ mtr_add_arg($args, "--leak-check=yes");
+ mtr_add_arg($args, "--num-callers=16");
+ mtr_add_arg($args, "--suppressions=%s/valgrind.supp", $glob_mysql_test_dir)
+ if -f "$glob_mysql_test_dir/valgrind.supp";
+ }
# Add valgrind options, can be overriden by user
mtr_add_arg($args, '%s', $_) for (split(' ', $opt_valgrind_options));
@@ -3375,6 +4701,14 @@ sub valgrind_arguments {
mtr_add_arg($args, $$exe);
$$exe= $opt_valgrind_path || "valgrind";
+
+ if ($exe_libtool)
+ {
+ # Add "libtool --mode-execute" before the test to execute
+ # if running in valgrind(to avoid valgrinding bash)
+ unshift(@$args, "--mode=execute", $$exe);
+ $$exe= $exe_libtool;
+ }
}
@@ -3394,9 +4728,7 @@ sub usage ($) {
print STDERR <<HERE;
-mysql-test-run [ OPTIONS ] [ TESTCASE ]
-
-FIXME when is TESTCASE arg used or not?!
+$0 [ OPTIONS ] [ TESTCASE ]
Options to control what engine/variation to run
@@ -3409,33 +4741,52 @@ Options to control what engine/variation to run
compress Use the compressed protocol between client and server
ssl Use ssl protocol between client and server
skip-ssl Dont start server with support for ssl connections
- bench Run the benchmark suite FIXME
- small-bench FIXME
+ bench Run the benchmark suite
+ small-bench Run the benchmarks with --small-tests --small-tables
+ with-ndbcluster Use cluster as default table type for benchmark
+ vs-config Visual Studio configuration used to create executables
+ (default: MTR_VS_CONFIG environment variable)
Options to control directories to use
- vardir=DIR The directory where files generated from the test run
- is stored(default: ./var). Specifying a ramdisk or tmpfs
- will speed up tests.
+ benchdir=DIR The directory where the benchmark suite is stored
+ (default: ../../mysql-bench)
tmpdir=DIR The directory where temporary files are stored
(default: ./var/tmp).
+ vardir=DIR The directory where files generated from the test run
+ is stored (default: ./var). Specifying a ramdisk or
+ tmpfs will speed up tests.
+ mem[=DIR] Run testsuite in "memory" using tmpfs or ramdisk
+ Attempts to use DIR first if specified else
+ uses as builtin list of standard locations
+ for tmpfs (/dev/shm)
+ The option can also be set using environment
+ variable MTR_MEM=[DIR]
Options to control what test suites or cases to run
force Continue to run the suite after failure
- with-ndbcluster Use cluster, and enable test cases that requres it
- skip-ndb[cluster] Skip the ndb test cases, don't start cluster
+ with-ndbcluster-only Run only tests that include "ndb" in the filename
+ skip-ndb[cluster] Skip all tests that need cluster
+ skip-ndb[cluster]-slave Skip all tests that need a slave cluster
+ ndb-extra Run extra tests from ndb directory
do-test=PREFIX Run test cases which name are prefixed with PREFIX
start-from=PREFIX Run test cases starting from test prefixed with PREFIX
suite=NAME Run the test suite named NAME. The default is "main"
skip-rpl Skip the replication test cases.
skip-im Don't start IM, and skip the IM test cases
skip-test=PREFIX Skip test cases which name are prefixed with PREFIX
+ big-test Pass "--big-test" to mysqltest which will set the
+ environment variable BIG_TEST, which can be checked
+ from test cases.
Options that specify ports
master_port=PORT Specify the port number used by the first master
slave_port=PORT Specify the port number used by the first slave
- ndbcluster_port=PORT Specify the port number used by cluster
+ ndbcluster-port=PORT Specify the port number used by cluster
+ ndbcluster-port-slave=PORT Specify the port number used by slave cluster
+ mtr-build-thread=# Specify unique collection of ports. Can also be set by
+ setting the environment variable MTR_BUILD_THREAD.
Options for test case authoring
@@ -3449,22 +4800,26 @@ Options that pass on options
Options to run test on running server
extern Use running server for tests FIXME DANGEROUS
- ndbconnectstring=STR Use running cluster, and connect using STR
+ ndb-connectstring=STR Use running cluster, and connect using STR
+ ndb-connectstring-slave=STR Use running slave cluster, and connect using STR
user=USER User for connect to server
Options for debugging the product
- gdb Start the mysqld(s) in gdb
- manual-gdb Let user manually start mysqld in gdb, before running test(s)
- manual-debug Let user manually start mysqld in debugger, before running test(s)
+ client-ddd Start mysqltest client in ddd
+ client-debugger=NAME Start mysqltest in the selected debugger
client-gdb Start mysqltest client in gdb
ddd Start mysqld in ddd
- client-ddd Start mysqltest client in ddd
+ debug Dump trace output for all servers and client programs
debugger=NAME Start mysqld in the selected debugger
- client-debugger=NAME Start mysqltest in the selected debugger
- strace-client FIXME
+ gdb Start the mysqld(s) in gdb
+ manual-debug Let user manually start mysqld in debugger, before
+ running test(s)
+ manual-gdb Let user manually start mysqld in gdb, before running
+ test(s)
master-binary=PATH Specify the master "mysqld" to use
slave-binary=PATH Specify the slave "mysqld" to use
+ strace-client Create strace output for mysqltest client
Options for coverage, profiling etc
@@ -3473,16 +4828,19 @@ Options for coverage, profiling etc
valgrind Run the "mysqltest" and "mysqld" executables using
valgrind with options($default_valgrind_options)
valgrind-all Synonym for --valgrind
- valgrind-mysqltest Run the "mysqltest" executable with valgrind
+ valgrind-mysqltest Run the "mysqltest" and "mysql_client_test" executable
+ with valgrind
valgrind-mysqld Run the "mysqld" executable with valgrind
valgrind-options=ARGS Options to give valgrind, replaces default options
valgrind-path=[EXE] Path to the valgrind executable
+ callgrind Instruct valgrind to use callgrind
Misc options
comment=STR Write STR to the output
+ notimer Don't show test case execution time
script-debug Debug this script itself
- timer Show test case execution time
+ verbose More verbose output
start-and-exit Only initialize and start the servers, using the
startup settings for the specified test case (if any)
start-dirty Only start the servers (without initialization) for
@@ -3492,29 +4850,26 @@ Misc options
help Get this help text
unified-diff | udiff When presenting differences, use unified diff
- testcase-timeout=MINUTES Max test case run time (default 5)
- suite-timeout=MINUTES Max test suite run time (default 120)
+ testcase-timeout=MINUTES Max test case run time (default $default_testcase_timeout)
+ suite-timeout=MINUTES Max test suite run time (default $default_suite_timeout)
+
Deprecated options
with-openssl Deprecated option for ssl
Options not yet described, or that I want to look into more
-
- big-test
- debug
- local
- local-master
- netware
- old-master
- sleep=SECONDS
- socket=PATH
- user-test=s
- wait-timeout=SECONDS
- warnings
- log-warnings
+ local
+ netware
+ sleep=SECONDS
+ socket=PATH
+ user-test=s
+ wait-timeout=SECONDS
+ warnings
+ log-warnings
HERE
mtr_exit(1);
}
+
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 590885b3d46..a81a3b8b607 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -123,7 +123,7 @@ find_valgrind()
fi
# >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr
valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && FIND_VALGRIND="$FIND_VALGRIND --tool=memcheck"
- FIND_VALGRIND="$FIND_VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$CWD/valgrind.supp"
+ FIND_VALGRIND="$FIND_VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$MYSQL_TEST_DIR/valgrind.supp"
}
# No paths below as we can't be sure where the program is!
@@ -174,18 +174,24 @@ fi
# Misc. Definitions
#--
-if [ -d ../sql ] ; then
+# BASEDIR is always above mysql-test directory ...
+MYSQL_TEST_DIR=`pwd`
+cd ..
+
+if [ -d ./sql ] ; then
SOURCE_DIST=1
else
BINARY_DIST=1
-fi
-#BASEDIR is always one above mysql-test directory
-CWD=`pwd`
-cd ..
+ # ... one level for tar.gz, two levels for a RPM installation
+ if [ ! -f ./bin/mysql_upgrade ] ; then
+ # Has to be RPM installation
+ cd ..
+ fi
+fi
BASEDIR=`pwd`
-cd $CWD
-MYSQL_TEST_DIR=$BASEDIR/mysql-test
+
+cd $MYSQL_TEST_DIR
MYSQL_TEST_WINDIR=$MYSQL_TEST_DIR
MYSQLTEST_VARDIR=$MYSQL_TEST_DIR/var
export MYSQL_TEST_DIR MYSQL_TEST_WINDIR MYSQLTEST_VARDIR
@@ -744,8 +750,15 @@ else
if test -x "$BASEDIR/libexec/mysqld"
then
MYSQLD="$VALGRIND $BASEDIR/libexec/mysqld"
- else
+ elif test -x "$BASEDIR/bin/mysqld"
+ then
MYSQLD="$VALGRIND $BASEDIR/bin/mysqld"
+ elif test -x "$BASEDIR/sbin/mysqld"
+ then
+ MYSQLD="$VALGRIND $BASEDIR/sbin/mysqld"
+ else
+ $ECHO "Fatal error: Cannot find program mysqld in $BASEDIR/{libexec,bin,sbin}" 1>&2
+ exit 1
fi
CLIENT_BINDIR="$BASEDIR/bin"
if test -d "$BASEDIR/tests"
@@ -1390,7 +1403,7 @@ start_master()
then
$ECHO "set args $master_args" > $GDB_MASTER_INIT$1
$ECHO "To start gdb for the master , type in another window:"
- $ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT$1 $MASTER_MYSQLD"
+ $ECHO "cd $MYSQL_TEST_DIR ; gdb -x $GDB_MASTER_INIT$1 $MASTER_MYSQLD"
wait_for_master=1500
else
( $ECHO set args $master_args;
@@ -1508,7 +1521,7 @@ start_slave()
then
$ECHO "set args $slave_args" > $GDB_SLAVE_INIT
echo "To start gdb for the slave, type in another window:"
- echo "cd $CWD ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD"
+ echo "cd $MYSQL_TEST_DIR ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD"
wait_for_slave=1500
else
( $ECHO set args $slave_args;
@@ -1750,10 +1763,13 @@ run_testcase ()
--result-file=*)
result_file=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--result-file=;;"`
result_file="r/$result_file.result"
- # Note that this must be set to space, not "" for test-reset to
-# work
+ # Note that this must be set to space, not "" for test-reset to work
EXTRA_MASTER_OPT=" "
;;
+ --force-restart)
+ # Note that this must be set to space, not "" for test-reset to work
+ EXTRA_MASTER_OPT=" "
+ ;;
esac
stop_master
stop_master 1
@@ -2071,12 +2087,15 @@ then
# Remove files that can cause problems
$RM -rf $MYSQL_TEST_DIR/var/ndbcluster
- $RM -f $MYSQL_TEST_DIR/var/run/* $MYSQL_TEST_DIR/var/tmp/*
+ $RM -rf $MYSQL_TEST_DIR/var/run/* $MYSQL_TEST_DIR/var/tmp/*
# Remove old berkeley db log files that can confuse the server
$RM -f $MASTER_MYDDIR/log.*
$RM -f $MASTER_MYDDIR"1"/log.*
+ # Remove old log and reject files
+ $RM -f r/*.reject r/*.progress r/*.log r/*.warnings
+
wait_for_master=$SLEEP_TIME_FOR_FIRST_MASTER
wait_for_slave=$SLEEP_TIME_FOR_FIRST_SLAVE
$ECHO "Installing Test Databases"
diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result
index 4c565f4f1b1..60806e7393e 100644
--- a/mysql-test/r/check.result
+++ b/mysql-test/r/check.result
@@ -1,6 +1,6 @@
drop table if exists t1;
create table t1(n int not null, key(n), key(n), key(n), key(n));
- check table t1 extended;
+check table t1 extended;
insert into t1 values (200000);
Table Op Msg_type Msg_text
test.t1 check status OK
diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result
index da0ca8ddba1..c141b255716 100644
--- a/mysql-test/r/compare.result
+++ b/mysql-test/r/compare.result
@@ -46,6 +46,10 @@ create table t1 (a tinyint(1),b binary(1));
insert into t1 values (0x01,0x01);
select * from t1 where a=b;
a b
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: ''
select * from t1 where a=b and b=0x01;
a b
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: ''
drop table if exists t1;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 5f885ad199b..1dcbc693597 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -767,11 +767,5 @@ t1 CREATE TABLE `t1` (
`i` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 MAX_ROWS=4294967295
drop table t1;
-create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb
-character set utf8 collate utf8_general_ci;
-Warnings:
-Warning 1071 Specified key was too long; max key length is 765 bytes
-insert into t1 values('aaa');
-drop table t1;
create table t1 (upgrade int);
drop table t1;
diff --git a/mysql-test/r/csv.result b/mysql-test/r/csv.result
index f3e91a663b8..8ec79e9d7a9 100644
--- a/mysql-test/r/csv.result
+++ b/mysql-test/r/csv.result
@@ -4913,8 +4913,7 @@ bonfire
Colombo
nondecreasing
DROP TABLE t1;
-ALTER TABLE t2 RENAME t1
-#;
+ALTER TABLE t2 RENAME t1;
DROP TABLE t1;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
diff --git a/mysql-test/r/ctype_cp1250_ch.result b/mysql-test/r/ctype_cp1250_ch.result
index b55849e4e12..73f415732cd 100644
--- a/mysql-test/r/ctype_cp1250_ch.result
+++ b/mysql-test/r/ctype_cp1250_ch.result
@@ -1,3 +1,4 @@
+DROP TABLE IF EXISTS t1;
SHOW COLLATION LIKE 'cp1250_czech_cs';
Collation Charset Id Default Compiled Sortlen
cp1250_czech_cs cp1250 34 Yes 2
diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result
index 4e145346081..125e0edd1f9 100644
--- a/mysql-test/r/ctype_recoding.result
+++ b/mysql-test/r/ctype_recoding.result
@@ -171,8 +171,8 @@ create table t1 (a char(10) character set koi8r, b text character set koi8r);
insert into t1 values ('test','test');
insert into t1 values ('ÊÃÕË','ÊÃÕË');
Warnings:
-Warning 1265 Data truncated for column 'a' at row 1
-Warning 1265 Data truncated for column 'b' at row 1
+Warning 1366 Incorrect string value: '\xCA\xC3\xD5\xCB' for column 'a' at row 1
+Warning 1366 Incorrect string value: '\xCA\xC3\xD5\xCB' for column 'b' at row 1
drop table t1;
set names koi8r;
create table t1 (a char(10) character set cp1251);
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 76fcbbeb9f8..e32c1e8aae0 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -723,6 +723,28 @@ lily
river
drop table t1;
deallocate prepare stmt;
+create table t1 (
+a char(10) unicode not null,
+index a (a)
+) engine=myisam;
+insert into t1 values (repeat(0x201f, 10));
+insert into t1 values (repeat(0x2020, 10));
+insert into t1 values (repeat(0x2021, 10));
+explain select hex(a) from t1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 20 NULL 3 Using index
+select hex(a) from t1 order by a;
+hex(a)
+201F201F201F201F201F201F201F201F201F201F
+2020202020202020202020202020202020202020
+2021202120212021202120212021202120212021
+alter table t1 drop index a;
+select hex(a) from t1 order by a;
+hex(a)
+201F201F201F201F201F201F201F201F201F201F
+2020202020202020202020202020202020202020
+2021202120212021202120212021202120212021
+drop table t1;
CREATE TABLE t1 (id int, s char(5) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci);
INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ');
SELECT id, MIN(s) FROM t1 GROUP BY id;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 00fd5a0c9aa..4eb74510c93 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -197,7 +197,7 @@ drop table t1;
create table t1 (s1 char(10) character set utf8);
insert into t1 values (0x41FF);
Warnings:
-Warning 1265 Data truncated for column 's1' at row 1
+Warning 1366 Incorrect string value: '\xFF' for column 's1' at row 1
select hex(s1) from t1;
hex(s1)
41
@@ -205,7 +205,7 @@ drop table t1;
create table t1 (s1 varchar(10) character set utf8);
insert into t1 values (0x41FF);
Warnings:
-Warning 1265 Data truncated for column 's1' at row 1
+Warning 1366 Incorrect string value: '\xFF' for column 's1' at row 1
select hex(s1) from t1;
hex(s1)
41
@@ -213,7 +213,7 @@ drop table t1;
create table t1 (s1 text character set utf8);
insert into t1 values (0x41FF);
Warnings:
-Warning 1265 Data truncated for column 's1' at row 1
+Warning 1366 Incorrect string value: '\xFF' for column 's1' at row 1
select hex(s1) from t1;
hex(s1)
41
@@ -1536,6 +1536,32 @@ set @a:=null;
execute my_stmt using @a;
a b
drop table if exists t1;
+drop table if exists t1;
+drop view if exists v1, v2;
+set names utf8;
+create table t1(col1 varchar(12) character set utf8 collate utf8_unicode_ci);
+insert into t1 values('t1_val');
+create view v1 as select 'v1_val' as col1;
+select coercibility(col1), collation(col1) from v1;
+coercibility(col1) collation(col1)
+4 utf8_general_ci
+create view v2 as select col1 from v1 union select col1 from t1;
+select coercibility(col1), collation(col1)from v2;
+coercibility(col1) collation(col1)
+2 utf8_unicode_ci
+2 utf8_unicode_ci
+drop view v1, v2;
+create view v1 as select 'v1_val' collate utf8_swedish_ci as col1;
+select coercibility(col1), collation(col1) from v1;
+coercibility(col1) collation(col1)
+0 utf8_swedish_ci
+create view v2 as select col1 from v1 union select col1 from t1;
+select coercibility(col1), collation(col1) from v2;
+coercibility(col1) collation(col1)
+0 utf8_swedish_ci
+0 utf8_swedish_ci
+drop view v1, v2;
+drop table t1;
CREATE TABLE t1 (
colA int(11) NOT NULL,
colB varchar(255) character set utf8 NOT NULL,
diff --git a/mysql-test/r/drop.result b/mysql-test/r/drop.result
index d122dabc4ec..ff11905aa34 100644
--- a/mysql-test/r/drop.result
+++ b/mysql-test/r/drop.result
@@ -77,9 +77,9 @@ drop table if exists t1;
create table t1 (i int);
lock tables t1 read;
create database mysqltest;
- drop table t1;
+drop table t1;
show open tables;
- drop database mysqltest;
+drop database mysqltest;
select 1;
1
1
diff --git a/mysql-test/r/flush.result b/mysql-test/r/flush.result
index a7f5e5e8fec..7eb7fd16edb 100644
--- a/mysql-test/r/flush.result
+++ b/mysql-test/r/flush.result
@@ -9,13 +9,13 @@ n
flush tables with read lock;
drop table t2;
ERROR HY000: Can't execute the query because you have a conflicting read lock
- drop table t2;
+drop table t2;
unlock tables;
create database mysqltest;
create table mysqltest.t1(n int);
insert into mysqltest.t1 values (23);
flush tables with read lock;
- drop database mysqltest;
+drop database mysqltest;
select * from mysqltest.t1;
n
23
@@ -51,7 +51,7 @@ drop table t1, t2, t3;
create table t1 (c1 int);
create table t2 (c1 int);
lock table t1 write;
- flush tables with read lock;
- insert into t2 values(1);
+flush tables with read lock;
+insert into t2 values(1);
unlock tables;
drop table t1, t2;
diff --git a/mysql-test/r/flush_block_commit.result b/mysql-test/r/flush_block_commit.result
index 2e9f1920937..d5b10868358 100644
--- a/mysql-test/r/flush_block_commit.result
+++ b/mysql-test/r/flush_block_commit.result
@@ -5,7 +5,7 @@ insert into t1 values(1);
flush tables with read lock;
select * from t1;
a
- commit;
+commit;
select * from t1;
a
unlock tables;
@@ -14,8 +14,8 @@ select * from t1 for update;
a
1
begin;
- select * from t1 for update;
- flush tables with read lock;
+select * from t1 for update;
+flush tables with read lock;
commit;
a
1
diff --git a/mysql-test/r/flush_read_lock_kill.result b/mysql-test/r/flush_read_lock_kill.result
index dfdcf51457a..6703b6bd533 100644
--- a/mysql-test/r/flush_read_lock_kill.result
+++ b/mysql-test/r/flush_read_lock_kill.result
@@ -1,7 +1,7 @@
drop table if exists t1;
create table t1 (kill_id int);
insert into t1 values(connection_id());
- flush tables with read lock;
+flush tables with read lock;
select ((@id := kill_id) - kill_id) from t1;
((@id := kill_id) - kill_id)
0
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 85894d5cb0e..7c9069791fa 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -372,10 +372,10 @@ t collation(t) FORMAT(MATCH t AGAINST ('Osnabruck'),6)
aus Osnabrück utf8_general_ci 1.591140
alter table t1 modify t varchar(200) collate latin1_german2_ci not null;
Warnings:
-Warning 1265 Data truncated for column 't' at row 3
-Warning 1265 Data truncated for column 't' at row 4
-Warning 1265 Data truncated for column 't' at row 5
-Warning 1265 Data truncated for column 't' at row 6
+Warning 1366 Incorrect string value: '\xD0\xAD\xD1\x82\xD0\xBE...' for column 't' at row 3
+Warning 1366 Incorrect string value: '\xD0\x9E\xD1\x82\xD0\xBB...' for column 't' at row 4
+Warning 1366 Incorrect string value: '\xD0\x9D\xD0\xB5 \xD0...' for column 't' at row 5
+Warning 1366 Incorrect string value: '\xD0\xB8 \xD0\xB1\xD1...' for column 't' at row 6
SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück');
t collation(t)
aus Osnabrück latin1_german2_ci
diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result
index 00d5ebfc351..4a3454cf658 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -79,6 +79,16 @@ uncompress(a) uncompressed_length(a)
NULL NULL
a 1
drop table t1;
+create table t1(a blob);
+insert into t1 values ('0'), (NULL), ('0');
+select compress(a), compress(a) from t1;
+select compress(a) is null from t1;
+compress(a) is null
+0
+1
+0
+drop table t1;
+End of 4.1 tests
create table t1 (a varchar(32) not null);
insert into t1 values ('foo');
explain select * from t1 where uncompress(a) is null;
diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result
index 841d13a6ea6..ac5709260fd 100644
--- a/mysql-test/r/func_date_add.result
+++ b/mysql-test/r/func_date_add.result
@@ -71,3 +71,17 @@ NULL
NULL
NULL
drop table t1;
+End of 4.1 tests
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY;
+CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY
+2006-09-27
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH;
+CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH
+2006-10-26
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR;
+CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR
+2007-09-26
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK;
+CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK
+2006-10-03
+End of 5.0 tests
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 5dbbd891427..6989b89833b 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -658,3 +658,73 @@ GROUP_CONCAT(a) x
2 1,2
1 2,3
DROP TABLE t1;
+set names utf8;
+create table t1
+(
+x text character set utf8 not null,
+y integer not null
+);
+insert into t1 values (repeat('a', 1022), 0), (repeat(_utf8 0xc3b7, 4), 0);
+set group_concat_max_len= 1022 + 10;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1032 1031 1027 aaaaaaa,÷÷÷÷ C3B7C3B7C3B7
+set group_concat_max_len= 1022 + 9;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1031 1031 1027 aaaaaaa,÷÷÷÷ C3B7C3B7C3B7
+set group_concat_max_len= 1022 + 8;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1030 1029 1026 aaaaaaaa,÷÷÷ C3B7C3B7C3B7
+set group_concat_max_len= 1022 + 7;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1029 1029 1026 aaaaaaaa,÷÷÷ C3B7C3B7C3B7
+set group_concat_max_len= 1022 + 6;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1028 1027 1025 aaaaaaaaa,÷÷ 612CC3B7C3B7
+set group_concat_max_len= 1022 + 5;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1027 1027 1025 aaaaaaaaa,÷÷ 612CC3B7C3B7
+set group_concat_max_len= 1022 + 4;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1026 1025 1024 aaaaaaaaaa,÷ 6161612CC3B7
+set group_concat_max_len= 1022 + 3;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1025 1025 1024 aaaaaaaaaa,÷ 6161612CC3B7
+set group_concat_max_len= 1022 + 2;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1024 1023 1023 aaaaaaaaaaa, 61616161612C
+set group_concat_max_len= 1022 + 1;
+select @x:=group_concat(x) from t1 group by y;
+select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12)
+1023 1023 1023 aaaaaaaaaaa, 61616161612C
+drop table t1;
+set group_concat_max_len=1024;
+set names latin1;
+create table t1 (f1 int unsigned, f2 varchar(255));
+insert into t1 values (1,repeat('a',255)),(2,repeat('b',255));
+select f2,group_concat(f1) from t1 group by f2;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 t1 f2 f2 253 255 255 Y 0 0 8
+def group_concat(f1) 252 1024 1 Y 128 0 63
+f2 group_concat(f1)
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2
+drop table t1;
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index e38e2624e19..a172d04d880 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -202,6 +202,14 @@ select count(*) from t1 where id not in (1,2);
count(*)
1
drop table t1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 SELECT 1 IN (2, NULL);
+SELECT should return NULL.
+SELECT * FROM t1;
+1 IN (2, NULL)
+NULL
+DROP TABLE t1;
+End of 4.1 tests
CREATE TABLE t1 (a int PRIMARY KEY);
INSERT INTO t1 VALUES (44), (45), (46);
SELECT * FROM t1 WHERE a IN (45);
@@ -343,3 +351,4 @@ some_id
1
2
drop table t1;
+End of 5.0 tests
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index f0262acd71e..c1ac3e191d3 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -63,7 +63,7 @@ FROM t1
WHERE conn = 'default';
IS_USED_LOCK('bug16501') = connection_id
1
- SELECT GET_LOCK('bug16501',600);
+SELECT GET_LOCK('bug16501',600);
SELECT IS_USED_LOCK('bug16501') = CONNECTION_ID();
IS_USED_LOCK('bug16501') = CONNECTION_ID()
1
diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result
index 64eb6eefd1a..18908c2c46e 100644
--- a/mysql-test/r/func_sapdb.result
+++ b/mysql-test/r/func_sapdb.result
@@ -107,7 +107,9 @@ subtime("02:01:01.999999", "01:01:01.999999")
01:00:00.000000
select timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002");
timediff("1997-01-01 23:59:59.000001","1995-12-31 23:59:59.000002")
-8807:59:59.999999
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '8807:59:59.999999'
select timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002");
timediff("1997-12-31 23:59:59.000001","1997-12-30 01:01:01.000002")
46:58:57.999999
@@ -219,13 +221,16 @@ SELECT TIMEDIFF(t1, t4) As ttt, TIMEDIFF(t2, t3) As qqq,
TIMEDIFF(t3, t2) As eee, TIMEDIFF(t2, t4) As rrr from test;
ttt qqq eee rrr
-744:00:00 NULL NULL NULL
-26305:01:02 22:58:58 -22:58:58 NULL
--26305:01:02 -22:58:58 22:58:58 NULL
+838:59:59 22:58:58 -22:58:58 NULL
+-838:59:59 -22:58:58 22:58:58 NULL
NULL 26:02:02 -26:02:02 NULL
00:00:00 -26:02:02 26:02:02 NULL
NULL NULL NULL NULL
NULL NULL NULL NULL
00:00:00 -24:00:00 24:00:00 NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '26305:01:02'
+Warning 1292 Truncated incorrect time value: '-26305:01:02'
drop table t1, test;
select addtime("-01:01:01.01", "-23:59:59.1") as a;
a
@@ -235,7 +240,9 @@ a
10000
select microsecond(19971231235959.01) as a;
a
-10000
+0
+Warnings:
+Warning 1292 Truncated incorrect time value: '19971231235959.01'
select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a;
a
1997-12-31 00:00:10.090000
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index c2c12f8d291..14c61a2dd93 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1148,4 +1148,772 @@ id select_type table type possible_keys key key_len ref rows Extra
Warnings:
Note 1003 select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5))
DROP TABLE t1,t2;
+select locate('he','hello',-2);
+locate('he','hello',-2)
+0
+select locate('lo','hello',-4294967295);
+locate('lo','hello',-4294967295)
+0
+select locate('lo','hello',4294967295);
+locate('lo','hello',4294967295)
+0
+select locate('lo','hello',-4294967296);
+locate('lo','hello',-4294967296)
+0
+select locate('lo','hello',4294967296);
+locate('lo','hello',4294967296)
+0
+select locate('lo','hello',-4294967297);
+locate('lo','hello',-4294967297)
+0
+select locate('lo','hello',4294967297);
+locate('lo','hello',4294967297)
+0
+select locate('lo','hello',-18446744073709551615);
+locate('lo','hello',-18446744073709551615)
+0
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select locate('lo','hello',18446744073709551615);
+locate('lo','hello',18446744073709551615)
+0
+select locate('lo','hello',-18446744073709551616);
+locate('lo','hello',-18446744073709551616)
+0
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select locate('lo','hello',18446744073709551616);
+locate('lo','hello',18446744073709551616)
+0
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select locate('lo','hello',-18446744073709551617);
+locate('lo','hello',-18446744073709551617)
+0
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select locate('lo','hello',18446744073709551617);
+locate('lo','hello',18446744073709551617)
+0
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select left('hello', 10);
+left('hello', 10)
+hello
+select left('hello', 0);
+left('hello', 0)
+
+select left('hello', -1);
+left('hello', -1)
+
+select left('hello', -4294967295);
+left('hello', -4294967295)
+
+select left('hello', 4294967295);
+left('hello', 4294967295)
+hello
+select left('hello', -4294967296);
+left('hello', -4294967296)
+
+select left('hello', 4294967296);
+left('hello', 4294967296)
+hello
+select left('hello', -4294967297);
+left('hello', -4294967297)
+
+select left('hello', 4294967297);
+left('hello', 4294967297)
+hello
+select left('hello', -18446744073709551615);
+left('hello', -18446744073709551615)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select left('hello', 18446744073709551615);
+left('hello', 18446744073709551615)
+hello
+select left('hello', -18446744073709551616);
+left('hello', -18446744073709551616)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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: ''
+select left('hello', -18446744073709551617);
+left('hello', -18446744073709551617)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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: ''
+select right('hello', 10);
+right('hello', 10)
+hello
+select right('hello', 0);
+right('hello', 0)
+
+select right('hello', -1);
+right('hello', -1)
+
+select right('hello', -4294967295);
+right('hello', -4294967295)
+
+select right('hello', 4294967295);
+right('hello', 4294967295)
+hello
+select right('hello', -4294967296);
+right('hello', -4294967296)
+
+select right('hello', 4294967296);
+right('hello', 4294967296)
+hello
+select right('hello', -4294967297);
+right('hello', -4294967297)
+
+select right('hello', 4294967297);
+right('hello', 4294967297)
+hello
+select right('hello', -18446744073709551615);
+right('hello', -18446744073709551615)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select right('hello', 18446744073709551615);
+right('hello', 18446744073709551615)
+hello
+select right('hello', -18446744073709551616);
+right('hello', -18446744073709551616)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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: ''
+select right('hello', -18446744073709551617);
+right('hello', -18446744073709551617)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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: ''
+select substring('hello', 2, -1);
+substring('hello', 2, -1)
+
+select substring('hello', -1, 1);
+substring('hello', -1, 1)
+o
+select substring('hello', -2, 1);
+substring('hello', -2, 1)
+l
+select substring('hello', -4294967295, 1);
+substring('hello', -4294967295, 1)
+
+select substring('hello', 4294967295, 1);
+substring('hello', 4294967295, 1)
+
+select substring('hello', -4294967296, 1);
+substring('hello', -4294967296, 1)
+
+select substring('hello', 4294967296, 1);
+substring('hello', 4294967296, 1)
+
+select substring('hello', -4294967297, 1);
+substring('hello', -4294967297, 1)
+
+select substring('hello', 4294967297, 1);
+substring('hello', 4294967297, 1)
+
+select substring('hello', -18446744073709551615, 1);
+substring('hello', -18446744073709551615, 1)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select substring('hello', 18446744073709551615, 1);
+substring('hello', 18446744073709551615, 1)
+
+select substring('hello', -18446744073709551616, 1);
+substring('hello', -18446744073709551616, 1)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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: ''
+select substring('hello', -18446744073709551617, 1);
+substring('hello', -18446744073709551617, 1)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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: ''
+select substring('hello', 1, -1);
+substring('hello', 1, -1)
+
+select substring('hello', 1, -4294967295);
+substring('hello', 1, -4294967295)
+
+select substring('hello', 1, 4294967295);
+substring('hello', 1, 4294967295)
+hello
+select substring('hello', 1, -4294967296);
+substring('hello', 1, -4294967296)
+
+select substring('hello', 1, 4294967296);
+substring('hello', 1, 4294967296)
+hello
+select substring('hello', 1, -4294967297);
+substring('hello', 1, -4294967297)
+
+select substring('hello', 1, 4294967297);
+substring('hello', 1, 4294967297)
+hello
+select substring('hello', 1, -18446744073709551615);
+substring('hello', 1, -18446744073709551615)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select substring('hello', 1, 18446744073709551615);
+substring('hello', 1, 18446744073709551615)
+hello
+select substring('hello', 1, -18446744073709551616);
+substring('hello', 1, -18446744073709551616)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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: ''
+select substring('hello', 1, -18446744073709551617);
+substring('hello', 1, -18446744073709551617)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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: ''
+select substring('hello', -1, -1);
+substring('hello', -1, -1)
+
+select substring('hello', -4294967295, -4294967295);
+substring('hello', -4294967295, -4294967295)
+
+select substring('hello', 4294967295, 4294967295);
+substring('hello', 4294967295, 4294967295)
+
+select substring('hello', -4294967296, -4294967296);
+substring('hello', -4294967296, -4294967296)
+
+select substring('hello', 4294967296, 4294967296);
+substring('hello', 4294967296, 4294967296)
+
+select substring('hello', -4294967297, -4294967297);
+substring('hello', -4294967297, -4294967297)
+
+select substring('hello', 4294967297, 4294967297);
+substring('hello', 4294967297, 4294967297)
+
+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: ''
+select substring('hello', 18446744073709551615, 18446744073709551615);
+substring('hello', 18446744073709551615, 18446744073709551615)
+
+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: ''
+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: ''
+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: ''
+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: ''
+select insert('hello', -1, 1, 'hi');
+insert('hello', -1, 1, 'hi')
+hello
+select insert('hello', -4294967295, 1, 'hi');
+insert('hello', -4294967295, 1, 'hi')
+hello
+select insert('hello', 4294967295, 1, 'hi');
+insert('hello', 4294967295, 1, 'hi')
+hello
+select insert('hello', -4294967296, 1, 'hi');
+insert('hello', -4294967296, 1, 'hi')
+hello
+select insert('hello', 4294967296, 1, 'hi');
+insert('hello', 4294967296, 1, 'hi')
+hello
+select insert('hello', -4294967297, 1, 'hi');
+insert('hello', -4294967297, 1, 'hi')
+hello
+select insert('hello', 4294967297, 1, 'hi');
+insert('hello', 4294967297, 1, 'hi')
+hello
+select insert('hello', -18446744073709551615, 1, 'hi');
+insert('hello', -18446744073709551615, 1, 'hi')
+hello
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', 18446744073709551615, 1, 'hi');
+insert('hello', 18446744073709551615, 1, 'hi')
+hello
+select insert('hello', -18446744073709551616, 1, 'hi');
+insert('hello', -18446744073709551616, 1, 'hi')
+hello
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', 18446744073709551616, 1, 'hi');
+insert('hello', 18446744073709551616, 1, 'hi')
+hello
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', -18446744073709551617, 1, 'hi');
+insert('hello', -18446744073709551617, 1, 'hi')
+hello
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', 18446744073709551617, 1, 'hi');
+insert('hello', 18446744073709551617, 1, 'hi')
+hello
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', 1, -1, 'hi');
+insert('hello', 1, -1, 'hi')
+hi
+select insert('hello', 1, -4294967295, 'hi');
+insert('hello', 1, -4294967295, 'hi')
+hi
+select insert('hello', 1, 4294967295, 'hi');
+insert('hello', 1, 4294967295, 'hi')
+hi
+select insert('hello', 1, -4294967296, 'hi');
+insert('hello', 1, -4294967296, 'hi')
+hi
+select insert('hello', 1, 4294967296, 'hi');
+insert('hello', 1, 4294967296, 'hi')
+hi
+select insert('hello', 1, -4294967297, 'hi');
+insert('hello', 1, -4294967297, 'hi')
+hi
+select insert('hello', 1, 4294967297, 'hi');
+insert('hello', 1, 4294967297, 'hi')
+hi
+select insert('hello', 1, -18446744073709551615, 'hi');
+insert('hello', 1, -18446744073709551615, 'hi')
+hi
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', 1, 18446744073709551615, 'hi');
+insert('hello', 1, 18446744073709551615, 'hi')
+hi
+select insert('hello', 1, -18446744073709551616, 'hi');
+insert('hello', 1, -18446744073709551616, 'hi')
+hi
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', 1, 18446744073709551616, 'hi');
+insert('hello', 1, 18446744073709551616, 'hi')
+hi
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', 1, -18446744073709551617, 'hi');
+insert('hello', 1, -18446744073709551617, 'hi')
+hi
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', 1, 18446744073709551617, 'hi');
+insert('hello', 1, 18446744073709551617, 'hi')
+hi
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+select insert('hello', -1, -1, 'hi');
+insert('hello', -1, -1, 'hi')
+hello
+select insert('hello', -4294967295, -4294967295, 'hi');
+insert('hello', -4294967295, -4294967295, 'hi')
+hello
+select insert('hello', 4294967295, 4294967295, 'hi');
+insert('hello', 4294967295, 4294967295, 'hi')
+hello
+select insert('hello', -4294967296, -4294967296, 'hi');
+insert('hello', -4294967296, -4294967296, 'hi')
+hello
+select insert('hello', 4294967296, 4294967296, 'hi');
+insert('hello', 4294967296, 4294967296, 'hi')
+hello
+select insert('hello', -4294967297, -4294967297, 'hi');
+insert('hello', -4294967297, -4294967297, 'hi')
+hello
+select insert('hello', 4294967297, 4294967297, 'hi');
+insert('hello', 4294967297, 4294967297, 'hi')
+hello
+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: ''
+select insert('hello', 18446744073709551615, 18446744073709551615, 'hi');
+insert('hello', 18446744073709551615, 18446744073709551615, 'hi')
+hello
+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: ''
+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: ''
+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: ''
+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: ''
+select repeat('hello', -1);
+repeat('hello', -1)
+
+select repeat('hello', -4294967295);
+repeat('hello', -4294967295)
+
+select repeat('hello', 4294967295);
+repeat('hello', 4294967295)
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select repeat('hello', -4294967296);
+repeat('hello', -4294967296)
+
+select repeat('hello', 4294967296);
+repeat('hello', 4294967296)
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select repeat('hello', -4294967297);
+repeat('hello', -4294967297)
+
+select repeat('hello', 4294967297);
+repeat('hello', 4294967297)
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select repeat('hello', -18446744073709551615);
+repeat('hello', -18446744073709551615)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select repeat('hello', 18446744073709551615);
+repeat('hello', 18446744073709551615)
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select repeat('hello', -18446744073709551616);
+repeat('hello', -18446744073709551616)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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 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: ''
+select repeat('hello', 18446744073709551617);
+repeat('hello', 18446744073709551617)
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select space(-1);
+space(-1)
+
+select space(-4294967295);
+space(-4294967295)
+
+select space(4294967295);
+space(4294967295)
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select space(-4294967296);
+space(-4294967296)
+
+select space(4294967296);
+space(4294967296)
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select space(-4294967297);
+space(-4294967297)
+
+select space(4294967297);
+space(4294967297)
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select space(-18446744073709551615);
+space(-18446744073709551615)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select space(18446744073709551615);
+space(18446744073709551615)
+NULL
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
+select space(-18446744073709551616);
+space(-18446744073709551616)
+
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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 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: ''
+select space(18446744073709551617);
+space(18446744073709551617)
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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')
+NULL
+select rpad('hello', -4294967295, '1');
+rpad('hello', -4294967295, '1')
+NULL
+select rpad('hello', 4294967295, '1');
+rpad('hello', 4294967295, '1')
+NULL
+Warnings:
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -4294967296, '1');
+rpad('hello', -4294967296, '1')
+NULL
+select rpad('hello', 4294967296, '1');
+rpad('hello', 4294967296, '1')
+NULL
+Warnings:
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -4294967297, '1');
+rpad('hello', -4294967297, '1')
+NULL
+select rpad('hello', 4294967297, '1');
+rpad('hello', 4294967297, '1')
+NULL
+Warnings:
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -18446744073709551615, '1');
+rpad('hello', -18446744073709551615, '1')
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select rpad('hello', 18446744073709551615, '1');
+rpad('hello', 18446744073709551615, '1')
+NULL
+Warnings:
+Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
+select rpad('hello', -18446744073709551616, '1');
+rpad('hello', -18446744073709551616, '1')
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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 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: ''
+select rpad('hello', 18446744073709551617, '1');
+rpad('hello', 18446744073709551617, '1')
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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')
+NULL
+select lpad('hello', -4294967295, '1');
+lpad('hello', -4294967295, '1')
+NULL
+select lpad('hello', 4294967295, '1');
+lpad('hello', 4294967295, '1')
+NULL
+Warnings:
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -4294967296, '1');
+lpad('hello', -4294967296, '1')
+NULL
+select lpad('hello', 4294967296, '1');
+lpad('hello', 4294967296, '1')
+NULL
+Warnings:
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -4294967297, '1');
+lpad('hello', -4294967297, '1')
+NULL
+select lpad('hello', 4294967297, '1');
+lpad('hello', 4294967297, '1')
+NULL
+Warnings:
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -18446744073709551615, '1');
+lpad('hello', -18446744073709551615, '1')
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1292 Truncated incorrect DECIMAL value: ''
+select lpad('hello', 18446744073709551615, '1');
+lpad('hello', 18446744073709551615, '1')
+NULL
+Warnings:
+Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
+select lpad('hello', -18446744073709551616, '1');
+lpad('hello', -18446744073709551616, '1')
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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 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: ''
+select lpad('hello', 18446744073709551617, '1');
+lpad('hello', 18446744073709551617, '1')
+NULL
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
+Error 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;
+SELECT CHAR(0xff,0x8f USING utf8);
+CHAR(0xff,0x8f USING utf8)
+NULL
+Warnings:
+Error 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'
+SET SQL_MODE=@orig_sql_mode;
End of 5.0 tests
diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result
index d9437f6c515..43832bdbccc 100644
--- a/mysql-test/r/func_test.result
+++ b/mysql-test/r/func_test.result
@@ -182,6 +182,81 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
5 mod 3 5 mod -3 -5 mod 3 -5 mod -3
2 2 -2 -2
+select (12%0) <=> null as '1';
+1
+1
+select (12%0) is null as '1';
+1
+1
+select 12%0 as 'NULL';
+NULL
+NULL
+select 12%2 as '0';
+0
+0
+select 12%NULL as 'NULL';
+NULL
+NULL
+select 12 % null as 'NULL';
+NULL
+NULL
+select null % 12 as 'NULL';
+NULL
+NULL
+select null % 0 as 'NULL';
+NULL
+NULL
+select 0 % null as 'NULL';
+NULL
+NULL
+select null % null as 'NULL';
+NULL
+NULL
+select (12 mod 0) <=> null as '1';
+1
+1
+select (12 mod 0) is null as '1';
+1
+1
+select 12 mod 0 as 'NULL';
+NULL
+NULL
+select 12 mod 2 as '0';
+0
+0
+select 12 mod null as 'NULL';
+NULL
+NULL
+select null mod 12 as 'NULL';
+NULL
+NULL
+select null mod 0 as 'NULL';
+NULL
+NULL
+select 0 mod null as 'NULL';
+NULL
+NULL
+select null mod null as 'NULL';
+NULL
+NULL
+select mod(12.0, 0) as 'NULL';
+NULL
+NULL
+select mod(12, 0.0) as 'NULL';
+NULL
+NULL
+select mod(12, NULL) as 'NULL';
+NULL
+NULL
+select mod(12.0, NULL) as 'NULL';
+NULL
+NULL
+select mod(NULL, 2) as 'NULL';
+NULL
+NULL
+select mod(NULL, 2.0) as 'NULL';
+NULL
+NULL
create table t1 (a int, b int);
insert into t1 values (1,2), (2,3), (3,4), (4,5);
select * from t1 where a not between 1 and 2;
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 25c910a711a..e8fd7a4e4c9 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -339,7 +339,9 @@ extract(DAY_MINUTE FROM "02 10:11:12")
21011
select extract(DAY_SECOND FROM "225 10:11:12");
extract(DAY_SECOND FROM "225 10:11:12")
-225101112
+8385959
+Warnings:
+Warning 1292 Truncated incorrect time value: '225 10:11:12'
select extract(HOUR FROM "1999-01-02 10:11:12");
extract(HOUR FROM "1999-01-02 10:11:12")
10
@@ -548,12 +550,48 @@ unix_timestamp('1969-12-01 19:00:01')
select from_unixtime(-1);
from_unixtime(-1)
NULL
-select from_unixtime(2145916800);
-from_unixtime(2145916800)
+select from_unixtime(2147483647);
+from_unixtime(2147483647)
+2038-01-19 06:14:07
+select from_unixtime(2147483648);
+from_unixtime(2147483648)
NULL
select from_unixtime(0);
from_unixtime(0)
1970-01-01 03:00:00
+select unix_timestamp(from_unixtime(2147483647));
+unix_timestamp(from_unixtime(2147483647))
+2147483647
+select unix_timestamp(from_unixtime(2147483648));
+unix_timestamp(from_unixtime(2147483648))
+NULL
+select unix_timestamp('2039-01-20 01:00:00');
+unix_timestamp('2039-01-20 01:00:00')
+0
+select unix_timestamp('1968-01-20 01:00:00');
+unix_timestamp('1968-01-20 01:00:00')
+0
+select unix_timestamp('2038-02-10 01:00:00');
+unix_timestamp('2038-02-10 01:00:00')
+0
+select unix_timestamp('1969-11-20 01:00:00');
+unix_timestamp('1969-11-20 01:00:00')
+0
+select unix_timestamp('2038-01-20 01:00:00');
+unix_timestamp('2038-01-20 01:00:00')
+0
+select unix_timestamp('1969-12-30 01:00:00');
+unix_timestamp('1969-12-30 01:00:00')
+0
+select unix_timestamp('2038-01-17 12:00:00');
+unix_timestamp('2038-01-17 12:00:00')
+2147331600
+select unix_timestamp('1970-01-01 03:00:01');
+unix_timestamp('1970-01-01 03:00:01')
+1
+select unix_timestamp('2038-01-19 07:14:07');
+unix_timestamp('2038-01-19 07:14:07')
+0
CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
SELECT * from t1;
@@ -612,7 +650,7 @@ date_add(date,INTERVAL "1 1:1:1" DAY_SECOND)
2003-01-03 01:01:01
select date_add(date,INTERVAL "1" WEEK) from t1;
date_add(date,INTERVAL "1" WEEK)
-2003-01-09 00:00:00
+2003-01-09
select date_add(date,INTERVAL "1" QUARTER) from t1;
date_add(date,INTERVAL "1" QUARTER)
2003-04-02
@@ -621,7 +659,7 @@ timestampadd(MINUTE, 1, date)
2003-01-02 00:01:00
select timestampadd(WEEK, 1, date) from t1;
timestampadd(WEEK, 1, date)
-2003-01-09 00:00:00
+2003-01-09
select timestampadd(SQL_TSI_SECOND, 1, date) from t1;
timestampadd(SQL_TSI_SECOND, 1, date)
2003-01-02 00:00:01
@@ -890,6 +928,93 @@ t1 CREATE TABLE `t1` (
`from_unixtime(1) + 0` double(23,6) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
+SELECT SEC_TO_TIME(3300000);
+SEC_TO_TIME(3300000)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '3300000'
+SELECT SEC_TO_TIME(3300000)+0;
+SEC_TO_TIME(3300000)+0
+8385959.000000
+Warnings:
+Warning 1292 Truncated incorrect time value: '3300000'
+SELECT SEC_TO_TIME(3600 * 4294967296);
+SEC_TO_TIME(3600 * 4294967296)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '15461882265600'
+SELECT TIME_TO_SEC('916:40:00');
+TIME_TO_SEC('916:40:00')
+3020399
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:40:00'
+SELECT ADDTIME('500:00:00', '416:40:00');
+ADDTIME('500:00:00', '416:40:00')
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:40:00'
+SELECT ADDTIME('916:40:00', '416:40:00');
+ADDTIME('916:40:00', '416:40:00')
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:40:00'
+Warning 1292 Truncated incorrect time value: '1255:39:59'
+SELECT SUBTIME('916:40:00', '416:40:00');
+SUBTIME('916:40:00', '416:40:00')
+422:19:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:40:00'
+SELECT SUBTIME('-916:40:00', '416:40:00');
+SUBTIME('-916:40:00', '416:40:00')
+-838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '-916:40:00'
+Warning 1292 Truncated incorrect time value: '-1255:39:59'
+SELECT MAKETIME(916,0,0);
+MAKETIME(916,0,0)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '916:00:00'
+SELECT MAKETIME(4294967296, 0, 0);
+MAKETIME(4294967296, 0, 0)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '4294967296:00:00'
+SELECT MAKETIME(-4294967296, 0, 0);
+MAKETIME(-4294967296, 0, 0)
+-838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '-4294967296:00:00'
+SELECT MAKETIME(0, 4294967296, 0);
+MAKETIME(0, 4294967296, 0)
+NULL
+SELECT MAKETIME(0, 0, 4294967296);
+MAKETIME(0, 0, 4294967296)
+NULL
+SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0);
+MAKETIME(CAST(-1 AS UNSIGNED), 0, 0)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00'
+SELECT EXTRACT(HOUR FROM '100000:02:03');
+EXTRACT(HOUR FROM '100000:02:03')
+838
+Warnings:
+Warning 1292 Truncated incorrect time value: '100000:02:03'
+CREATE TABLE t1(f1 TIME);
+INSERT INTO t1 VALUES('916:00:00 a');
+Warnings:
+Warning 1265 Data truncated for column 'f1' at row 1
+Warning 1264 Out of range value adjusted for column 'f1' at row 1
+SELECT * FROM t1;
+f1
+838:59:59
+DROP TABLE t1;
+SELECT SEC_TO_TIME(CAST(-1 AS UNSIGNED));
+SEC_TO_TIME(CAST(-1 AS UNSIGNED))
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '18446744073709551615'
SET NAMES latin1;
SET character_set_results = NULL;
SHOW VARIABLES LIKE 'character_set_results';
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 46aecde2cc5..870e160e563 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -673,6 +673,22 @@ POINT(10 10)
select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440))));
(asWKT(geomfromwkb((0x010100000000000000000024400000000000002440))))
POINT(10 10)
+create table t1 (g GEOMETRY);
+select * from t1;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 t1 g g 255 4294967295 0 Y 144 0 63
+g
+select asbinary(g) from t1;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def asbinary(g) 252 8192 0 Y 128 0 63
+asbinary(g)
+drop table t1;
+create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b));
+alter table t1 disable keys;
+load data infile '../std_data_ln/bad_gis_data.dat' into table t1;
+ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 1
+alter table t1 enable keys;
+drop table t1;
create table t1 (s1 geometry not null,s2 char(100));
create trigger t1_bu before update on t1 for each row set new.s1 = null;
insert into t1 values (null,null);
@@ -696,16 +712,6 @@ alter table t1 add primary key pti(pt);
ERROR 42000: BLOB/TEXT column 'pt' used in key specification without a key length
alter table t1 add primary key pti(pt(20));
drop table t1;
-create table t1 (g GEOMETRY);
-select * from t1;
-Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def test t1 t1 g g 255 4294967295 0 Y 144 0 63
-g
-select asbinary(g) from t1;
-Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
-def asbinary(g) 252 8192 0 Y 128 0 63
-asbinary(g)
-drop table t1;
create table t1 select GeomFromText('point(1 1)');
desc t1;
Field Type Null Key Default Extra
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 2700426257b..ff9b7bc6f1f 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -336,12 +336,12 @@ drop database mysqltest_1;
set password = password("changed");
ERROR 42000: Access denied for user ''@'localhost' to database 'mysql'
lock table mysql.user write;
- flush privileges;
- grant all on *.* to 'mysqltest_1'@'localhost';
+flush privileges;
+grant all on *.* to 'mysqltest_1'@'localhost';
unlock tables;
lock table mysql.user write;
- set password for 'mysqltest_1'@'localhost' = password('');
- revoke all on *.* from 'mysqltest_1'@'localhost';
+set password for 'mysqltest_1'@'localhost' = password('');
+revoke all on *.* from 'mysqltest_1'@'localhost';
unlock tables;
drop user 'mysqltest_1'@'localhost';
create database TESTDB;
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index 0304919baf6..7583aa14db8 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -2162,3 +2162,127 @@ SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
MIN(c)
2
DROP TABLE t1,t2;
+CREATE TABLE t1 (a INT, b INT, INDEX (a,b));
+INSERT INTO t1 (a, b) VALUES (1,1), (1,2), (1,3), (1,4), (1,5),
+(2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6);
+EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 5 NULL 8 Using index for group-by
+FLUSH STATUS;
+SELECT max(b), a FROM t1 GROUP BY a;
+max(b) a
+5 1
+3 2
+1 3
+6 4
+SHOW STATUS LIKE 'handler_read__e%';
+Variable_name Value
+Handler_read_key 8
+Handler_read_next 0
+EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range NULL a 5 NULL 8 Using index for group-by
+FLUSH STATUS;
+CREATE TABLE t2 SELECT max(b), a FROM t1 GROUP BY a;
+SHOW STATUS LIKE 'handler_read__e%';
+Variable_name Value
+Handler_read_key 8
+Handler_read_next 0
+FLUSH STATUS;
+SELECT * FROM (SELECT max(b), a FROM t1 GROUP BY a) b;
+max(b) a
+5 1
+3 2
+1 3
+6 4
+SHOW STATUS LIKE 'handler_read__e%';
+Variable_name Value
+Handler_read_key 8
+Handler_read_next 0
+FLUSH STATUS;
+(SELECT max(b), a FROM t1 GROUP BY a) UNION
+(SELECT max(b), a FROM t1 GROUP BY a);
+max(b) a
+5 1
+3 2
+1 3
+6 4
+SHOW STATUS LIKE 'handler_read__e%';
+Variable_name Value
+Handler_read_key 16
+Handler_read_next 0
+EXPLAIN (SELECT max(b), a FROM t1 GROUP BY a) UNION
+(SELECT max(b), a FROM t1 GROUP BY a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range NULL a 5 NULL 8 Using index for group-by
+2 UNION t1 range NULL a 5 NULL 8 Using index for group-by
+NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
+EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
+FROM t1 AS t1_outer;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS
+(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 index NULL a 10 NULL 8 Using index
+EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
+(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
+a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1_outer index NULL a 10 NULL 15 Using where; Using index
+2 DEPENDENT SUBQUERY t1 index NULL a 10 NULL 8 Using index
+EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
+a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1_outer range NULL a 5 NULL 8 Using index for group-by
+2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2
+ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2)
+AND t1_outer1.b = t1_outer2.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1_outer1 ref a a 5 const 1 Using where; Using index
+1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index
+2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
+FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1_outer index NULL a 10 NULL 15 Using index
+3 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+CREATE TABLE t3 LIKE t1;
+FLUSH STATUS;
+INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a;
+SHOW STATUS LIKE 'handler_read__e%';
+Variable_name Value
+Handler_read_key 8
+Handler_read_next 0
+DELETE FROM t3;
+FLUSH STATUS;
+INSERT INTO t3 SELECT 1, (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2)
+FROM t1 LIMIT 1;
+SHOW STATUS LIKE 'handler_read__e%';
+Variable_name Value
+Handler_read_key 8
+Handler_read_next 0
+FLUSH STATUS;
+DELETE FROM t3 WHERE (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) > 10000;
+SHOW STATUS LIKE 'handler_read__e%';
+Variable_name Value
+Handler_read_key 8
+Handler_read_next 0
+FLUSH STATUS;
+DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x
+FROM t1) > 10000;
+Warnings:
+Error 1242 Subquery returns more than 1 row
+SHOW STATUS LIKE 'handler_read__e%';
+Variable_name Value
+Handler_read_key 8
+Handler_read_next 1
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
index 104025e83eb..85cf47b5806 100644
--- a/mysql-test/r/handler.result
+++ b/mysql-test/r/handler.result
@@ -452,7 +452,7 @@ handler t1 read first;
c1
1
send the below to another connection, do not wait for the result
- optimize table t1;
+optimize table t1;
proceed with the normal connection
handler t1 read next;
c1
@@ -469,7 +469,7 @@ flush tables with read lock;
drop table t1;
ERROR HY000: Can't execute the query because you have a conflicting read lock
send the below to another connection, do not wait for the result
- drop table t1;
+drop table t1;
proceed with the normal connection
select * from t1;
c1
diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result
index 52a69d98fcf..d80a34f8427 100644
--- a/mysql-test/r/im_daemon_life_cycle.result
+++ b/mysql-test/r/im_daemon_life_cycle.result
@@ -6,8 +6,9 @@ instance_name status
mysqld1 online
mysqld2 offline
Killing the process...
-Sleeping...
+Waiting...
Success: the process was restarted.
+Success: server is ready to accept connection on socket.
--------------------------------------------------------------------
-- Test for BUG#12751
@@ -15,8 +16,9 @@ Success: the process was restarted.
START INSTANCE mysqld2;
Success: the process has been started.
Killing the process...
-Sleeping...
+Waiting...
Success: the process was restarted.
+Success: server is ready to accept connection on socket.
SHOW INSTANCE STATUS mysqld1;
instance_name status version
mysqld1 online VERSION
diff --git a/mysql-test/r/im_life_cycle.result b/mysql-test/r/im_life_cycle.result
index 69f6bb5a490..a9ad85d5947 100644
--- a/mysql-test/r/im_life_cycle.result
+++ b/mysql-test/r/im_life_cycle.result
@@ -39,7 +39,7 @@ ERROR HY000: Bad instance name. Check that the instance with such a name exists
-- 1.1.6.
--------------------------------------------------------------------
Killing the process...
-Sleeping...
+Waiting...
Success: the process was restarted.
SHOW INSTANCES;
instance_name status
@@ -52,7 +52,7 @@ mysqld2 offline
START INSTANCE mysqld2;
Success: the process has been started.
Killing the process...
-Sleeping...
+Waiting...
Success: the process was killed.
--------------------------------------------------------------------
diff --git a/mysql-test/r/im_utils.result b/mysql-test/r/im_utils.result
index f671089d31d..626f24b4635 100644
--- a/mysql-test/r/im_utils.result
+++ b/mysql-test/r/im_utils.result
@@ -22,8 +22,8 @@ basedir VALUE
server_id VALUE
skip-stack-trace VALUE
skip-innodb VALUE
-skip-bdb VALUE
skip-ndbcluster VALUE
+skip-bdb VALUE
SHOW INSTANCE OPTIONS mysqld2;
option_name value
instance_name VALUE
@@ -42,8 +42,8 @@ basedir VALUE
server_id VALUE
skip-stack-trace VALUE
skip-innodb VALUE
-skip-bdb VALUE
skip-ndbcluster VALUE
+skip-bdb VALUE
START INSTANCE mysqld2;
Success: the process has been started.
STOP INSTANCE mysqld2;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index 407f8a040b7..43eedc19f12 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -737,6 +737,7 @@ select table_schema,table_name, column_name from
information_schema.columns
where data_type = 'longtext';
table_schema table_name column_name
+information_schema COLUMNS COLUMN_DEFAULT
information_schema COLUMNS COLUMN_TYPE
information_schema ROUTINES ROUTINE_DEFINITION
information_schema ROUTINES SQL_MODE
@@ -1240,3 +1241,31 @@ WHERE table_name=(SELECT MAX(table_name)
FROM information_schema.tables);
table_name
VIEWS
+DROP TABLE IF EXISTS bug23037;
+DROP FUNCTION IF EXISTS get_value;
+SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='bug23037';
+COLUMN_NAME MD5(COLUMN_DEFAULT) LENGTH(COLUMN_DEFAULT)
+fld1 7cf7a6782be951a1f2464a350da926a5 65532
+SELECT MD5(get_value());
+MD5(get_value())
+7cf7a6782be951a1f2464a350da926a5
+SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT), COLUMN_DEFAULT=get_value() FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='bug23037';
+COLUMN_NAME MD5(COLUMN_DEFAULT) LENGTH(COLUMN_DEFAULT) COLUMN_DEFAULT=get_value()
+fld1 7cf7a6782be951a1f2464a350da926a5 65532 1
+DROP TABLE bug23037;
+DROP FUNCTION get_value;
+create view v1 as
+select table_schema as object_schema,
+table_name as object_name,
+table_type as object_type
+from information_schema.tables
+order by object_schema;
+explain select * from v1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED tables ALL NULL NULL NULL NULL 2 Using filesort
+explain select * from (select table_name from information_schema.tables) as a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
+2 DERIVED tables ALL NULL NULL NULL NULL 2
+drop view v1;
diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result
index c4564251a35..012f9492d8d 100644
--- a/mysql-test/r/innodb_mysql.result
+++ b/mysql-test/r/innodb_mysql.result
@@ -104,6 +104,14 @@ SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` =
id1
2
DROP TABLE t1, t2;
+create table t1 (c1 int) engine=innodb;
+handler t1 open;
+handler t1 read first;
+c1
+Before and after comparison
+0
+drop table t1;
+End of 4.1 tests
create table t1m (a int) engine=myisam;
create table t1i (a int) engine=innodb;
create table t2m (a int) engine=myisam;
@@ -295,6 +303,22 @@ b
c
d
drop table t1,t4;
+DROP TABLE IF EXISTS t2, t1;
+CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE= InnoDB;
+CREATE TABLE t2 (
+i INT NOT NULL,
+FOREIGN KEY (i) REFERENCES t1 (i) ON DELETE NO ACTION
+) ENGINE= InnoDB;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+DELETE IGNORE FROM t1 WHERE i = 1;
+Warnings:
+Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`i`) REFERENCES `t1` (`i`) ON DELETE NO ACTION)
+SELECT * FROM t1, t2;
+i i
+1 1
+DROP TABLE t2, t1;
+End of 4.1 tests.
create table t1 (
a varchar(30), b varchar(30), primary key(a), key(b)
) engine=innodb;
@@ -337,6 +361,12 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where
DROP TABLE t1,t2;
+create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb
+character set utf8 collate utf8_general_ci;
+Warnings:
+Warning 1071 Specified key was too long; max key length is 765 bytes
+insert into t1 values('aaa');
+drop table t1;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c FLOAT, KEY b(b)) ENGINE = INNODB;
INSERT INTO t1 VALUES ( 1 , 1 , 1);
INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20), 1 FROM t1;
@@ -353,3 +383,4 @@ EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using filesort
DROP TABLE t1;
+End of 5.0 tests
diff --git a/mysql-test/r/innodb_notembedded.result b/mysql-test/r/innodb_notembedded.result
index 9aac20e515d..cc13a429dfc 100644
--- a/mysql-test/r/innodb_notembedded.result
+++ b/mysql-test/r/innodb_notembedded.result
@@ -10,7 +10,7 @@ start transaction;
select f1();
f1()
100
- update t1 set col2=0 where col1=1;
+update t1 set col2=0 where col1=1;
select * from t1;
col1 col2
1 100
diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result
index b78c677fb02..cf5486d1091 100644
--- a/mysql-test/r/kill.result
+++ b/mysql-test/r/kill.result
@@ -22,7 +22,7 @@ create table t2 (id int unsigned not null);
insert into t2 select id from t1;
create table t3 (kill_id int);
insert into t3 values(connection_id());
- select id from t1 where id in (select distinct id from t2);
+select id from t1 where id in (select distinct id from t2);
select ((@id := kill_id) - kill_id) from t3;
((@id := kill_id) - kill_id)
0
@@ -32,7 +32,7 @@ drop table t1, t2, t3;
select get_lock("a", 10);
get_lock("a", 10)
1
- select get_lock("a", 10);
+select get_lock("a", 10);
get_lock("a", 10)
NULL
select 1;
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
index c80108f723a..af49e1a27dc 100644
--- a/mysql-test/r/lock_multi.result
+++ b/mysql-test/r/lock_multi.result
@@ -2,8 +2,8 @@ drop table if exists t1,t2;
create table t1(n int);
insert into t1 values (1);
lock tables t1 write;
- update low_priority t1 set n = 4;
- select n from t1;
+update low_priority t1 set n = 4;
+select n from t1;
unlock tables;
n
4
@@ -11,8 +11,8 @@ drop table t1;
create table t1(n int);
insert into t1 values (1);
lock tables t1 read;
- update low_priority t1 set n = 4;
- select n from t1;
+update low_priority t1 set n = 4;
+select n from t1;
unlock tables;
n
1
@@ -23,7 +23,7 @@ insert into t1 values(1,1);
insert into t1 values(2,2);
insert into t2 values(1,2);
lock table t1 read;
- update t1,t2 set c=a where b=d;
+update t1,t2 set c=a where b=d;
select c from t2;
c
2
@@ -32,7 +32,7 @@ drop table t2;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
- insert t1 select * from t2;
+insert t1 select * from t2;
drop table t2;
ERROR 42S02: Table 'test.t2' doesn't exist
drop table t1;
@@ -45,7 +45,7 @@ unlock tables;
drop table t1;
CREATE DATABASE mysqltest_1;
FLUSH TABLES WITH READ LOCK;
- DROP DATABASE mysqltest_1;
+DROP DATABASE mysqltest_1;
DROP DATABASE mysqltest_1;
ERROR HY000: Can't execute the query because you have a conflicting read lock
UNLOCK TABLES;
@@ -55,7 +55,7 @@ use mysql;
LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
FLUSH TABLES;
use mysql;
- SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
+SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
OPTIMIZE TABLES columns_priv, db, host, user;
Table Op Msg_type Msg_text
mysql.columns_priv optimize status OK
@@ -69,14 +69,14 @@ use test;
use test;
CREATE TABLE t1 (c1 int);
LOCK TABLE t1 WRITE;
- FLUSH TABLES WITH READ LOCK;
+FLUSH TABLES WITH READ LOCK;
CREATE TABLE t2 (c1 int);
UNLOCK TABLES;
UNLOCK TABLES;
DROP TABLE t1, t2;
CREATE TABLE t1 (c1 int);
LOCK TABLE t1 WRITE;
- FLUSH TABLES WITH READ LOCK;
+FLUSH TABLES WITH READ LOCK;
CREATE TABLE t2 AS SELECT * FROM t1;
ERROR HY000: Table 't2' was not locked with LOCK TABLES
UNLOCK TABLES;
@@ -84,7 +84,7 @@ UNLOCK TABLES;
DROP TABLE t1;
create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb;
lock tables t1 write;
- alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
- alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
+alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
+alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; alter table t1 auto_increment=0; //
unlock tables;
drop table t1;
diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result
index 7705961d08d..6df3cf61ddb 100644
--- a/mysql-test/r/lowercase_table.result
+++ b/mysql-test/r/lowercase_table.result
@@ -84,3 +84,27 @@ create table t2 like T1;
drop table t1, t2;
show tables;
Tables_in_test
+set names utf8;
+drop table if exists Ä°,Ä°Ä°;
+create table Ä° (s1 int);
+show create table Ä°;
+Table Create Table
+Ä° CREATE TABLE `i` (
+ `s1` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show tables;
+Tables_in_test
+i
+drop table Ä°;
+create table Ä°Ä° (s1 int);
+show create table Ä°Ä°;
+Table Create Table
+Ä°Ä° CREATE TABLE `ii` (
+ `s1` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show tables;
+Tables_in_test
+ii
+drop table Ä°Ä°;
+set names latin1;
+End of 5.0 tests
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index 50b0b6ae294..34e961395c4 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -96,3 +96,37 @@ i
2
affected rows: 1
affected rows: 0
+create table t1 (id int(10));
+insert into t1 values (1);
+CREATE VIEW v1 AS select t1.id as id from t1;
+CREATE VIEW v2 AS select t1.id as renamed from t1;
+CREATE VIEW v3 AS select t1.id + 12 as renamed from t1;
+select * from v1 group by id limit 1;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 v1 id id 3 10 1 Y 32768 0 63
+id
+1
+select * from v1 group by id limit 0;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 v1 id id 3 10 0 Y 32768 0 63
+id
+select * from v1 where id=1000 group by id;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 v1 id id 3 10 0 Y 32768 0 63
+id
+select * from v1 where id=1 group by id;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 v1 id id 3 10 1 Y 32768 0 63
+id
+1
+select * from v2 where renamed=1 group by renamed;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 v2 id renamed 3 10 1 Y 32768 0 63
+renamed
+1
+select * from v3 where renamed=1 group by renamed;
+Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
+def v3 renamed 8 12 0 Y 32896 0 63
+renamed
+drop table t1;
+drop view v1,v2,v3;
diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result
index e7fc22dac7c..6c19c429296 100644
--- a/mysql-test/r/mix_innodb_myisam_binlog.result
+++ b/mysql-test/r/mix_innodb_myisam_binlog.result
@@ -195,7 +195,7 @@ select (@before:=unix_timestamp())*0;
(@before:=unix_timestamp())*0
0
begin;
- select * from t1 for update;
+select * from t1 for update;
insert into t2 values (20);
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
select (@after:=unix_timestamp())*0;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index b4a7aa5cb76..78872f27c47 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -509,8 +509,8 @@ create table t2 (a int);
insert into t2 values (10), (20), (30);
create view v1 as select a as b, a/10 as a from t2;
lock table t1 write;
- alter table t1 add column c int default 100 after a;
- update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
+alter table t1 add column c int default 100 after a;
+update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
unlock tables;
select * from t1;
a c b
diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result
index 1053b1918fb..14267afc27e 100644
--- a/mysql-test/r/mysql.result
+++ b/mysql-test/r/mysql.result
@@ -149,4 +149,33 @@ ERROR at line 1: USE must be followed by a database name
\\
';
';
+create table t17583 (a int);
+insert into t17583 (a) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+select count(*) from t17583;
+count(*)
+1280
+drop table t17583;
+Test connect without db- or host-name => reconnect
+Test connect with dbname only => new dbname, old hostname
+ERROR 1064 (42000) at line 1: 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 'connecttest' at line 1
+Test connect with _invalid_ dbname only => new invalid dbname, old hostname
+ERROR 1049 (42000) at line 1: Unknown database 'invalid'
+ERROR 1049 (42000) at line 1: Unknown database 'invalid'
+Test connect with dbname + hostname
+Test connect with dbname + _invalid_ hostname
+ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno)
+ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'invalid_hostname' (errno)
+The commands reported in the bug report
+ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'cyril has found a bug :)XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' (errno)
+Too long dbname
+ERROR 1049 (42000) at line 1: Unknown database 'test_really_long_dbnamexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
+Too long hostname
+ERROR 2005 (HY000) at line 1: Unknown MySQL server host 'cyrils_superlonghostnameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' (errno)
End of 5.0 tests
diff --git a/mysql-test/r/mysqldump-max.result b/mysql-test/r/mysqldump-max.result
index 78867d1e430..9ae3e368e28 100644
--- a/mysql-test/r/mysqldump-max.result
+++ b/mysql-test/r/mysqldump-max.result
@@ -1,21 +1,4 @@
-drop table if exists t1;
-Warnings:
-Note 1051 Unknown table 't1'
-drop table if exists t2;
-Warnings:
-Note 1051 Unknown table 't2'
-drop table if exists t3;
-Warnings:
-Note 1051 Unknown table 't3'
-drop table if exists t4;
-Warnings:
-Note 1051 Unknown table 't4'
-drop table if exists t5;
-Warnings:
-Note 1051 Unknown table 't5'
-drop table if exists t6;
-Warnings:
-Note 1051 Unknown table 't6'
+drop table if exists t1, t2, t3, t4, t5, t6;
create table t1 (id int(8), name varchar(32));
create table t2 (id int(8), name varchar(32)) ENGINE="MyISAM";
create table t3 (id int(8), name varchar(32)) ENGINE="MEMORY";
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index ee50fc42203..54583febbc8 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -3196,5 +3196,27 @@ UNLOCK TABLES;
DROP TABLE `t1`;
#
+# Bug #19745: mysqldump --xml produces invalid xml
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (f1 int(10), data MEDIUMBLOB);
+INSERT INTO t1 VALUES(1,0xff00fef0);
+<?xml version="1.0"?>
+<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<database name="test">
+ <table_structure name="t1">
+ <field Field="f1" Type="int(10)" Null="YES" Key="" Extra="" />
+ <field Field="data" Type="mediumblob" Null="YES" Key="" Extra="" />
+ </table_structure>
+ <table_data name="t1">
+ <row>
+ <field name="f1">1</field>
+ <field name="data" xsi:type="xs:hexBinary">FF00FEF0</field>
+ </row>
+ </table_data>
+</database>
+</mysqldump>
+DROP TABLE t1;
+#
# End of 5.0 tests
#
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index 123091841df..1cfc482416e 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -152,8 +152,38 @@ mysqltest: At line 1: Missing delimiter
mysqltest: At line 1: End of line junk detected: "sleep 7
# Another comment
"
+mysqltest: At line 1: Missing delimiter
+mysqltest: At line 1: Missing delimiter
+mysqltest: At line 1: End of line junk detected: "disconnect default
+
+#
+# comment
+# comment2
+
+# comment 3
+--disable_query_log
+"
+mysqltest: At line 1: End of line junk detected: "disconnect default # comment
+# comment part2
+
+# comment 3
+--disable_query_log
+"
mysqltest: At line 1: Extra delimiter ";" found
mysqltest: At line 1: Extra delimiter ";" found
+mysqltest: At line 1: Missing argument(s) to 'error'
+mysqltest: At line 1: Missing argument(s) to 'error'
+mysqltest: At line 1: The sqlstate definition must start with an uppercase S
+mysqltest: At line 1: The error name definition must start with an uppercase E
+mysqltest: At line 1: Invalid argument to error: '9eeeee' - the errno may only consist of digits[0-9]
+mysqltest: At line 1: Invalid argument to error: '1sssss' - the errno may only consist of digits[0-9]
+mysqltest: At line 1: The sqlstate must be exactly 5 chars long
+mysqltest: At line 1: The sqlstate may only consist of digits[0-9] and _uppercase_ letters
+mysqltest: At line 1: The sqlstate must be exactly 5 chars long
+mysqltest: At line 1: Unknown SQL error name 'E9999'
+mysqltest: At line 1: Invalid argument to error: '999e9' - the errno may only consist of digits[0-9]
+mysqltest: At line 1: Invalid argument to error: '9b' - the errno may only consist of digits[0-9]
+mysqltest: At line 1: Too many errorcodes specified
MySQL
"MySQL"
MySQL: The world''s most popular open source database
@@ -168,8 +198,8 @@ source database
- most popular open
- source database
- MySQL: The world''s
--- most popular open
--- source database
+-- most popular
+-- open source database
# MySQL: The
--world''s
# most popular
@@ -195,8 +225,8 @@ source database
# source database
-- MySQL: The
-- world''s most
--- popular open
--- source database
+-- popular
+-- open source database
# MySQL: The
- world''s most
-- popular open
@@ -224,12 +254,11 @@ banana = banana
Not a banana: ba\$cat\$cat
mysqltest: At line 1: Missing arguments to let
mysqltest: At line 1: Missing variable name in let
-mysqltest: At line 1: Variable name in hi=hi does not start with '$'
mysqltest: At line 1: Missing assignment operator in let
mysqltest: At line 1: Missing assignment operator in let
mysqltest: At line 1: Missing assignment operator in let
mysqltest: At line 1: Missing variable name in let
-mysqltest: At line 1: Variable name in =hi does not start with '$'
+mysqltest: At line 1: Missing variable name in let
mysqltest: At line 1: Missing assignment operator in let
# Execute: --echo # <whatever> success: $success
# <whatever> success: 1
@@ -240,7 +269,7 @@ mysqltest: At line 1: Missing assignment operator in let
1
# Execute: echo $success ;
1
-mysqltest: At line 1: Missing file name in source
+mysqltest: At line 1: Missing required argument 'filename' to command 'source'
mysqltest: At line 1: Could not open file ./non_existingFile
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": At line 1: Source directives are nesting too deep
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/error.sql": At line 1: query 'garbage ' failed: 1064: 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 'garbage' at line 1
@@ -333,16 +362,16 @@ Counter is greater than 0, (counter=10)
Counter is not 0, (counter=0)
1
Testing while with not
-mysqltest: In included file "./include/mysqltest_while.inc": At line 64: Nesting too deeply
+mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest_while.inc": At line 64: Nesting too deeply
mysqltest: At line 1: missing '(' in while
mysqltest: At line 1: missing ')' in while
mysqltest: At line 1: Missing '{' after while. Found "dec $i"
mysqltest: At line 1: Stray '}' - end of block before beginning
mysqltest: At line 1: Stray 'end' command - end of block before beginning
-mysqltest: At line 1: query '' failed: 1065: Query was empty
+mysqltest: At line 1: query '{' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '{' at line 1
mysqltest: At line 1: Missing '{' after while. Found "echo hej"
mysqltest: At line 3: Missing end of block
-mysqltest: At line 1: Missing newline between while and '{'
+mysqltest: At line 3: Missing end of block
mysqltest: At line 1: missing '(' in if
mysqltest: At line 1: Stray 'end' command - end of block before beginning
select "b" bs col1, "c" bs col2;
@@ -372,17 +401,15 @@ mysqltest: At line 1: Wrong column number to replace_column in 'replace_column 1
mysqltest: At line 1: Invalid integer argument "10!"
mysqltest: At line 1: End of line junk detected: "!"
mysqltest: At line 1: Invalid integer argument "a"
-mysqltest: At line 1: Syntax error in connect - expected '(' found 'mysqltest: At line 1: Missing connection host
-mysqltest: At line 1: Missing connection host
-mysqltest: At line 1: Missing connection user
-mysqltest: At line 1: Missing connection user
-mysqltest: At line 1: Missing connection password
-mysqltest: At line 1: Missing connection db
-mysqltest: At line 1: Could not open connection 'con2': 1049 Unknown database 'illegal_db'
+mysqltest: At line 1: Missing required argument 'connection name' to command 'connect'
+mysqltest: At line 1: Missing required argument 'connection name' to command 'connect'
+mysqltest: At line 1: Missing required argument 'host' to command 'connect'
+mysqltest: At line 1: Missing required argument 'host' to command 'connect'
+mysqltest: At line 1: query 'connect con2,localhost,root,,illegal_db' failed: 1049: Unknown database 'illegal_db'
mysqltest: At line 1: Illegal argument for port: 'illegal_port'
mysqltest: At line 1: Illegal option to connect: SMTP
OK
-mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 7: Connection limit exhausted - increase MAX_CONS in mysqltest.c
+mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 7: Connection limit exhausted, you can have max 128 connections
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 3: connection 'test_con1' not found in connection pool
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/mysqltest.sql": At line 2: Connection test_con1 already exists
connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET);
@@ -450,3 +477,47 @@ sleep;
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 'sleep' at line 1
;
ERROR 42000: Query was empty
+select "b" as col1, "c" as col2;
+col1 col2
+b c
+select "b" as col1, "b" as col2, "c" as col3;
+col1 col2 col3
+b b c
+seled "b" bs col1, "d" bs col2;
+col1 col2
+b d
+select "raspberry and strawberry","blackberry","tomato";
+raspberry and strawberry blackberry tomato
+raspberry and strawberry blackberry tomato
+mysqltest: At line 1: Error parsing replace_regex "a"
+mysqltest: At line 1: Error parsing replace_regex "a;"
+mysqltest: At line 1: Error parsing replace_regex "a"
+mysqltest: At line 1: Error parsing replace_regex "a "
+mysqltest: At line 1: Error parsing replace_regex "a b"
+mysqltest: At line 1: Error parsing replace_regex "/a b c"
+mysqltest: At line 1: Error parsing replace_regex "/a /b c "
+create table t1 (a int, b int);
+insert into t1 values (1,3);
+insert into t1 values (2,4);
+select * from t1;
+a D
+1 1
+1 4
+drop table t1;
+mysqltest: At line 1: Missing required argument 'filename' to command 'remove_file'
+mysqltest: At line 1: Missing required argument 'filename' to command 'write_file'
+mysqltest: At line 1: End of file encountered before 'EOF' delimiter was found
+mysqltest: At line 1: End of line junk detected: "write_file filename ";
+"
+mysqltest: At line 1: Missing required argument 'filename' to command 'file_exists'
+mysqltest: At line 1: Missing required argument 'from_file' to command 'copy_file'
+mysqltest: At line 1: Missing required argument 'to_file' to command 'copy_file'
+hello
+hello
+hello
+mysqltest: At line 1: Max delimiter length(16) exceeded
+hello
+hello
+mysqltest: At line 1: test of die
+Some output
+End of tests
diff --git a/mysql-test/r/ndb_charset.result b/mysql-test/r/ndb_charset.result
index 3763e20e59a..9e519c39496 100644
--- a/mysql-test/r/ndb_charset.result
+++ b/mysql-test/r/ndb_charset.result
@@ -112,9 +112,9 @@ unique key(a)
) engine=ndb;
insert into t1 values(1, 'aAa');
insert into t1 values(2, 'aaa');
-ERROR 23000: Duplicate entry '2' for key 1
+ERROR 23000: Duplicate entry '' for key 0
insert into t1 values(3, 'AAA');
-ERROR 23000: Duplicate entry '3' for key 1
+ERROR 23000: Duplicate entry '' for key 0
select * from t1 order by p;
p a
1 aAa
@@ -138,9 +138,9 @@ unique key(a)
) engine=ndb;
insert into t1 values (1,'A'),(2,'b '),(3,'C '),(4,'d '),(5,'E'),(6,'f');
insert into t1 values(99,'b');
-ERROR 23000: Duplicate entry '99' for key 1
+ERROR 23000: Duplicate entry '' for key 0
insert into t1 values(99,'a ');
-ERROR 23000: Duplicate entry '99' for key 1
+ERROR 23000: Duplicate entry '' for key 0
select a,length(a) from t1 order by a;
a length(a)
A 1
diff --git a/mysql-test/r/ndb_condition_pushdown.result b/mysql-test/r/ndb_condition_pushdown.result
index aefbcbf6ede..6012c9b6969 100644
--- a/mysql-test/r/ndb_condition_pushdown.result
+++ b/mysql-test/r/ndb_condition_pushdown.result
@@ -1782,6 +1782,28 @@ select * from t5 where b like '%jo%' order by a;
a b
1 jonas
3 johan
+set engine_condition_pushdown = off;
+select auto from t1 where date_time like '1902-02-02 %' order by auto;
+auto
+2
+select auto from t1 where date_time not like '1902-02-02 %' order by auto;
+auto
+3
+4
+set engine_condition_pushdown = on;
+explain select auto from t1 where date_time like '1902-02-02 %';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+select auto from t1 where date_time like '1902-02-02 %' order by auto;
+auto
+2
+explain select auto from t1 where date_time not like '1902-02-02 %';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+select auto from t1 where date_time not like '1902-02-02 %' order by auto;
+auto
+3
+4
drop table t1;
create table t1 (a int, b varchar(3), primary key using hash(a))
engine=ndb;
diff --git a/mysql-test/r/ndb_config.result b/mysql-test/r/ndb_config.result
index ef5c924a398..9470cd7256c 100644
--- a/mysql-test/r/ndb_config.result
+++ b/mysql-test/r/ndb_config.result
@@ -9,3 +9,6 @@ ndbd,1,localhost ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndb_mgmd,5,l
ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndb_mgmd,6,localhost mysqld,1, mysqld,7, mysqld,8, mysqld,9, mysqld,10,
ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndbd,6,localhost ndb_mgmd,1,localhost ndb_mgmd,2,localhost mysqld,11, mysqld,12, mysqld,13, mysqld,14, mysqld,15,
shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2
+1 2 3
+
+1 2 3
diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result
index 7864a5d1354..ce4759ad553 100644
--- a/mysql-test/r/ndb_index_unique.result
+++ b/mysql-test/r/ndb_index_unique.result
@@ -22,7 +22,7 @@ select * from t1 where b = 4 order by a;
a b c
3 4 6
insert into t1 values(8, 2, 3);
-ERROR 23000: Duplicate entry '8' for key 1
+ERROR 23000: Duplicate entry '' for key 0
select * from t1 order by a;
a b c
1 2 3
@@ -89,7 +89,7 @@ a b c
1 1 1
4 4 NULL
insert into t1 values(5,1,1);
-ERROR 23000: Duplicate entry '5' for key 1
+ERROR 23000: Duplicate entry '' for key 0
drop table t1;
CREATE TABLE t2 (
a int unsigned NOT NULL PRIMARY KEY,
@@ -112,7 +112,7 @@ select * from t2 where b = 4 order by a;
a b c
3 4 6
insert into t2 values(8, 2, 3);
-ERROR 23000: Duplicate entry '8' for key 1
+ERROR 23000: Duplicate entry '' for key 0
select * from t2 order by a;
a b c
1 2 3
@@ -177,7 +177,7 @@ pk a
3 NULL
4 4
insert into t1 values (5,0);
-ERROR 23000: Duplicate entry '5' for key 1
+ERROR 23000: Duplicate entry '' for key 0
select * from t1 order by pk;
pk a
-1 NULL
@@ -210,7 +210,7 @@ pk a b c
0 NULL 18 NULL
1 3 19 abc
insert into t2 values(2,3,19,'abc');
-ERROR 23000: Duplicate entry '2' for key 1
+ERROR 23000: Duplicate entry '' for key 0
select * from t2 order by pk;
pk a b c
-1 1 17 NULL
@@ -630,7 +630,7 @@ create table t1 (a int primary key, b varchar(1000) not null, unique key (b))
engine=ndb charset=utf8;
insert into t1 values (1, repeat(_utf8 0xe288ab6474, 200));
insert into t1 values (2, repeat(_utf8 0xe288ab6474, 200));
-ERROR 23000: Duplicate entry '2' for key 1
+ERROR 23000: Duplicate entry '' for key 0
select a, sha1(b) from t1;
a sha1(b)
1 08f5d02c8b8bc244f275bdfc22c42c5cab0d9d7d
diff --git a/mysql-test/r/ndb_multi.result b/mysql-test/r/ndb_multi.result
index bd3af223a65..5d75722982f 100644
--- a/mysql-test/r/ndb_multi.result
+++ b/mysql-test/r/ndb_multi.result
@@ -28,8 +28,6 @@ Handler_discover 0
drop table t1;
create table t1 (a int) engine=ndbcluster;
insert into t1 value (2);
-select * from t1;
-ERROR HY000: Got error 241 'Invalid schema object version' from ndbcluster
flush table t1;
select * from t1;
a
@@ -54,13 +52,13 @@ a b c last_col
1 Hi! 89 Longtext column
show status like 'handler_discover%';
Variable_name Value
-Handler_discover 1
+Handler_discover 2
show tables like 't4';
Tables_in_test (t4)
t4
show status like 'handler_discover%';
Variable_name Value
-Handler_discover 2
+Handler_discover 3
show tables;
Tables_in_test
t1
@@ -69,3 +67,35 @@ t3
t4
drop table t1, t2, t3, t4;
drop table t1, t3, t4;
+create table t1(c1 int key)ENGINE=MyISAM;
+insert into t1 values(1),(3),(5);
+select * from t1 order by c1;
+c1
+1
+3
+5
+create table t1(c1 int key)ENGINE=MyISAM;
+insert into t1 values(100),(344),(533);
+select * from t1 order by c1;
+c1
+100
+344
+533
+alter table t1 engine=ndb;
+show tables;
+Tables_in_test
+t1
+Warnings:
+Warning 1050 Local table test.t1 shadows ndb table
+select * from t1 order by c1;
+c1
+100
+344
+533
+drop table t1;
+select * from t1 order by c1;
+c1
+1
+3
+5
+drop table t1;
diff --git a/mysql-test/r/ndb_update.result b/mysql-test/r/ndb_update.result
index c2247564e65..164d1bd700c 100644
--- a/mysql-test/r/ndb_update.result
+++ b/mysql-test/r/ndb_update.result
@@ -18,7 +18,7 @@ pk1 b c
2 2 2
4 1 1
UPDATE t1 set pk1 = 1, c = 2 where pk1 = 4;
-ERROR 23000: Duplicate entry '1' for key 1
+ERROR 23000: Duplicate entry '' for key 0
select * from t1 order by pk1;
pk1 b c
0 0 0
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index 8f9fd50eced..914fe25119f 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -47,7 +47,7 @@ drop table t1;
mysqltest: Could not open connection 'default': 2026 SSL connection error
mysqltest: Could not open connection 'default': 2026 SSL connection error
mysqltest: Could not open connection 'default': 2026 SSL connection error
-Error when connection to server using SSL:Unable to get private key from ''
+SSL error: Unable to get private key from ''
mysqltest: Could not open connection 'default': 2026 SSL connection error
-Error when connection to server using SSL:Unable to get certificate from ''
+SSL error: Unable to get certificate from ''
mysqltest: Could not open connection 'default': 2026 SSL connection error
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index be29b310434..7b04c1acdc0 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -760,13 +760,6 @@ xxxxxxxxxxxxxxxxxxxaa
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxz
drop table t1;
-create table t1 (a int not null, b int not null, c int not null);
-insert t1 values (1,1,1),(1,1,2),(1,2,1);
-select a, b from t1 group by a, b order by sum(c);
-a b
-1 2
-1 1
-drop table t1;
create table t1 (
`sid` decimal(8,0) default null,
`wnid` varchar(11) not null default '',
@@ -881,6 +874,13 @@ num (select num + 2 FROM t1 LIMIT 1)
SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a;
ERROR 42S22: Unknown column 'num' in 'on clause'
DROP TABLE t1;
+create table t1 (a int not null, b int not null, c int not null);
+insert t1 values (1,1,1),(1,1,2),(1,2,1);
+select a, b from t1 group by a, b order by sum(c);
+a b
+1 2
+1 1
+drop table t1;
CREATE TABLE t1 (a int, b int, PRIMARY KEY (a));
INSERT INTO t1 VALUES (1,1), (2,2), (3,3);
explain SELECT t1.b as a, t2.b as c FROM
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 048c3ae46d3..234c12955d9 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -795,12 +795,12 @@ set @old_max_prepared_stmt_count= @@max_prepared_stmt_count;
show variables like 'max_prepared_stmt_count';
Variable_name Value
max_prepared_stmt_count 16382
-show variables like 'prepared_stmt_count';
+show status like 'prepared_stmt_count';
Variable_name Value
-prepared_stmt_count 0
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
-@@max_prepared_stmt_count @@prepared_stmt_count
-16382 0
+Prepared_stmt_count 0
+select @@max_prepared_stmt_count;
+@@max_prepared_stmt_count
+16382
set global max_prepared_stmt_count=-1;
select @@max_prepared_stmt_count;
@@max_prepared_stmt_count
@@ -819,67 +819,70 @@ set max_prepared_stmt_count=1;
ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL
set local max_prepared_stmt_count=1;
ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL
-set local prepared_stmt_count=0;
-ERROR HY000: Variable 'prepared_stmt_count' is a read only variable
-set @@prepared_stmt_count=0;
-ERROR HY000: Variable 'prepared_stmt_count' is a read only variable
-set global prepared_stmt_count=1;
-ERROR HY000: Variable 'prepared_stmt_count' is a read only variable
set global max_prepared_stmt_count=1;
select @@max_prepared_stmt_count;
@@max_prepared_stmt_count
1
set global max_prepared_stmt_count=0;
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
-@@max_prepared_stmt_count @@prepared_stmt_count
-0 0
+select @@max_prepared_stmt_count;
+@@max_prepared_stmt_count
+0
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 0
prepare stmt from "select 1";
ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 0)
-select @@prepared_stmt_count;
-@@prepared_stmt_count
-0
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 0
set global max_prepared_stmt_count=1;
prepare stmt from "select 1";
-select @@prepared_stmt_count;
-@@prepared_stmt_count
-1
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 1
prepare stmt1 from "select 1";
ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 1)
-select @@prepared_stmt_count;
-@@prepared_stmt_count
-1
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 1
deallocate prepare stmt;
-select @@prepared_stmt_count;
-@@prepared_stmt_count
-0
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 0
prepare stmt from "select 1";
-select @@prepared_stmt_count;
-@@prepared_stmt_count
-1
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 1
prepare stmt from "select 2";
-select @@prepared_stmt_count;
-@@prepared_stmt_count
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 1
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 1
+select @@max_prepared_stmt_count;
+@@max_prepared_stmt_count
1
-select @@prepared_stmt_count, @@max_prepared_stmt_count;
-@@prepared_stmt_count @@max_prepared_stmt_count
-1 1
set global max_prepared_stmt_count=0;
prepare stmt from "select 1";
ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 0)
execute stmt;
ERROR HY000: Unknown prepared statement handler (stmt) given to EXECUTE
-select @@prepared_stmt_count;
-@@prepared_stmt_count
-0
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 0
prepare stmt from "select 1";
ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 0)
-select @@prepared_stmt_count;
-@@prepared_stmt_count
-0
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 0
set global max_prepared_stmt_count=3;
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
-@@max_prepared_stmt_count @@prepared_stmt_count
-3 0
+select @@max_prepared_stmt_count;
+@@max_prepared_stmt_count
+3
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 0
prepare stmt from "select 1";
prepare stmt from "select 2";
prepare stmt1 from "select 3";
@@ -887,13 +890,13 @@ prepare stmt2 from "select 4";
ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 3)
prepare stmt2 from "select 4";
ERROR 42000: Can't create more than max_prepared_stmt_count statements (current value: 3)
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
-@@max_prepared_stmt_count @@prepared_stmt_count
-3 3
+select @@max_prepared_stmt_count;
+@@max_prepared_stmt_count
+3
+show status like 'prepared_stmt_count';
+Variable_name Value
+Prepared_stmt_count 3
deallocate prepare stmt;
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
-@@max_prepared_stmt_count @@prepared_stmt_count
-3 0
set global max_prepared_stmt_count= @old_max_prepared_stmt_count;
drop table if exists t1;
create temporary table if not exists t1 (a1 int);
@@ -956,7 +959,103 @@ GROUP_CONCAT(Track SEPARATOR ', ')
CAD
DEALLOCATE PREPARE STMT;
DROP TABLE t1;
-End of 4.1 tests
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT, INDEX(i));
+INSERT INTO t1 VALUES (1);
+PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(COUNT(i) = 1) COUNT(i)
+0 0
+SET @a = 1;
+EXECUTE stmt USING @a;
+(COUNT(i) = 1) COUNT(i)
+1 1
+SET @a = 0;
+EXECUTE stmt USING @a;
+(COUNT(i) = 1) COUNT(i)
+0 0
+PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(AVG(i) = 1) AVG(i)
+NULL NULL
+SET @a = 1;
+EXECUTE stmt USING @a;
+(AVG(i) = 1) AVG(i)
+1 1.0000
+SET @a = 0;
+EXECUTE stmt USING @a;
+(AVG(i) = 1) AVG(i)
+NULL NULL
+PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(VARIANCE(i) = 1) VARIANCE(i)
+NULL NULL
+SET @a = 1;
+EXECUTE stmt USING @a;
+(VARIANCE(i) = 1) VARIANCE(i)
+0 0.0000
+SET @a = 0;
+EXECUTE stmt USING @a;
+(VARIANCE(i) = 1) VARIANCE(i)
+NULL NULL
+PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(STDDEV(i) = 1) STDDEV(i)
+NULL NULL
+SET @a = 1;
+EXECUTE stmt USING @a;
+(STDDEV(i) = 1) STDDEV(i)
+0 0.0000
+SET @a = 0;
+EXECUTE stmt USING @a;
+(STDDEV(i) = 1) STDDEV(i)
+NULL NULL
+PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_OR(i) = 1) BIT_OR(i)
+0 0
+SET @a = 1;
+EXECUTE stmt USING @a;
+(BIT_OR(i) = 1) BIT_OR(i)
+1 1
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_OR(i) = 1) BIT_OR(i)
+0 0
+PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_AND(i) = 1) BIT_AND(i)
+0 18446744073709551615
+SET @a = 1;
+EXECUTE stmt USING @a;
+(BIT_AND(i) = 1) BIT_AND(i)
+1 1
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_AND(i) = 1) BIT_AND(i)
+0 18446744073709551615
+PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_XOR(i) = 1) BIT_XOR(i)
+0 0
+SET @a = 1;
+EXECUTE stmt USING @a;
+(BIT_XOR(i) = 1) BIT_XOR(i)
+1 1
+SET @a = 0;
+EXECUTE stmt USING @a;
+(BIT_XOR(i) = 1) BIT_XOR(i)
+0 0
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+End of 4.1 tests.
create table t1 (a varchar(20));
insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1';
@@ -1379,4 +1478,40 @@ i
1
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1;
+INSERT INTO t1 VALUES (1), (2);
+SELECT t1.i FROM t1 JOIN v1 ON t1.i = v1.i
+WHERE EXISTS (SELECT * FROM t1 WHERE v1.i = 1);
+i
+1
+PREPARE stmt FROM "SELECT t1.i FROM t1 JOIN v1 ON t1.i = v1.i
+WHERE EXISTS (SELECT * FROM t1 WHERE v1.i = 1)";
+EXECUTE stmt;
+i
+1
+EXECUTE stmt;
+i
+1
+DEALLOCATE PREPARE stmt;
+DROP VIEW v1;
+DROP TABLE t1;
+DROP PROCEDURE IF EXISTS p1;
+flush status;
+prepare sq from 'show status like "slow_queries"';
+execute sq;
+Variable_name Value
+Slow_queries 0
+prepare no_index from 'select 1 from information_schema.tables limit 1';
+execute sq;
+Variable_name Value
+Slow_queries 0
+execute no_index;
+1
+1
+execute sq;
+Variable_name Value
+Slow_queries 1
+deallocate prepare no_index;
+deallocate prepare sq;
End of 5.0 tests.
diff --git a/mysql-test/r/ps_11bugs.result b/mysql-test/r/ps_11bugs.result
index c849c25d646..ebe161f46b3 100644
--- a/mysql-test/r/ps_11bugs.result
+++ b/mysql-test/r/ps_11bugs.result
@@ -130,3 +130,36 @@ prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1)
execute st_18492;
a
drop table t1;
+create table t1 (a int, b varchar(4));
+create table t2 (a int, b varchar(4), primary key(a));
+prepare stmt1 from 'insert into t1 (a, b) values (?, ?)';
+prepare stmt2 from 'insert into t2 (a, b) values (?, ?)';
+set @intarg= 11;
+set @varchararg= '2222';
+execute stmt1 using @intarg, @varchararg;
+execute stmt2 using @intarg, @varchararg;
+set @intarg= 12;
+execute stmt1 using @intarg, @UNDEFINED;
+execute stmt2 using @intarg, @UNDEFINED;
+set @intarg= 13;
+execute stmt1 using @UNDEFINED, @varchararg;
+execute stmt2 using @UNDEFINED, @varchararg;
+ERROR 23000: Column 'a' cannot be null
+set @intarg= 14;
+set @nullarg= Null;
+execute stmt1 using @UNDEFINED, @nullarg;
+execute stmt2 using @nullarg, @varchararg;
+ERROR 23000: Column 'a' cannot be null
+select * from t1;
+a b
+11 2222
+12 NULL
+NULL 2222
+NULL NULL
+select * from t2;
+a b
+11 2222
+12 NULL
+drop table t1;
+drop table t2;
+End of 5.0 tests.
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 5224280e134..d2b022a93fb 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -932,8 +932,7 @@ abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzab
zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba
flush query cache;
drop table t1, t2;
-set GLOBAL query_cache_size=1355776
-#;
+set GLOBAL query_cache_size=1355776;
flush status;
CREATE TABLE t1 (
`date` datetime NOT NULL default '0000-00-00 00:00:00',
@@ -1274,3 +1273,51 @@ Variable_name Value
Last_query_cost 0.000000
drop table t1;
SET GLOBAL query_cache_size=0;
+set global query_cache_size=1024*1024;
+flush status;
+create table t1 (a int);
+insert into t1 (a) values (1), (2), (3);
+select * from t1;
+a
+1
+2
+3
+show status like 'Qcache_hits';
+Variable_name Value
+Qcache_hits 0
+select * from t1;
+a
+1
+2
+3
+show status like 'Qcache_hits';
+Variable_name Value
+Qcache_hits 1
+create table t2 like t1;
+select * from t1;
+a
+1
+2
+3
+show status like 'Qcache_hits';
+Variable_name Value
+Qcache_hits 2
+insert into t2 select * from t1;
+select * from t1;
+a
+1
+2
+3
+show status like 'Qcache_hits';
+Variable_name Value
+Qcache_hits 3
+drop table t1, t2;
+create table t1(c1 int);
+create table t2(c1 int);
+create table t3(c1 int);
+create view v1 as select t3.c1 as c1 from t3,t2 where t3.c1 = t2.c1;
+start transaction;
+insert into t1(c1) select c1 from v1;
+drop table t1, t2, t3;
+drop view v1;
+set global query_cache_size=0;
diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result
index 4226738725a..8e5df012cfb 100644
--- a/mysql-test/r/query_cache_notembedded.result
+++ b/mysql-test/r/query_cache_notembedded.result
@@ -326,7 +326,7 @@ insert into t1 values(3);
set i_var = sleep(3);
return 0;
end;|
- select f1();
+select f1();
select sleep(4);
sleep(4)
0
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index add95613d62..c96173e74cc 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -665,6 +665,16 @@ OR ((pk4 =1) AND (((pk1 IN ( 7, 2, 1 ))) OR (pk1 =522)) AND ((pk2 IN ( 0, 2635))
pk1 pk2 pk3 pk4 filler
2621 2635 1000015 0 filler
drop table t1, t2;
+create table t1(a char(2), key(a(1)));
+insert into t1 values ('x'), ('xx');
+explain select a from t1 where a > 'x';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 2 NULL 2 Using where
+select a from t1 where a > 'x';
+a
+xx
+drop table t1;
+End of 4.1 tests
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
status varchar(20),
diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result
index 345270231ef..1257a668cce 100644
--- a/mysql-test/r/rename.result
+++ b/mysql-test/r/rename.result
@@ -43,7 +43,7 @@ Note 1051 Unknown table 't4'
CREATE TABLE t1 (a int);
CREATE TABLE t3 (a int);
FLUSH TABLES WITH READ LOCK;
- RENAME TABLE t1 TO t2, t3 to t4;
+RENAME TABLE t1 TO t2, t3 to t4;
show tables;
Tables_in_test
t1
@@ -54,6 +54,7 @@ Tables_in_test
t2
t4
drop table t2, t4;
+End of 4.1 tests
create table t1(f1 int);
create view v1 as select * from t1;
alter table v1 rename to v2;
@@ -64,3 +65,4 @@ rename table v2 to v1;
ERROR 42S01: Table 'v1' already exists
drop view v1;
drop table t1;
+End of 5.0 tests
diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result
index ef4226e07b5..3b4cd05f640 100644
--- a/mysql-test/r/rpl000001.result
+++ b/mysql-test/r/rpl000001.result
@@ -44,7 +44,7 @@ create table t2(id int);
insert into t2 values(connection_id());
create temporary table t3(n int);
insert into t3 select get_lock('crash_lock%20C', 1) from t2;
- update t1 set n = n + get_lock('crash_lock%20C', 2);
+update t1 set n = n + get_lock('crash_lock%20C', 2);
select (@id := id) - id from t2;
(@id := id) - id
0
diff --git a/mysql-test/r/rpl000018.result b/mysql-test/r/rpl000018.result
deleted file mode 100644
index b71f6492b97..00000000000
--- a/mysql-test/r/rpl000018.result
+++ /dev/null
@@ -1,14 +0,0 @@
-reset master;
-reset slave;
-start slave;
-show binary logs;
-Log_name
-master-bin.000001
-master-bin.000002
-drop table if exists t1;
-create table t1(n int);
-insert into t1 values (3351);
-select * from t1;
-n
-3351
-drop table t1;
diff --git a/mysql-test/r/rpl_chain_temp_table.result b/mysql-test/r/rpl_chain_temp_table.result
deleted file mode 100644
index 5ece80565c7..00000000000
--- a/mysql-test/r/rpl_chain_temp_table.result
+++ /dev/null
@@ -1,30 +0,0 @@
-slave stop;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-slave start;
-reset master;
-change master to master_host='127.0.0.1',master_port=9307, master_user='root';
-start slave;
-create temporary table t1 (a int);
-create temporary table t1 (a int);
-show status like 'slave_open_temp_tables';
-Variable_name Value
-Slave_open_temp_tables 2
-create temporary table t1 (a int);
-create temporary table t1 (a int);
-show status like 'slave_open_temp_tables';
-Variable_name Value
-Slave_open_temp_tables 4
-stop slave;
-insert into t1 values(1);
-create table t2 as select * from t1;
-start slave;
-show status like 'slave_open_temp_tables';
-Variable_name Value
-Slave_open_temp_tables 4
-select * from t2;
-a
-1
-drop table t2;
diff --git a/mysql-test/r/rpl_deadlock.result b/mysql-test/r/rpl_deadlock.result
index 541e12b806f..bea7fd81616 100644
--- a/mysql-test/r/rpl_deadlock.result
+++ b/mysql-test/r/rpl_deadlock.result
@@ -6,7 +6,7 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
create table t1 (a int not null, key(a)) engine=innodb;
create table t2 (a int not null, key(a)) engine=innodb;
-create table t3 (a int) engine=innodb;
+create table t3 (a int unique) engine=innodb;
create table t4 (a int) engine=innodb;
show variables like 'slave_transaction_retries';
Variable_name Value
@@ -35,14 +35,14 @@ begin;
select * from t1 for update;
a
start slave;
-insert into t2 values(22);
+insert into t2 values(201);
commit;
select * from t1;
a
1
select * from t2;
a
-22
+201
show slave status;
Slave_IO_State #
Master_Host 127.0.0.1
@@ -50,7 +50,7 @@ Master_User root
Master_Port MASTER_MYPORT
Connect_Retry 1
Master_Log_File master-bin.000001
-Read_Master_Log_Pos 18911
+Read_Master_Log_Pos 18918
Relay_Log_File #
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
@@ -65,7 +65,7 @@ Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
-Exec_Master_Log_Pos 18911
+Exec_Master_Log_Pos 18918
Relay_Log_Space #
Until_Condition None
Until_Log_File
@@ -78,12 +78,16 @@ Master_SSL_Cipher
Master_SSL_Key
Seconds_Behind_Master #
stop slave;
-change master to master_log_pos=532;
+delete from t3;
+change master to master_log_pos=539;
begin;
select * from t2 for update;
a
-22
+201
start slave;
+select count(*) from t3 /* must be zero */;
+count(*)
+0
commit;
select * from t1;
a
@@ -91,7 +95,7 @@ a
1
select * from t2;
a
-22
+201
show slave status;
Slave_IO_State #
Master_Host 127.0.0.1
@@ -99,7 +103,7 @@ Master_User root
Master_Port MASTER_MYPORT
Connect_Retry 1
Master_Log_File master-bin.000001
-Read_Master_Log_Pos 18911
+Read_Master_Log_Pos 18918
Relay_Log_File #
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
@@ -114,7 +118,7 @@ Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
-Exec_Master_Log_Pos 18911
+Exec_Master_Log_Pos 18918
Relay_Log_Space #
Until_Condition None
Until_Log_File
@@ -128,12 +132,16 @@ Master_SSL_Key
Seconds_Behind_Master #
set global max_relay_log_size=0;
stop slave;
-change master to master_log_pos=532;
+delete from t3;
+change master to master_log_pos=539;
begin;
select * from t2 for update;
a
-22
+201
start slave;
+select count(*) from t3 /* must be zero */;
+count(*)
+0
commit;
select * from t1;
a
@@ -142,7 +150,7 @@ a
1
select * from t2;
a
-22
+201
show slave status;
Slave_IO_State #
Master_Host 127.0.0.1
@@ -150,7 +158,7 @@ Master_User root
Master_Port MASTER_MYPORT
Connect_Retry 1
Master_Log_File master-bin.000001
-Read_Master_Log_Pos 18911
+Read_Master_Log_Pos 18918
Relay_Log_File #
Relay_Log_Pos #
Relay_Master_Log_File master-bin.000001
@@ -165,7 +173,7 @@ Replicate_Wild_Ignore_Table
Last_Errno 0
Last_Error
Skip_Counter 0
-Exec_Master_Log_Pos 18911
+Exec_Master_Log_Pos 18918
Relay_Log_Space #
Until_Condition None
Until_Log_File
diff --git a/mysql-test/r/rpl_error_ignored_table.result b/mysql-test/r/rpl_error_ignored_table.result
index a0a808ce9a8..b813941a782 100644
--- a/mysql-test/r/rpl_error_ignored_table.result
+++ b/mysql-test/r/rpl_error_ignored_table.result
@@ -20,7 +20,7 @@ create table t2 (a int primary key);
insert into t2 values(1);
create table t3 (id int);
insert into t3 values(connection_id());
- update t2 set a = a + 1 + get_lock('crash_lock%20C', 10);
+update t2 set a = a + 1 + get_lock('crash_lock%20C', 10);
select (@id := id) - id from t3;
(@id := id) - id
0
diff --git a/mysql-test/r/rpl_failsafe.result b/mysql-test/r/rpl_failsafe.result
deleted file mode 100644
index 956555f9318..00000000000
--- a/mysql-test/r/rpl_failsafe.result
+++ /dev/null
@@ -1,34 +0,0 @@
-stop slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-start slave;
-show variables like 'rpl_recovery_rank';
-Variable_name Value
-rpl_recovery_rank 1
-show status like 'Rpl_status';
-Variable_name Value
-Rpl_status AUTH_MASTER
-create table t1(n int);
-drop table t1;
-show variables like 'rpl_recovery_rank';
-Variable_name Value
-rpl_recovery_rank 2
-show status like 'Rpl_status';
-Variable_name Value
-Rpl_status ACTIVE_SLAVE
-start slave;
-show variables like 'rpl_recovery_rank';
-Variable_name Value
-rpl_recovery_rank 3
-show status like 'Rpl_status';
-Variable_name Value
-Rpl_status ACTIVE_SLAVE
-start slave;
-show variables like 'rpl_recovery_rank';
-Variable_name Value
-rpl_recovery_rank 4
-show status like 'Rpl_status';
-Variable_name Value
-Rpl_status ACTIVE_SLAVE
diff --git a/mysql-test/r/rpl_heap.result b/mysql-test/r/rpl_heap.result
deleted file mode 100644
index 1facbcb7676..00000000000
--- a/mysql-test/r/rpl_heap.result
+++ /dev/null
@@ -1,29 +0,0 @@
-reset master;
-drop table if exists t1;
-create table t1 type=HEAP select 10 as a;
-insert into t1 values(11);
-show binlog events from 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.001 79 Query 1 79 use `test`; create table t1 type=HEAP select 10 as a
-master-bin.001 154 Query 1 154 use `test`; insert into t1 values(11)
-reset slave;
-start slave;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `a` bigint(2) NOT NULL default '0'
-) TYPE=HEAP
-select * from t1;
-a
-10
-11
-select * from t1;
-a
-select * from t1 limit 10;
-a
-show binlog events in 'master-bin.002' from 79;
-Log_name Pos Event_type Server_id Orig_log_pos Info
-master-bin.002 79 Query 1 79 use `test`; DELETE FROM `test`.`t1`
-select * from t1;
-a
-drop table t1;
diff --git a/mysql-test/r/rpl_ignore_table.result b/mysql-test/r/rpl_ignore_table.result
index 356a9dcb2f8..136cf5cc5eb 100644
--- a/mysql-test/r/rpl_ignore_table.result
+++ b/mysql-test/r/rpl_ignore_table.result
@@ -14,3 +14,19 @@ SELECT * FROM t4;
a
DROP TABLE t1;
DROP TABLE t4;
+DROP TABLE IF EXISTS t5;
+CREATE TABLE t5 (
+word varchar(50) collate utf8_unicode_ci NOT NULL default ''
+) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+SET @@session.character_set_client=33,@@session.collation_connection=192;
+CREATE TEMPORARY TABLE tmptbl504451f4258$1 (id INT NOT NULL) ENGINE=MEMORY;
+INSERT INTO t5 (word) VALUES ('TEST’');
+SELECT HEX(word) FROM t5;
+HEX(word)
+54455354E28099
+SELECT HEX(word) FROM t5;
+HEX(word)
+54455354E28099
+SELECT * FROM tmptbl504451f4258$1;
+ERROR 42S02: Table 'test.tmptbl504451f4258$1' doesn't exist
+DROP TABLE t5;
diff --git a/mysql-test/r/rpl_master_pos_wait.result b/mysql-test/r/rpl_master_pos_wait.result
index 2f3e47999cf..f0f48de4e07 100644
--- a/mysql-test/r/rpl_master_pos_wait.result
+++ b/mysql-test/r/rpl_master_pos_wait.result
@@ -12,7 +12,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select master_pos_wait(_latin1'master-bin.999999',0,2) AS `master_pos_wait('master-bin.999999',0,2)`
- select master_pos_wait('master-bin.999999',0);
+select master_pos_wait('master-bin.999999',0);
stop slave sql_thread;
master_pos_wait('master-bin.999999',0)
NULL
diff --git a/mysql-test/r/rpl_packet.result b/mysql-test/r/rpl_packet.result
new file mode 100644
index 00000000000..a5c9b43cabb
--- /dev/null
+++ b/mysql-test/r/rpl_packet.result
@@ -0,0 +1,17 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________;
+create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________;
+select @@net_buffer_length, @@max_allowed_packet;
+@@net_buffer_length @@max_allowed_packet
+1024 1024
+create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
+INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023');
+select count(*) from `DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________`.`t1` /* must be 1 */;
+count(*)
+1
+drop database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________;
diff --git a/mysql-test/r/rpl_trigger.result b/mysql-test/r/rpl_trigger.result
index 49f0f5c4c44..f8573eec75f 100644
--- a/mysql-test/r/rpl_trigger.result
+++ b/mysql-test/r/rpl_trigger.result
@@ -71,8 +71,6 @@ get_lock("bug12480",2)
1
create table t1 (a datetime,b datetime, c datetime);
drop function if exists bug12480;
-Warnings:
-Note 1305 FUNCTION bug12480 does not exist
create function bug12480() returns datetime
begin
set @a=get_lock("bug12480",2);
@@ -943,3 +941,30 @@ c
---> Cleaning up...
DROP TABLE t1;
DROP TABLE t2;
+drop table if exists t1;
+create table t1(a int, b varchar(50));
+drop trigger not_a_trigger;
+ERROR HY000: Trigger does not exist
+drop trigger if exists not_a_trigger;
+Warnings:
+Note 1360 Trigger does not exist
+create trigger t1_bi before insert on t1
+for each row set NEW.b := "In trigger t1_bi";
+insert into t1 values (1, "a");
+drop trigger if exists t1_bi;
+insert into t1 values (2, "b");
+drop trigger if exists t1_bi;
+Warnings:
+Note 1360 Trigger does not exist
+insert into t1 values (3, "c");
+select * from t1;
+a b
+1 In trigger t1_bi
+2 b
+3 c
+select * from t1;
+a b
+1 In trigger t1_bi
+2 b
+3 c
+drop table t1;
diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result
index 601f3d9cd14..be03f3f080a 100644
--- a/mysql-test/r/rpl_view.result
+++ b/mysql-test/r/rpl_view.result
@@ -47,11 +47,11 @@ show binlog events limit 1,100;
Log_name Pos Event_type Server_id End_log_pos Info
slave-bin.000001 # Query 1 # use `test`; create table t1 (a int)
slave-bin.000001 # Query 1 # use `test`; insert into t1 values (1)
-slave-bin.000001 # Query 1 # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW v1 AS select a from t1
+slave-bin.000001 # Query 1 # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select a from t1
slave-bin.000001 # Query 1 # use `test`; insert into v1 values (2)
slave-bin.000001 # Query 1 # use `test`; update v1 set a=3 where a=1
slave-bin.000001 # Query 1 # use `test`; delete from v1 where a=2
-slave-bin.000001 # Query 1 # use `test`; ALTER ALGORITHM=UNDEFINED DEFINER=root@localhost SQL SECURITY DEFINER VIEW v1 AS select a as b from t1
+slave-bin.000001 # Query 1 # use `test`; ALTER ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select a as b from t1
slave-bin.000001 # Query 1 # use `test`; drop view v1
slave-bin.000001 # Query 1 # use `test`; drop table t1
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index 7bdfa78066c..0dfb7c95f9a 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -296,7 +296,7 @@ SET sql_quote_show_create= @old_sql_quote_show_create;
SET sql_mode= @old_sql_mode;
select @@max_heap_table_size;
@@max_heap_table_size
-1047552
+1048576
CREATE TABLE t1 (
a int(11) default NULL,
KEY a USING BTREE (a)
@@ -520,6 +520,7 @@ t1 NULL NULL NULL NULL # # # # NULL NULL NULL NULL NULL NULL NULL NULL Incorrect
show create table t1;
ERROR HY000: Incorrect information in file: './test/t1.frm'
drop table t1;
+End of 4.1 tests
CREATE TABLE txt1(a int);
CREATE TABLE tyt2(a int);
CREATE TABLE urkunde(a int);
@@ -629,3 +630,19 @@ SHOW TABLES FROM no_such_database;
ERROR 42000: Unknown database 'no_such_database'
SHOW COLUMNS FROM no_such_table;
ERROR 42S02: Table 'test.no_such_table' doesn't exist
+flush status;
+show status like 'slow_queries';
+Variable_name Value
+Slow_queries 0
+show tables;
+Tables_in_test
+show status like 'slow_queries';
+Variable_name Value
+Slow_queries 0
+select 1 from information_schema.tables limit 1;
+1
+1
+show status like 'slow_queries';
+Variable_name Value
+Slow_queries 1
+End of 5.0 tests
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 85ea624ce2f..63fd1bfff6d 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -1226,3 +1226,27 @@ 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 'IF NOT EXISTS bug14702()
BEGIN
END' at line 1
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT);
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @a;
+ERROR HY000: View's SELECT contains a 'INTO' clause
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file";
+ERROR HY000: View's SELECT contains a 'INTO' clause
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file";
+ERROR HY000: View's SELECT contains a 'INTO' clause
+CREATE PROCEDURE bug20953()
+CREATE VIEW v AS SELECT i FROM t1 PROCEDURE ANALYSE();
+ERROR HY000: View's SELECT contains a 'PROCEDURE' clause
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1;
+ERROR HY000: View's SELECT contains a subquery in the FROM clause
+CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i;
+ERROR HY000: View's SELECT contains a variable or parameter
+CREATE PROCEDURE bug20953()
+BEGIN
+DECLARE i INT;
+CREATE VIEW v AS SELECT i;
+END |
+ERROR HY000: View's SELECT contains a variable or parameter
+PREPARE stmt FROM "CREATE VIEW v AS SELECT ?";
+ERROR HY000: View's SELECT contains a variable or parameter
+DROP TABLE t1;
diff --git a/mysql-test/r/sp-threads.result b/mysql-test/r/sp-threads.result
index c516d7a643f..953830ecc87 100644
--- a/mysql-test/r/sp-threads.result
+++ b/mysql-test/r/sp-threads.result
@@ -31,7 +31,7 @@ create procedure bug9486()
update t1, t2 set val= 1 where id1=id2;
call bug9486();
lock tables t2 write;
- call bug9486();
+call bug9486();
show processlist;
Id User Host db Command Time State Info
# root localhost test Sleep # NULL
@@ -77,7 +77,7 @@ select * from t1;
end|
use test;
lock table t1 write;
- call p2();
+call p2();
use test;
drop procedure p1;
create procedure p1() select * from t1;
diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result
index 14040f8420e..f362187cd14 100644
--- a/mysql-test/r/sp-vars.result
+++ b/mysql-test/r/sp-vars.result
@@ -4,6 +4,7 @@ DROP FUNCTION IF EXISTS sp_vars_check_ret1;
DROP FUNCTION IF EXISTS sp_vars_check_ret2;
DROP FUNCTION IF EXISTS sp_vars_check_ret3;
DROP FUNCTION IF EXISTS sp_vars_check_ret4;
+DROP FUNCTION IF EXISTS sp_vars_div_zero;
SET @@sql_mode = 'ansi';
CREATE PROCEDURE sp_vars_check_dflt()
BEGIN
@@ -88,6 +89,12 @@ CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2)
BEGIN
RETURN 12 * 10 + 34 + 0.1234;
END|
+CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER
+BEGIN
+DECLARE div_zero INTEGER;
+SELECT 1/0 INTO div_zero;
+RETURN div_zero;
+END|
---------------------------------------------------------------
Calling the routines, created in ANSI mode.
@@ -172,6 +179,9 @@ sp_vars_check_ret4()
154.12
Warnings:
Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1
+SELECT sp_vars_div_zero();
+sp_vars_div_zero()
+NULL
SET @@sql_mode = 'traditional';
---------------------------------------------------------------
@@ -257,12 +267,16 @@ sp_vars_check_ret4()
154.12
Warnings:
Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1
+SELECT sp_vars_div_zero();
+sp_vars_div_zero()
+NULL
DROP PROCEDURE sp_vars_check_dflt;
DROP PROCEDURE sp_vars_check_assignment;
DROP FUNCTION sp_vars_check_ret1;
DROP FUNCTION sp_vars_check_ret2;
DROP FUNCTION sp_vars_check_ret3;
DROP FUNCTION sp_vars_check_ret4;
+DROP FUNCTION sp_vars_div_zero;
CREATE PROCEDURE sp_vars_check_dflt()
BEGIN
DECLARE v1 TINYINT DEFAULT 1e200;
@@ -346,6 +360,12 @@ CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2)
BEGIN
RETURN 12 * 10 + 34 + 0.1234;
END|
+CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER
+BEGIN
+DECLARE div_zero INTEGER;
+SELECT 1/0 INTO div_zero;
+RETURN div_zero;
+END|
---------------------------------------------------------------
Calling the routines, created in TRADITIONAL mode.
@@ -366,6 +386,8 @@ sp_vars_check_ret4()
154.12
Warnings:
Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1
+SELECT sp_vars_div_zero();
+ERROR 22012: Division by 0
SET @@sql_mode = 'ansi';
DROP PROCEDURE sp_vars_check_dflt;
DROP PROCEDURE sp_vars_check_assignment;
@@ -373,6 +395,7 @@ DROP FUNCTION sp_vars_check_ret1;
DROP FUNCTION sp_vars_check_ret2;
DROP FUNCTION sp_vars_check_ret3;
DROP FUNCTION sp_vars_check_ret4;
+DROP FUNCTION sp_vars_div_zero;
---------------------------------------------------------------
BIT data type tests
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 31aa96ab05d..1bb4b3a405b 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -5470,5 +5470,161 @@ CAD
CHF
DROP FUNCTION bug21493|
DROP TABLE t3,t4|
+drop function if exists func_20028_a|
+drop function if exists func_20028_b|
+drop function if exists func_20028_c|
+drop procedure if exists proc_20028_a|
+drop procedure if exists proc_20028_b|
+drop procedure if exists proc_20028_c|
+drop table if exists table_20028|
+create table table_20028 (i int)|
+SET @save_sql_mode=@@sql_mode|
+SET sql_mode=''|
+create function func_20028_a() returns integer
+begin
+declare temp integer;
+select i into temp from table_20028 limit 1;
+return ifnull(temp, 0);
+end|
+create function func_20028_b() returns integer
+begin
+return func_20028_a();
+end|
+create function func_20028_c() returns integer
+begin
+declare div_zero integer;
+set SQL_MODE='TRADITIONAL';
+select 1/0 into div_zero;
+return div_zero;
+end|
+create procedure proc_20028_a()
+begin
+declare temp integer;
+select i into temp from table_20028 limit 1;
+end|
+create procedure proc_20028_b()
+begin
+call proc_20028_a();
+end|
+create procedure proc_20028_c()
+begin
+declare div_zero integer;
+set SQL_MODE='TRADITIONAL';
+select 1/0 into div_zero;
+end|
+select func_20028_a()|
+func_20028_a()
+0
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+select func_20028_b()|
+func_20028_b()
+0
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+select func_20028_c()|
+ERROR 22012: Division by 0
+call proc_20028_a()|
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+call proc_20028_b()|
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+call proc_20028_c()|
+ERROR 22012: Division by 0
+SET sql_mode='TRADITIONAL'|
+drop function func_20028_a|
+drop function func_20028_b|
+drop function func_20028_c|
+drop procedure proc_20028_a|
+drop procedure proc_20028_b|
+drop procedure proc_20028_c|
+create function func_20028_a() returns integer
+begin
+declare temp integer;
+select i into temp from table_20028 limit 1;
+return ifnull(temp, 0);
+end|
+create function func_20028_b() returns integer
+begin
+return func_20028_a();
+end|
+create function func_20028_c() returns integer
+begin
+declare div_zero integer;
+set SQL_MODE='';
+select 1/0 into div_zero;
+return div_zero;
+end|
+create procedure proc_20028_a()
+begin
+declare temp integer;
+select i into temp from table_20028 limit 1;
+end|
+create procedure proc_20028_b()
+begin
+call proc_20028_a();
+end|
+create procedure proc_20028_c()
+begin
+declare div_zero integer;
+set SQL_MODE='';
+select 1/0 into div_zero;
+end|
+select func_20028_a()|
+func_20028_a()
+0
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+select func_20028_b()|
+func_20028_b()
+0
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+select func_20028_c()|
+func_20028_c()
+NULL
+call proc_20028_a()|
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+call proc_20028_b()|
+Warnings:
+Warning 1329 No data - zero rows fetched, selected, or processed
+call proc_20028_c()|
+SET @@sql_mode=@save_sql_mode|
+drop function func_20028_a|
+drop function func_20028_b|
+drop function func_20028_c|
+drop procedure proc_20028_a|
+drop procedure proc_20028_b|
+drop procedure proc_20028_c|
+drop table table_20028|
+drop procedure if exists proc_21462_a|
+drop procedure if exists proc_21462_b|
+create procedure proc_21462_a()
+begin
+select "Called A";
+end|
+create procedure proc_21462_b(x int)
+begin
+select "Called B";
+end|
+call proc_21462_a|
+Called A
+Called A
+call proc_21462_a()|
+Called A
+Called A
+call proc_21462_a(1)|
+ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_a; expected 0, got 1
+call proc_21462_b|
+ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_b; expected 1, got 0
+call proc_21462_b()|
+ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_b; expected 1, got 0
+call proc_21462_b(1)|
+Called B
+Called B
+drop procedure proc_21462_a|
+drop procedure proc_21462_b|
End of 5.0 tests
drop table t1,t2;
diff --git a/mysql-test/r/sp_notembedded.result b/mysql-test/r/sp_notembedded.result
index bcde32572c2..60e427e17a5 100644
--- a/mysql-test/r/sp_notembedded.result
+++ b/mysql-test/r/sp_notembedded.result
@@ -85,8 +85,7 @@ flush status|
flush query cache|
delete from t1|
drop procedure bug3583|
-drop table t1;
-#|
+drop table t1|
drop procedure if exists bug6807|
create procedure bug6807()
begin
diff --git a/mysql-test/r/ssl_des.result b/mysql-test/r/ssl_des.result
new file mode 100644
index 00000000000..cd8bf52139e
--- /dev/null
+++ b/mysql-test/r/ssl_des.result
@@ -0,0 +1,2159 @@
+SHOW STATUS LIKE 'Ssl_cipher';
+Variable_name Value
+Ssl_cipher DHE-RSA-AES256-SHA
+drop table if exists t1,t2,t3,t4;
+CREATE TABLE t1 (
+Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
+Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
+);
+INSERT INTO t1 VALUES (9410,9412);
+select period from t1;
+period
+9410
+select * from t1;
+Period Varor_period
+9410 9412
+select t1.* from t1;
+Period Varor_period
+9410 9412
+CREATE TABLE t2 (
+auto int not null auto_increment,
+fld1 int(6) unsigned zerofill DEFAULT '000000' NOT NULL,
+companynr tinyint(2) unsigned zerofill DEFAULT '00' NOT NULL,
+fld3 char(30) DEFAULT '' NOT NULL,
+fld4 char(35) DEFAULT '' NOT NULL,
+fld5 char(35) DEFAULT '' NOT NULL,
+fld6 char(4) DEFAULT '' NOT NULL,
+UNIQUE fld1 (fld1),
+KEY fld3 (fld3),
+PRIMARY KEY (auto)
+);
+select t2.fld3 from t2 where companynr = 58 and fld3 like "%imaginable%";
+fld3
+imaginable
+select fld3 from t2 where fld3 like "%cultivation" ;
+fld3
+cultivation
+select t2.fld3,companynr from t2 where companynr = 57+1 order by fld3;
+fld3 companynr
+concoct 58
+druggists 58
+engrossing 58
+Eurydice 58
+exclaimers 58
+ferociousness 58
+hopelessness 58
+Huey 58
+imaginable 58
+judges 58
+merging 58
+ostrich 58
+peering 58
+Phelps 58
+presumes 58
+Ruth 58
+sentences 58
+Shylock 58
+straggled 58
+synergy 58
+thanking 58
+tying 58
+unlocks 58
+select fld3,companynr from t2 where companynr = 58 order by fld3;
+fld3 companynr
+concoct 58
+druggists 58
+engrossing 58
+Eurydice 58
+exclaimers 58
+ferociousness 58
+hopelessness 58
+Huey 58
+imaginable 58
+judges 58
+merging 58
+ostrich 58
+peering 58
+Phelps 58
+presumes 58
+Ruth 58
+sentences 58
+Shylock 58
+straggled 58
+synergy 58
+thanking 58
+tying 58
+unlocks 58
+select fld3 from t2 order by fld3 desc limit 10;
+fld3
+youthfulness
+yelped
+Wotan
+workers
+Witt
+witchcraft
+Winsett
+Willy
+willed
+wildcats
+select fld3 from t2 order by fld3 desc limit 5;
+fld3
+youthfulness
+yelped
+Wotan
+workers
+Witt
+select fld3 from t2 order by fld3 desc limit 5,5;
+fld3
+witchcraft
+Winsett
+Willy
+willed
+wildcats
+select t2.fld3 from t2 where fld3 = 'honeysuckle';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckl_';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'hon_ysuckl_';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle%';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'h%le';
+fld3
+honeysuckle
+select t2.fld3 from t2 where fld3 LIKE 'honeysuckle_';
+fld3
+select t2.fld3 from t2 where fld3 LIKE 'don_t_find_me_please%';
+fld3
+explain select t2.fld3 from t2 where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 ignore index (fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select fld3 from t2 use index (fld1) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select fld3 from t2 use index (fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 use index (fld1,fld3) where fld3 = 'honeysuckle';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
+explain select fld3 from t2 ignore index (fld3,not_used);
+ERROR HY000: Key 'not_used' doesn't exist in table 't2'
+explain select fld3 from t2 use index (not_used);
+ERROR HY000: Key 'not_used' doesn't exist in table 't2'
+select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
+fld3
+honeysuckle
+honoring
+explain select t2.fld3 from t2 where fld3 >= 'honeysuckle' and fld3 <= 'honoring' order by fld3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld3 fld3 30 NULL 2 Using where; Using index
+select fld1,fld3 from t2 where fld3="Colombo" or fld3 = "nondecreasing" order by fld3;
+fld1 fld3
+148504 Colombo
+068305 Colombo
+000000 nondecreasing
+select fld1,fld3 from t2 where companynr = 37 and fld3 = 'appendixes';
+fld1 fld3
+232605 appendixes
+1232605 appendixes
+1232606 appendixes
+1232607 appendixes
+1232608 appendixes
+1232609 appendixes
+select fld1 from t2 where fld1=250501 or fld1="250502";
+fld1
+250501
+250502
+explain select fld1 from t2 where fld1=250501 or fld1="250502";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld1 fld1 4 NULL 2 Using where; Using index
+select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
+fld1
+250501
+250502
+250505
+250601
+explain select fld1 from t2 where fld1=250501 or fld1=250502 or fld1 >= 250505 and fld1 <= 250601 or fld1 between 250501 and 250502;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range fld1 fld1 4 NULL 4 Using where; Using index
+select fld1,fld3 from t2 where companynr = 37 and fld3 like 'f%';
+fld1 fld3
+218401 faithful
+018007 fanatic
+228311 fated
+018017 featherweight
+218022 feed
+088303 feminine
+058004 Fenton
+038017 fetched
+018054 fetters
+208101 fiftieth
+238007 filial
+013606 fingerings
+218008 finishers
+038205 firearm
+188505 fitting
+202301 Fitzpatrick
+238008 fixedly
+012001 flanking
+018103 flint
+018104 flopping
+188007 flurried
+013602 foldout
+226205 foothill
+232102 forgivably
+228306 forthcoming
+186002 freakish
+208113 freest
+231315 freezes
+036002 funereal
+226209 furnishings
+198006 furthermore
+select fld3 from t2 where fld3 like "L%" and fld3 = "ok";
+fld3
+select fld3 from t2 where (fld3 like "C%" and fld3 = "Chantilly");
+fld3
+Chantilly
+select fld1,fld3 from t2 where fld1 like "25050%";
+fld1 fld3
+250501 poisoning
+250502 Iraqis
+250503 heaving
+250504 population
+250505 bomb
+select fld1,fld3 from t2 where fld1 like "25050_";
+fld1 fld3
+250501 poisoning
+250502 Iraqis
+250503 heaving
+250504 population
+250505 bomb
+select distinct companynr from t2;
+companynr
+00
+37
+36
+50
+58
+29
+40
+53
+65
+41
+34
+68
+select distinct companynr from t2 order by companynr;
+companynr
+00
+29
+34
+36
+37
+40
+41
+50
+53
+58
+65
+68
+select distinct companynr from t2 order by companynr desc;
+companynr
+68
+65
+58
+53
+50
+41
+40
+37
+36
+34
+29
+00
+select distinct t2.fld3,period from t2,t1 where companynr=37 and fld3 like "O%";
+fld3 period
+obliterates 9410
+offload 9410
+opaquely 9410
+organizer 9410
+overestimating 9410
+overlay 9410
+select distinct fld3 from t2 where companynr = 34 order by fld3;
+fld3
+absentee
+accessed
+ahead
+alphabetic
+Asiaticizations
+attitude
+aye
+bankruptcies
+belays
+Blythe
+bomb
+boulevard
+bulldozes
+cannot
+caressing
+charcoal
+checksumming
+chess
+clubroom
+colorful
+cosy
+creator
+crying
+Darius
+diffusing
+duality
+Eiffel
+Epiphany
+Ernestine
+explorers
+exterminated
+famine
+forked
+Gershwins
+heaving
+Hodges
+Iraqis
+Italianization
+Lagos
+landslide
+libretto
+Majorca
+mastering
+narrowed
+occurred
+offerers
+Palestine
+Peruvianizes
+pharmaceutic
+poisoning
+population
+Pygmalion
+rats
+realest
+recording
+regimented
+retransmitting
+reviver
+rouses
+scars
+sicker
+sleepwalk
+stopped
+sugars
+translatable
+uncles
+unexpected
+uprisings
+versatility
+vest
+select distinct fld3 from t2 limit 10;
+fld3
+abates
+abiding
+Abraham
+abrogating
+absentee
+abut
+accessed
+accruing
+accumulating
+accuracies
+select distinct fld3 from t2 having fld3 like "A%" limit 10;
+fld3
+abates
+abiding
+Abraham
+abrogating
+absentee
+abut
+accessed
+accruing
+accumulating
+accuracies
+select distinct substring(fld3,1,3) from t2 where fld3 like "A%";
+substring(fld3,1,3)
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+Adl
+adm
+Ado
+ads
+adv
+aer
+aff
+afi
+afl
+afo
+agi
+ahe
+aim
+air
+Ald
+alg
+ali
+all
+alp
+alr
+ama
+ame
+amm
+ana
+and
+ane
+Ang
+ani
+Ann
+Ant
+api
+app
+aqu
+Ara
+arc
+Arm
+arr
+Art
+Asi
+ask
+asp
+ass
+ast
+att
+aud
+Aug
+aut
+ave
+avo
+awe
+aye
+Azt
+select distinct substring(fld3,1,3) as a from t2 having a like "A%" order by a limit 10;
+a
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+select distinct substring(fld3,1,3) from t2 where fld3 like "A%" limit 10;
+substring(fld3,1,3)
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+select distinct substring(fld3,1,3) as a from t2 having a like "A%" limit 10;
+a
+aba
+abi
+Abr
+abs
+abu
+acc
+acq
+acu
+Ade
+adj
+create table t3 (
+period int not null,
+name char(32) not null,
+companynr int not null,
+price double(11,0),
+price2 double(11,0),
+key (period),
+key (name)
+);
+create temporary table tmp engine = myisam select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+insert into tmp select * from t3;
+insert into t3 select * from tmp;
+alter table t3 add t2nr int not null auto_increment primary key first;
+drop table tmp;
+SET SQL_BIG_TABLES=1;
+select distinct concat(fld3," ",fld3) as namn from t2,t3 where t2.fld1=t3.t2nr order by namn limit 10;
+namn
+Abraham Abraham
+abrogating abrogating
+admonishing admonishing
+Adolph Adolph
+afield afield
+aging aging
+ammonium ammonium
+analyzable analyzable
+animals animals
+animized animized
+SET SQL_BIG_TABLES=0;
+select distinct concat(fld3," ",fld3) from t2,t3 where t2.fld1=t3.t2nr order by fld3 limit 10;
+concat(fld3," ",fld3)
+Abraham Abraham
+abrogating abrogating
+admonishing admonishing
+Adolph Adolph
+afield afield
+aging aging
+ammonium ammonium
+analyzable analyzable
+animals animals
+animized animized
+select distinct fld5 from t2 limit 10;
+fld5
+neat
+Steinberg
+jarring
+tinily
+balled
+persist
+attainments
+fanatic
+measures
+rightfulness
+select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10;
+fld3 count(*)
+affixed 1
+and 1
+annoyers 1
+Anthony 1
+assayed 1
+assurers 1
+attendants 1
+bedlam 1
+bedpost 1
+boasted 1
+SET SQL_BIG_TABLES=1;
+select distinct fld3,count(*) from t2 group by companynr,fld3 limit 10;
+fld3 count(*)
+affixed 1
+and 1
+annoyers 1
+Anthony 1
+assayed 1
+assurers 1
+attendants 1
+bedlam 1
+bedpost 1
+boasted 1
+SET SQL_BIG_TABLES=0;
+select distinct fld3,repeat("a",length(fld3)),count(*) from t2 group by companynr,fld3 limit 100,10;
+fld3 repeat("a",length(fld3)) count(*)
+circus aaaaaa 1
+cited aaaaa 1
+Colombo aaaaaaa 1
+congresswoman aaaaaaaaaaaaa 1
+contrition aaaaaaaaaa 1
+corny aaaaa 1
+cultivation aaaaaaaaaaa 1
+definiteness aaaaaaaaaaaa 1
+demultiplex aaaaaaaaaaa 1
+disappointing aaaaaaaaaaaaa 1
+select distinct companynr,rtrim(space(512+companynr)) from t3 order by 1,2;
+companynr rtrim(space(512+companynr))
+37
+78
+101
+154
+311
+447
+512
+select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by fld3;
+fld3
+explain select t3.t2nr,fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr order by t3.t2nr,fld3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.fld1 1 Using where; Using index
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL period NULL NULL NULL 41810 Using temporary; Using filesort
+1 SIMPLE t3 ref period period 4 test.t1.period 4181
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t3.period limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 index period period 4 NULL 41810
+1 SIMPLE t1 ref period period 4 test.t3.period 4181
+explain select * from t3 as t1,t3 where t1.period=t3.period order by t1.period limit 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index period period 4 NULL 41810
+1 SIMPLE t3 ref period period 4 test.t1.period 4181
+select period from t1;
+period
+9410
+select period from t1 where period=1900;
+period
+select fld3,period from t1,t2 where fld1 = 011401 order by period;
+fld3 period
+breaking 9410
+select fld3,period from t2,t3 where t2.fld1 = 011401 and t2.fld1=t3.t2nr and t3.period=1001;
+fld3 period
+breaking 1001
+explain select fld3,period from t2,t3 where t2.fld1 = 011401 and t3.t2nr=t2.fld1 and 1001 = t3.period;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 const fld1 fld1 4 const 1
+1 SIMPLE t3 const PRIMARY,period PRIMARY 4 const 1
+select fld3,period from t2,t1 where companynr*10 = 37*10;
+fld3 period
+breaking 9410
+Romans 9410
+intercepted 9410
+bewilderingly 9410
+astound 9410
+admonishing 9410
+sumac 9410
+flanking 9410
+combed 9410
+subjective 9410
+scatterbrain 9410
+Eulerian 9410
+Kane 9410
+overlay 9410
+perturb 9410
+goblins 9410
+annihilates 9410
+Wotan 9410
+snatching 9410
+concludes 9410
+laterally 9410
+yelped 9410
+grazing 9410
+Baird 9410
+celery 9410
+misunderstander 9410
+handgun 9410
+foldout 9410
+mystic 9410
+succumbed 9410
+Nabisco 9410
+fingerings 9410
+aging 9410
+afield 9410
+ammonium 9410
+boat 9410
+intelligibility 9410
+Augustine 9410
+teethe 9410
+dreaded 9410
+scholastics 9410
+audiology 9410
+wallet 9410
+parters 9410
+eschew 9410
+quitter 9410
+neat 9410
+Steinberg 9410
+jarring 9410
+tinily 9410
+balled 9410
+persist 9410
+attainments 9410
+fanatic 9410
+measures 9410
+rightfulness 9410
+capably 9410
+impulsive 9410
+starlet 9410
+terminators 9410
+untying 9410
+announces 9410
+featherweight 9410
+pessimist 9410
+daughter 9410
+decliner 9410
+lawgiver 9410
+stated 9410
+readable 9410
+attrition 9410
+cascade 9410
+motors 9410
+interrogate 9410
+pests 9410
+stairway 9410
+dopers 9410
+testicle 9410
+Parsifal 9410
+leavings 9410
+postulation 9410
+squeaking 9410
+contrasted 9410
+leftover 9410
+whiteners 9410
+erases 9410
+Punjab 9410
+Merritt 9410
+Quixotism 9410
+sweetish 9410
+dogging 9410
+scornfully 9410
+bellow 9410
+bills 9410
+cupboard 9410
+sureties 9410
+puddings 9410
+fetters 9410
+bivalves 9410
+incurring 9410
+Adolph 9410
+pithed 9410
+Miles 9410
+trimmings 9410
+tragedies 9410
+skulking 9410
+flint 9410
+flopping 9410
+relaxing 9410
+offload 9410
+suites 9410
+lists 9410
+animized 9410
+multilayer 9410
+standardizes 9410
+Judas 9410
+vacuuming 9410
+dentally 9410
+humanness 9410
+inch 9410
+Weissmuller 9410
+irresponsibly 9410
+luckily 9410
+culled 9410
+medical 9410
+bloodbath 9410
+subschema 9410
+animals 9410
+Micronesia 9410
+repetitions 9410
+Antares 9410
+ventilate 9410
+pityingly 9410
+interdependent 9410
+Graves 9410
+neonatal 9410
+chafe 9410
+honoring 9410
+realtor 9410
+elite 9410
+funereal 9410
+abrogating 9410
+sorters 9410
+Conley 9410
+lectured 9410
+Abraham 9410
+Hawaii 9410
+cage 9410
+hushes 9410
+Simla 9410
+reporters 9410
+Dutchman 9410
+descendants 9410
+groupings 9410
+dissociate 9410
+coexist 9410
+Beebe 9410
+Taoism 9410
+Connally 9410
+fetched 9410
+checkpoints 9410
+rusting 9410
+galling 9410
+obliterates 9410
+traitor 9410
+resumes 9410
+analyzable 9410
+terminator 9410
+gritty 9410
+firearm 9410
+minima 9410
+Selfridge 9410
+disable 9410
+witchcraft 9410
+betroth 9410
+Manhattanize 9410
+imprint 9410
+peeked 9410
+swelling 9410
+interrelationships 9410
+riser 9410
+Gandhian 9410
+peacock 9410
+bee 9410
+kanji 9410
+dental 9410
+scarf 9410
+chasm 9410
+insolence 9410
+syndicate 9410
+alike 9410
+imperial 9410
+convulsion 9410
+railway 9410
+validate 9410
+normalizes 9410
+comprehensive 9410
+chewing 9410
+denizen 9410
+schemer 9410
+chronicle 9410
+Kline 9410
+Anatole 9410
+partridges 9410
+brunch 9410
+recruited 9410
+dimensions 9410
+Chicana 9410
+announced 9410
+praised 9410
+employing 9410
+linear 9410
+quagmire 9410
+western 9410
+relishing 9410
+serving 9410
+scheduling 9410
+lore 9410
+eventful 9410
+arteriole 9410
+disentangle 9410
+cured 9410
+Fenton 9410
+avoidable 9410
+drains 9410
+detectably 9410
+husky 9410
+impelling 9410
+undoes 9410
+evened 9410
+squeezes 9410
+destroyer 9410
+rudeness 9410
+beaner 9410
+boorish 9410
+Everhart 9410
+encompass 9410
+mushrooms 9410
+Alison 9410
+externally 9410
+pellagra 9410
+cult 9410
+creek 9410
+Huffman 9410
+Majorca 9410
+governing 9410
+gadfly 9410
+reassigned 9410
+intentness 9410
+craziness 9410
+psychic 9410
+squabbled 9410
+burlesque 9410
+capped 9410
+extracted 9410
+DiMaggio 9410
+exclamation 9410
+subdirectory 9410
+Gothicism 9410
+feminine 9410
+metaphysically 9410
+sanding 9410
+Miltonism 9410
+freakish 9410
+index 9410
+straight 9410
+flurried 9410
+denotative 9410
+coming 9410
+commencements 9410
+gentleman 9410
+gifted 9410
+Shanghais 9410
+sportswriting 9410
+sloping 9410
+navies 9410
+leaflet 9410
+shooter 9410
+Joplin 9410
+babies 9410
+assails 9410
+admiring 9410
+swaying 9410
+Goldstine 9410
+fitting 9410
+Norwalk 9410
+analogy 9410
+deludes 9410
+cokes 9410
+Clayton 9410
+exhausts 9410
+causality 9410
+sating 9410
+icon 9410
+throttles 9410
+communicants 9410
+dehydrate 9410
+priceless 9410
+publicly 9410
+incidentals 9410
+commonplace 9410
+mumbles 9410
+furthermore 9410
+cautioned 9410
+parametrized 9410
+registration 9410
+sadly 9410
+positioning 9410
+babysitting 9410
+eternal 9410
+hoarder 9410
+congregates 9410
+rains 9410
+workers 9410
+sags 9410
+unplug 9410
+garage 9410
+boulder 9410
+specifics 9410
+Teresa 9410
+Winsett 9410
+convenient 9410
+buckboards 9410
+amenities 9410
+resplendent 9410
+sews 9410
+participated 9410
+Simon 9410
+certificates 9410
+Fitzpatrick 9410
+Evanston 9410
+misted 9410
+textures 9410
+save 9410
+count 9410
+rightful 9410
+chaperone 9410
+Lizzy 9410
+clenched 9410
+effortlessly 9410
+accessed 9410
+beaters 9410
+Hornblower 9410
+vests 9410
+indulgences 9410
+infallibly 9410
+unwilling 9410
+excrete 9410
+spools 9410
+crunches 9410
+overestimating 9410
+ineffective 9410
+humiliation 9410
+sophomore 9410
+star 9410
+rifles 9410
+dialysis 9410
+arriving 9410
+indulge 9410
+clockers 9410
+languages 9410
+Antarctica 9410
+percentage 9410
+ceiling 9410
+specification 9410
+regimented 9410
+ciphers 9410
+pictures 9410
+serpents 9410
+allot 9410
+realized 9410
+mayoral 9410
+opaquely 9410
+hostess 9410
+fiftieth 9410
+incorrectly 9410
+decomposition 9410
+stranglings 9410
+mixture 9410
+electroencephalography 9410
+similarities 9410
+charges 9410
+freest 9410
+Greenberg 9410
+tinting 9410
+expelled 9410
+warm 9410
+smoothed 9410
+deductions 9410
+Romano 9410
+bitterroot 9410
+corset 9410
+securing 9410
+environing 9410
+cute 9410
+Crays 9410
+heiress 9410
+inform 9410
+avenge 9410
+universals 9410
+Kinsey 9410
+ravines 9410
+bestseller 9410
+equilibrium 9410
+extents 9410
+relatively 9410
+pressure 9410
+critiques 9410
+befouled 9410
+rightfully 9410
+mechanizing 9410
+Latinizes 9410
+timesharing 9410
+Aden 9410
+embassies 9410
+males 9410
+shapelessly 9410
+mastering 9410
+Newtonian 9410
+finishers 9410
+abates 9410
+teem 9410
+kiting 9410
+stodgy 9410
+feed 9410
+guitars 9410
+airships 9410
+store 9410
+denounces 9410
+Pyle 9410
+Saxony 9410
+serializations 9410
+Peruvian 9410
+taxonomically 9410
+kingdom 9410
+stint 9410
+Sault 9410
+faithful 9410
+Ganymede 9410
+tidiness 9410
+gainful 9410
+contrary 9410
+Tipperary 9410
+tropics 9410
+theorizers 9410
+renew 9410
+already 9410
+terminal 9410
+Hegelian 9410
+hypothesizer 9410
+warningly 9410
+journalizing 9410
+nested 9410
+Lars 9410
+saplings 9410
+foothill 9410
+labeled 9410
+imperiously 9410
+reporters 9410
+furnishings 9410
+precipitable 9410
+discounts 9410
+excises 9410
+Stalin 9410
+despot 9410
+ripeness 9410
+Arabia 9410
+unruly 9410
+mournfulness 9410
+boom 9410
+slaughter 9410
+Sabine 9410
+handy 9410
+rural 9410
+organizer 9410
+shipyard 9410
+civics 9410
+inaccuracy 9410
+rules 9410
+juveniles 9410
+comprised 9410
+investigations 9410
+stabilizes 9410
+seminaries 9410
+Hunter 9410
+sporty 9410
+test 9410
+weasels 9410
+CERN 9410
+tempering 9410
+afore 9410
+Galatean 9410
+techniques 9410
+error 9410
+veranda 9410
+severely 9410
+Cassites 9410
+forthcoming 9410
+guides 9410
+vanish 9410
+lied 9410
+sawtooth 9410
+fated 9410
+gradually 9410
+widens 9410
+preclude 9410
+evenhandedly 9410
+percentage 9410
+disobedience 9410
+humility 9410
+gleaning 9410
+petted 9410
+bloater 9410
+minion 9410
+marginal 9410
+apiary 9410
+measures 9410
+precaution 9410
+repelled 9410
+primary 9410
+coverings 9410
+Artemia 9410
+navigate 9410
+spatial 9410
+Gurkha 9410
+meanwhile 9410
+Melinda 9410
+Butterfield 9410
+Aldrich 9410
+previewing 9410
+glut 9410
+unaffected 9410
+inmate 9410
+mineral 9410
+impending 9410
+meditation 9410
+ideas 9410
+miniaturizes 9410
+lewdly 9410
+title 9410
+youthfulness 9410
+creak 9410
+Chippewa 9410
+clamored 9410
+freezes 9410
+forgivably 9410
+reduce 9410
+McGovern 9410
+Nazis 9410
+epistle 9410
+socializes 9410
+conceptions 9410
+Kevin 9410
+uncovering 9410
+chews 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+appendixes 9410
+raining 9410
+infest 9410
+compartment 9410
+minting 9410
+ducks 9410
+roped 9410
+waltz 9410
+Lillian 9410
+repressions 9410
+chillingly 9410
+noncritical 9410
+lithograph 9410
+spongers 9410
+parenthood 9410
+posed 9410
+instruments 9410
+filial 9410
+fixedly 9410
+relives 9410
+Pandora 9410
+watering 9410
+ungrateful 9410
+secures 9410
+poison 9410
+dusted 9410
+encompasses 9410
+presentation 9410
+Kantian 9410
+select fld3,period,price,price2 from t2,t3 where t2.fld1=t3.t2nr and period >= 1001 and period <= 1002 and t2.companynr = 37 order by fld3,period, price;
+fld3 period price price2
+admonishing 1002 28357832 8723648
+analyzable 1002 28357832 8723648
+annihilates 1001 5987435 234724
+Antares 1002 28357832 8723648
+astound 1001 5987435 234724
+audiology 1001 5987435 234724
+Augustine 1002 28357832 8723648
+Baird 1002 28357832 8723648
+bewilderingly 1001 5987435 234724
+breaking 1001 5987435 234724
+Conley 1001 5987435 234724
+dentally 1002 28357832 8723648
+dissociate 1002 28357832 8723648
+elite 1001 5987435 234724
+eschew 1001 5987435 234724
+Eulerian 1001 5987435 234724
+flanking 1001 5987435 234724
+foldout 1002 28357832 8723648
+funereal 1002 28357832 8723648
+galling 1002 28357832 8723648
+Graves 1001 5987435 234724
+grazing 1001 5987435 234724
+groupings 1001 5987435 234724
+handgun 1001 5987435 234724
+humility 1002 28357832 8723648
+impulsive 1002 28357832 8723648
+inch 1001 5987435 234724
+intelligibility 1001 5987435 234724
+jarring 1001 5987435 234724
+lawgiver 1001 5987435 234724
+lectured 1002 28357832 8723648
+Merritt 1002 28357832 8723648
+neonatal 1001 5987435 234724
+offload 1002 28357832 8723648
+parters 1002 28357832 8723648
+pityingly 1002 28357832 8723648
+puddings 1002 28357832 8723648
+Punjab 1001 5987435 234724
+quitter 1002 28357832 8723648
+realtor 1001 5987435 234724
+relaxing 1001 5987435 234724
+repetitions 1001 5987435 234724
+resumes 1001 5987435 234724
+Romans 1002 28357832 8723648
+rusting 1001 5987435 234724
+scholastics 1001 5987435 234724
+skulking 1002 28357832 8723648
+stated 1002 28357832 8723648
+suites 1002 28357832 8723648
+sureties 1001 5987435 234724
+testicle 1002 28357832 8723648
+tinily 1002 28357832 8723648
+tragedies 1001 5987435 234724
+trimmings 1001 5987435 234724
+vacuuming 1001 5987435 234724
+ventilate 1001 5987435 234724
+wallet 1001 5987435 234724
+Weissmuller 1002 28357832 8723648
+Wotan 1002 28357832 8723648
+select t2.fld1,fld3,period,price,price2 from t2,t3 where t2.fld1>= 18201 and t2.fld1 <= 18811 and t2.fld1=t3.t2nr and period = 1001 and t2.companynr = 37;
+fld1 fld3 period price price2
+018201 relaxing 1001 5987435 234724
+018601 vacuuming 1001 5987435 234724
+018801 inch 1001 5987435 234724
+018811 repetitions 1001 5987435 234724
+create table t4 (
+companynr tinyint(2) unsigned zerofill NOT NULL default '00',
+companyname char(30) NOT NULL default '',
+PRIMARY KEY (companynr),
+UNIQUE KEY companyname(companyname)
+) ENGINE=MyISAM MAX_ROWS=50 PACK_KEYS=1 COMMENT='companynames';
+select STRAIGHT_JOIN t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr;
+companynr companyname
+00 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select SQL_SMALL_RESULT t2.companynr,companyname from t4,t2 where t2.companynr=t4.companynr group by t2.companynr;
+companynr companyname
+00 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select * from t1,t1 t12;
+Period Varor_period Period Varor_period
+9410 9412 9410 9412
+select t2.fld1,t22.fld1 from t2,t2 t22 where t2.fld1 >= 250501 and t2.fld1 <= 250505 and t22.fld1 >= 250501 and t22.fld1 <= 250505;
+fld1 fld1
+250501 250501
+250502 250501
+250503 250501
+250504 250501
+250505 250501
+250501 250502
+250502 250502
+250503 250502
+250504 250502
+250505 250502
+250501 250503
+250502 250503
+250503 250503
+250504 250503
+250505 250503
+250501 250504
+250502 250504
+250503 250504
+250504 250504
+250505 250504
+250501 250505
+250502 250505
+250503 250505
+250504 250505
+250505 250505
+insert into t2 (fld1, companynr) values (999999,99);
+select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
+companynr companyname
+99 NULL
+select count(*) from t2 left join t4 using (companynr) where t4.companynr is not null;
+count(*)
+1199
+explain select t2.companynr,companyname from t2 left join t4 using (companynr) where t4.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 Using where; Not exists
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1200 Using where; Not exists
+select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+companynr companyname
+select count(*) from t2 left join t4 using (companynr) where companynr is not null;
+count(*)
+1200
+explain select companynr,companyname from t2 left join t4 using (companynr) where companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+delete from t2 where fld1=999999;
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 and t4.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 and companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where t2.companynr > 0 or t2.companynr < 0 or t4.companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select t2.companynr,companyname from t4 left join t2 using (companynr) where ifnull(t2.companynr,1)>0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr is null;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where companynr > 0 or companynr < 0 or companynr > 0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL PRIMARY NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+explain select companynr,companyname from t4 left join t2 using (companynr) where ifnull(companynr,1)>0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
+companynr companynr
+37 36
+41 40
+explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t2.fld1 = 38208 or t2.fld1 = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select t2.fld1,t2.companynr,fld3,period from t3,t2 where (t3.t2nr = 38208 or t3.t2nr = 38008) and t2.fld1=t3.t2nr and period>=1008 and period<=1009;
+fld1 companynr fld3 period
+038008 37 reporters 1008
+038208 37 Selfridge 1008
+select period from t1 where (((period > 0) or period < 10000 or (period = 1900)) and (period=1900 and period <= 1901) or (period=1903 and (period=1903)) and period>=1902) or ((period=1904 or period=1905) or (period=1906 or period>1907)) or (period=1908 and period = 1909);
+period
+9410
+select period from t1 where ((period > 0 and period < 1) or (((period > 0 and period < 100) and (period > 10)) or (period > 10)) or (period > 0 and (period > 5 or period > 6)));
+period
+9410
+select a.fld1 from t2 as a,t2 b where ((a.fld1 = 250501 and a.fld1=b.fld1) or a.fld1=250502 or a.fld1=250503 or (a.fld1=250505 and a.fld1<=b.fld1 and b.fld1>=a.fld1)) and a.fld1=b.fld1;
+fld1
+250501
+250502
+250503
+250505
+select fld1 from t2 where fld1 in (250502,98005,98006,250503,250605,250606) and fld1 >=250502 and fld1 not in (250605,250606);
+fld1
+250502
+250503
+select fld1 from t2 where fld1 between 250502 and 250504;
+fld1
+250502
+250503
+250504
+select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld3 like "L%" or fld3 like "G%")) and fld3 like "L%" ;
+fld3
+label
+labeled
+labeled
+landslide
+laterally
+leaflet
+lewdly
+Lillian
+luckily
+select count(*) from t1;
+count(*)
+1
+select companynr,count(*),sum(fld1) from t2 group by companynr;
+companynr count(*) sum(fld1)
+00 82 10355753
+29 95 14473298
+34 70 17788966
+36 215 22786296
+37 588 83602098
+40 37 6618386
+41 52 12816335
+50 11 1595438
+53 4 793210
+58 23 2254293
+65 10 2284055
+68 12 3097288
+select companynr,count(*) from t2 group by companynr order by companynr desc limit 5;
+companynr count(*)
+68 12
+65 10
+58 23
+53 4
+50 11
+select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
+explain extended select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where
+Warnings:
+Note 1003 select count(0) AS `count(*)`,min(`test`.`t2`.`fld4`) AS `min(fld4)`,max(`test`.`t2`.`fld4`) AS `max(fld4)`,sum(`test`.`t2`.`fld1`) AS `sum(fld1)`,avg(`test`.`t2`.`fld1`) AS `avg(fld1)`,std(`test`.`t2`.`fld1`) AS `std(fld1)`,variance(`test`.`t2`.`fld1`) AS `variance(fld1)` from `test`.`t2` where ((`test`.`t2`.`companynr` = 34) and (`test`.`t2`.`fld4` <> _latin1''))
+select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
+companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087
+29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026
+34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
+select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
+companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
+37 1 1 5987435 5987435 5987435 5987435.0000
+37 2 1 28357832 28357832 28357832 28357832.0000
+37 3 1 39654943 39654943 39654943 39654943.0000
+37 11 1 5987435 5987435 5987435 5987435.0000
+37 12 1 28357832 28357832 28357832 28357832.0000
+37 13 1 39654943 39654943 39654943 39654943.0000
+37 21 1 5987435 5987435 5987435 5987435.0000
+37 22 1 28357832 28357832 28357832 28357832.0000
+37 23 1 39654943 39654943 39654943 39654943.0000
+37 31 1 5987435 5987435 5987435 5987435.0000
+select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
+companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
+37 1 1 5987435 5987435 5987435 5987435.0000
+37 2 1 28357832 28357832 28357832 28357832.0000
+37 3 1 39654943 39654943 39654943 39654943.0000
+37 11 1 5987435 5987435 5987435 5987435.0000
+37 12 1 28357832 28357832 28357832 28357832.0000
+37 13 1 39654943 39654943 39654943 39654943.0000
+37 21 1 5987435 5987435 5987435 5987435.0000
+37 22 1 28357832 28357832 28357832 28357832.0000
+37 23 1 39654943 39654943 39654943 39654943.0000
+37 31 1 5987435 5987435 5987435 5987435.0000
+select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ;
+companynr count(price) sum(price) min(price) max(price) avg(price)
+37 12543 309394878010 5987435 39654943 24666736.6667
+78 8362 414611089292 726498 98439034 49582766.0000
+101 4181 3489454238 834598 834598 834598.0000
+154 4181 4112197254950 983543950 983543950 983543950.0000
+311 4181 979599938 234298 234298 234298.0000
+447 4181 9929180954 2374834 2374834 2374834.0000
+512 4181 3288532102 786542 786542 786542.0000
+select distinct mod(companynr,10) from t4 group by companynr;
+mod(companynr,10)
+0
+9
+4
+6
+7
+1
+3
+8
+5
+select distinct 1 from t4 group by companynr;
+1
+1
+select count(distinct fld1) from t2;
+count(distinct fld1)
+1199
+select companynr,count(distinct fld1) from t2 group by companynr;
+companynr count(distinct fld1)
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(*) from t2 group by companynr;
+companynr count(*)
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct concat(fld1,repeat(65,1000))) from t2 group by companynr;
+companynr count(distinct concat(fld1,repeat(65,1000)))
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct concat(fld1,repeat(65,200))) from t2 group by companynr;
+companynr count(distinct concat(fld1,repeat(65,200)))
+00 82
+29 95
+34 70
+36 215
+37 588
+40 37
+41 52
+50 11
+53 4
+58 23
+65 10
+68 12
+select companynr,count(distinct floor(fld1/100)) from t2 group by companynr;
+companynr count(distinct floor(fld1/100))
+00 47
+29 35
+34 14
+36 69
+37 108
+40 16
+41 11
+50 9
+53 1
+58 1
+65 1
+68 1
+select companynr,count(distinct concat(repeat(65,1000),floor(fld1/100))) from t2 group by companynr;
+companynr count(distinct concat(repeat(65,1000),floor(fld1/100)))
+00 47
+29 35
+34 14
+36 69
+37 108
+40 16
+41 11
+50 9
+53 1
+58 1
+65 1
+68 1
+select sum(fld1),fld3 from t2 where fld3="Romans" group by fld1 limit 10;
+sum(fld1) fld3
+11402 Romans
+select name,count(*) from t3 where name='cloakroom' group by name;
+name count(*)
+cloakroom 4181
+select name,count(*) from t3 where name='cloakroom' and price>10 group by name;
+name count(*)
+cloakroom 4181
+select count(*) from t3 where name='cloakroom' and price2=823742;
+count(*)
+4181
+select name,count(*) from t3 where name='cloakroom' and price2=823742 group by name;
+name count(*)
+cloakroom 4181
+select name,count(*) from t3 where name >= "extramarital" and price <= 39654943 group by name;
+name count(*)
+extramarital 4181
+gazer 4181
+gems 4181
+Iranizes 4181
+spates 4181
+tucked 4181
+violinist 4181
+select t2.fld3,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name;
+fld3 count(*)
+spates 4181
+select companynr|0,companyname from t4 group by 1;
+companynr|0 companyname
+0 Unknown
+29 company 1
+34 company 2
+36 company 3
+37 company 4
+40 company 5
+41 company 6
+50 company 11
+53 company 7
+58 company 8
+65 company 9
+68 company 10
+select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by t2.companynr order by companyname;
+companynr companyname count(*)
+29 company 1 95
+68 company 10 12
+50 company 11 11
+34 company 2 70
+36 company 3 215
+37 company 4 588
+40 company 5 37
+41 company 6 52
+53 company 7 4
+58 company 8 23
+65 company 9 10
+00 Unknown 82
+select t2.fld1,count(*) from t2,t3 where t2.fld1=158402 and t3.name=t2.fld3 group by t3.name;
+fld1 count(*)
+158402 4181
+select sum(Period)/count(*) from t1;
+sum(Period)/count(*)
+9410.0000
+select companynr,count(price) as "count",sum(price) as "sum" ,abs(sum(price)/count(price)-avg(price)) as "diff",(0+count(price))*companynr as func from t3 group by companynr;
+companynr count sum diff func
+37 12543 309394878010 0.0000 464091
+78 8362 414611089292 0.0000 652236
+101 4181 3489454238 0.0000 422281
+154 4181 4112197254950 0.0000 643874
+311 4181 979599938 0.0000 1300291
+447 4181 9929180954 0.0000 1868907
+512 4181 3288532102 0.0000 2140672
+select companynr,sum(price)/count(price) as avg from t3 group by companynr having avg > 70000000 order by avg;
+companynr avg
+154 983543950.0000
+select companynr,count(*) from t2 group by companynr order by 2 desc;
+companynr count(*)
+37 588
+36 215
+29 95
+00 82
+34 70
+41 52
+40 37
+58 23
+68 12
+50 11
+65 10
+53 4
+select companynr,count(*) from t2 where companynr > 40 group by companynr order by 2 desc;
+companynr count(*)
+41 52
+58 23
+68 12
+50 11
+65 10
+53 4
+select t2.fld4,t2.fld1,count(price),sum(price),min(price),max(price),avg(price) from t3,t2 where t3.companynr = 37 and t2.fld1 = t3.t2nr group by fld1,t2.fld4;
+fld4 fld1 count(price) sum(price) min(price) max(price) avg(price)
+teethe 000001 1 5987435 5987435 5987435 5987435.0000
+dreaded 011401 1 5987435 5987435 5987435 5987435.0000
+scholastics 011402 1 28357832 28357832 28357832 28357832.0000
+audiology 011403 1 39654943 39654943 39654943 39654943.0000
+wallet 011501 1 5987435 5987435 5987435 5987435.0000
+parters 011701 1 5987435 5987435 5987435 5987435.0000
+eschew 011702 1 28357832 28357832 28357832 28357832.0000
+quitter 011703 1 39654943 39654943 39654943 39654943.0000
+neat 012001 1 5987435 5987435 5987435 5987435.0000
+Steinberg 012003 1 39654943 39654943 39654943 39654943.0000
+balled 012301 1 5987435 5987435 5987435 5987435.0000
+persist 012302 1 28357832 28357832 28357832 28357832.0000
+attainments 012303 1 39654943 39654943 39654943 39654943.0000
+capably 012501 1 5987435 5987435 5987435 5987435.0000
+impulsive 012602 1 28357832 28357832 28357832 28357832.0000
+starlet 012603 1 39654943 39654943 39654943 39654943.0000
+featherweight 012701 1 5987435 5987435 5987435 5987435.0000
+pessimist 012702 1 28357832 28357832 28357832 28357832.0000
+daughter 012703 1 39654943 39654943 39654943 39654943.0000
+lawgiver 013601 1 5987435 5987435 5987435 5987435.0000
+stated 013602 1 28357832 28357832 28357832 28357832.0000
+readable 013603 1 39654943 39654943 39654943 39654943.0000
+testicle 013801 1 5987435 5987435 5987435 5987435.0000
+Parsifal 013802 1 28357832 28357832 28357832 28357832.0000
+leavings 013803 1 39654943 39654943 39654943 39654943.0000
+squeaking 013901 1 5987435 5987435 5987435 5987435.0000
+contrasted 016001 1 5987435 5987435 5987435 5987435.0000
+leftover 016201 1 5987435 5987435 5987435 5987435.0000
+whiteners 016202 1 28357832 28357832 28357832 28357832.0000
+erases 016301 1 5987435 5987435 5987435 5987435.0000
+Punjab 016302 1 28357832 28357832 28357832 28357832.0000
+Merritt 016303 1 39654943 39654943 39654943 39654943.0000
+sweetish 018001 1 5987435 5987435 5987435 5987435.0000
+dogging 018002 1 28357832 28357832 28357832 28357832.0000
+scornfully 018003 1 39654943 39654943 39654943 39654943.0000
+fetters 018012 1 28357832 28357832 28357832 28357832.0000
+bivalves 018013 1 39654943 39654943 39654943 39654943.0000
+skulking 018021 1 5987435 5987435 5987435 5987435.0000
+flint 018022 1 28357832 28357832 28357832 28357832.0000
+flopping 018023 1 39654943 39654943 39654943 39654943.0000
+Judas 018032 1 28357832 28357832 28357832 28357832.0000
+vacuuming 018033 1 39654943 39654943 39654943 39654943.0000
+medical 018041 1 5987435 5987435 5987435 5987435.0000
+bloodbath 018042 1 28357832 28357832 28357832 28357832.0000
+subschema 018043 1 39654943 39654943 39654943 39654943.0000
+interdependent 018051 1 5987435 5987435 5987435 5987435.0000
+Graves 018052 1 28357832 28357832 28357832 28357832.0000
+neonatal 018053 1 39654943 39654943 39654943 39654943.0000
+sorters 018061 1 5987435 5987435 5987435 5987435.0000
+epistle 018062 1 28357832 28357832 28357832 28357832.0000
+Conley 018101 1 5987435 5987435 5987435 5987435.0000
+lectured 018102 1 28357832 28357832 28357832 28357832.0000
+Abraham 018103 1 39654943 39654943 39654943 39654943.0000
+cage 018201 1 5987435 5987435 5987435 5987435.0000
+hushes 018202 1 28357832 28357832 28357832 28357832.0000
+Simla 018402 1 28357832 28357832 28357832 28357832.0000
+reporters 018403 1 39654943 39654943 39654943 39654943.0000
+coexist 018601 1 5987435 5987435 5987435 5987435.0000
+Beebe 018602 1 28357832 28357832 28357832 28357832.0000
+Taoism 018603 1 39654943 39654943 39654943 39654943.0000
+Connally 018801 1 5987435 5987435 5987435 5987435.0000
+fetched 018802 1 28357832 28357832 28357832 28357832.0000
+checkpoints 018803 1 39654943 39654943 39654943 39654943.0000
+gritty 018811 1 5987435 5987435 5987435 5987435.0000
+firearm 018812 1 28357832 28357832 28357832 28357832.0000
+minima 019101 1 5987435 5987435 5987435 5987435.0000
+Selfridge 019102 1 28357832 28357832 28357832 28357832.0000
+disable 019103 1 39654943 39654943 39654943 39654943.0000
+witchcraft 019201 1 5987435 5987435 5987435 5987435.0000
+betroth 030501 1 5987435 5987435 5987435 5987435.0000
+Manhattanize 030502 1 28357832 28357832 28357832 28357832.0000
+imprint 030503 1 39654943 39654943 39654943 39654943.0000
+swelling 031901 1 5987435 5987435 5987435 5987435.0000
+interrelationships 036001 1 5987435 5987435 5987435 5987435.0000
+riser 036002 1 28357832 28357832 28357832 28357832.0000
+bee 038001 1 5987435 5987435 5987435 5987435.0000
+kanji 038002 1 28357832 28357832 28357832 28357832.0000
+dental 038003 1 39654943 39654943 39654943 39654943.0000
+railway 038011 1 5987435 5987435 5987435 5987435.0000
+validate 038012 1 28357832 28357832 28357832 28357832.0000
+normalizes 038013 1 39654943 39654943 39654943 39654943.0000
+Kline 038101 1 5987435 5987435 5987435 5987435.0000
+Anatole 038102 1 28357832 28357832 28357832 28357832.0000
+partridges 038103 1 39654943 39654943 39654943 39654943.0000
+recruited 038201 1 5987435 5987435 5987435 5987435.0000
+dimensions 038202 1 28357832 28357832 28357832 28357832.0000
+Chicana 038203 1 39654943 39654943 39654943 39654943.0000
+select t3.companynr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 group by companynr,fld3;
+companynr fld3 sum(price)
+512 boat 786542
+512 capably 786542
+512 cupboard 786542
+512 decliner 786542
+512 descendants 786542
+512 dopers 786542
+512 erases 786542
+512 Micronesia 786542
+512 Miles 786542
+512 skies 786542
+select t2.companynr,count(*),min(fld3),max(fld3),sum(price),avg(price) from t2,t3 where t3.companynr >= 30 and t3.companynr <= 58 and t3.t2nr = t2.fld1 and 1+1=2 group by t2.companynr;
+companynr count(*) min(fld3) max(fld3) sum(price) avg(price)
+00 1 Omaha Omaha 5987435 5987435.0000
+36 1 dubbed dubbed 28357832 28357832.0000
+37 83 Abraham Wotan 1908978016 22999735.1325
+50 2 scribbled tapestry 68012775 34006387.5000
+select t3.companynr+0,t3.t2nr,fld3,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 37 group by 1,t3.t2nr,fld3,fld3,fld3,fld3,fld3 order by fld1;
+t3.companynr+0 t2nr fld3 sum(price)
+37 1 Omaha 5987435
+37 11401 breaking 5987435
+37 11402 Romans 28357832
+37 11403 intercepted 39654943
+37 11501 bewilderingly 5987435
+37 11701 astound 5987435
+37 11702 admonishing 28357832
+37 11703 sumac 39654943
+37 12001 flanking 5987435
+37 12003 combed 39654943
+37 12301 Eulerian 5987435
+37 12302 dubbed 28357832
+37 12303 Kane 39654943
+37 12501 annihilates 5987435
+37 12602 Wotan 28357832
+37 12603 snatching 39654943
+37 12701 grazing 5987435
+37 12702 Baird 28357832
+37 12703 celery 39654943
+37 13601 handgun 5987435
+37 13602 foldout 28357832
+37 13603 mystic 39654943
+37 13801 intelligibility 5987435
+37 13802 Augustine 28357832
+37 13803 teethe 39654943
+37 13901 scholastics 5987435
+37 16001 audiology 5987435
+37 16201 wallet 5987435
+37 16202 parters 28357832
+37 16301 eschew 5987435
+37 16302 quitter 28357832
+37 16303 neat 39654943
+37 18001 jarring 5987435
+37 18002 tinily 28357832
+37 18003 balled 39654943
+37 18012 impulsive 28357832
+37 18013 starlet 39654943
+37 18021 lawgiver 5987435
+37 18022 stated 28357832
+37 18023 readable 39654943
+37 18032 testicle 28357832
+37 18033 Parsifal 39654943
+37 18041 Punjab 5987435
+37 18042 Merritt 28357832
+37 18043 Quixotism 39654943
+37 18051 sureties 5987435
+37 18052 puddings 28357832
+37 18053 tapestry 39654943
+37 18061 trimmings 5987435
+37 18062 humility 28357832
+37 18101 tragedies 5987435
+37 18102 skulking 28357832
+37 18103 flint 39654943
+37 18201 relaxing 5987435
+37 18202 offload 28357832
+37 18402 suites 28357832
+37 18403 lists 39654943
+37 18601 vacuuming 5987435
+37 18602 dentally 28357832
+37 18603 humanness 39654943
+37 18801 inch 5987435
+37 18802 Weissmuller 28357832
+37 18803 irresponsibly 39654943
+37 18811 repetitions 5987435
+37 18812 Antares 28357832
+37 19101 ventilate 5987435
+37 19102 pityingly 28357832
+37 19103 interdependent 39654943
+37 19201 Graves 5987435
+37 30501 neonatal 5987435
+37 30502 scribbled 28357832
+37 30503 chafe 39654943
+37 31901 realtor 5987435
+37 36001 elite 5987435
+37 36002 funereal 28357832
+37 38001 Conley 5987435
+37 38002 lectured 28357832
+37 38003 Abraham 39654943
+37 38011 groupings 5987435
+37 38012 dissociate 28357832
+37 38013 coexist 39654943
+37 38101 rusting 5987435
+37 38102 galling 28357832
+37 38103 obliterates 39654943
+37 38201 resumes 5987435
+37 38202 analyzable 28357832
+37 38203 terminator 39654943
+select sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1= t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008;
+sum(price)
+234298
+select t2.fld1,sum(price) from t3,t2 where t2.fld1 = t3.t2nr and t3.companynr = 512 and t3.t2nr = 38008 and t2.fld1 = 38008 or t2.fld1 = t3.t2nr and t3.t2nr = 38008 and t2.fld1 = 38008 or t3.t2nr = t2.fld1 and t2.fld1 = 38008 group by t2.fld1;
+fld1 sum(price)
+038008 234298
+explain select fld3 from t2 where 1>2 or 2>3;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+explain select fld3 from t2 where fld1=fld1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
+select companynr,fld1 from t2 HAVING fld1=250501 or fld1=250502;
+companynr fld1
+34 250501
+34 250502
+select companynr,fld1 from t2 WHERE fld1>=250501 HAVING fld1<=250502;
+companynr fld1
+34 250501
+34 250502
+select companynr,count(*) as count,sum(fld1) as sum from t2 group by companynr having count > 40 and sum/count >= 120000;
+companynr count sum
+00 82 10355753
+29 95 14473298
+34 70 17788966
+37 588 83602098
+41 52 12816335
+select companynr from t2 group by companynr having count(*) > 40 and sum(fld1)/count(*) >= 120000 ;
+companynr
+00
+29
+34
+37
+41
+select t2.companynr,companyname,count(*) from t2,t4 where t2.companynr=t4.companynr group by companyname having t2.companynr >= 40;
+companynr companyname count(*)
+68 company 10 12
+50 company 11 11
+40 company 5 37
+41 company 6 52
+53 company 7 4
+58 company 8 23
+65 company 9 10
+select count(*) from t2;
+count(*)
+1199
+select count(*) from t2 where fld1 < 098024;
+count(*)
+387
+select min(fld1) from t2 where fld1>= 098024;
+min(fld1)
+98024
+select max(fld1) from t2 where fld1>= 098024;
+max(fld1)
+1232609
+select count(*) from t3 where price2=76234234;
+count(*)
+4181
+select count(*) from t3 where companynr=512 and price2=76234234;
+count(*)
+4181
+explain select min(fld1),max(fld1),count(*) from t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+select min(fld1),max(fld1),count(*) from t2;
+min(fld1) max(fld1) count(*)
+0 1232609 1199
+select min(t2nr),max(t2nr) from t3 where t2nr=2115 and price2=823742;
+min(t2nr) max(t2nr)
+2115 2115
+select count(*),min(t2nr),max(t2nr) from t3 where name='spates' and companynr=78;
+count(*) min(t2nr) max(t2nr)
+4181 4 41804
+select t2nr,count(*) from t3 where name='gems' group by t2nr limit 20;
+t2nr count(*)
+9 1
+19 1
+29 1
+39 1
+49 1
+59 1
+69 1
+79 1
+89 1
+99 1
+109 1
+119 1
+129 1
+139 1
+149 1
+159 1
+169 1
+179 1
+189 1
+199 1
+select max(t2nr) from t3 where price=983543950;
+max(t2nr)
+41807
+select t1.period from t3 = t1 limit 1;
+period
+1001
+select t1.period from t1 as t1 limit 1;
+period
+9410
+select t1.period as "Nuvarande period" from t1 as t1 limit 1;
+Nuvarande period
+9410
+select period as ok_period from t1 limit 1;
+ok_period
+9410
+select period as ok_period from t1 group by ok_period limit 1;
+ok_period
+9410
+select 1+1 as summa from t1 group by summa limit 1;
+summa
+2
+select period as "Nuvarande period" from t1 group by "Nuvarande period" limit 1;
+Nuvarande period
+9410
+show tables;
+Tables_in_test
+t1
+t2
+t3
+t4
+show tables from test like "s%";
+Tables_in_test (s%)
+show tables from test like "t?";
+Tables_in_test (t?)
+show full columns from t2;
+Field Type Collation Null Key Default Extra Privileges Comment
+auto int(11) NULL NO PRI NULL auto_increment #
+fld1 int(6) unsigned zerofill NULL NO UNI 000000 #
+companynr tinyint(2) unsigned zerofill NULL NO 00 #
+fld3 char(30) latin1_swedish_ci NO MUL #
+fld4 char(35) latin1_swedish_ci NO #
+fld5 char(35) latin1_swedish_ci NO #
+fld6 char(4) latin1_swedish_ci NO #
+show full columns from t2 from test like 'f%';
+Field Type Collation Null Key Default Extra Privileges Comment
+fld1 int(6) unsigned zerofill NULL NO UNI 000000 #
+fld3 char(30) latin1_swedish_ci NO MUL #
+fld4 char(35) latin1_swedish_ci NO #
+fld5 char(35) latin1_swedish_ci NO #
+fld6 char(4) latin1_swedish_ci NO #
+show full columns from t2 from test like 's%';
+Field Type Collation Null Key Default Extra Privileges Comment
+show keys from t2;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t2 0 PRIMARY 1 auto A 1199 NULL NULL BTREE
+t2 0 fld1 1 fld1 A 1199 NULL NULL BTREE
+t2 1 fld3 1 fld3 A NULL NULL NULL BTREE
+drop table t4, t3, t2, t1;
+CREATE TABLE t1 (
+cont_nr int(11) NOT NULL auto_increment,
+ver_nr int(11) NOT NULL default '0',
+aufnr int(11) NOT NULL default '0',
+username varchar(50) NOT NULL default '',
+hdl_nr int(11) NOT NULL default '0',
+eintrag date NOT NULL default '0000-00-00',
+st_klasse varchar(40) NOT NULL default '',
+st_wert varchar(40) NOT NULL default '',
+st_zusatz varchar(40) NOT NULL default '',
+st_bemerkung varchar(255) NOT NULL default '',
+kunden_art varchar(40) NOT NULL default '',
+mcbs_knr int(11) default NULL,
+mcbs_aufnr int(11) NOT NULL default '0',
+schufa_status char(1) default '?',
+bemerkung text,
+wirknetz text,
+wf_igz int(11) NOT NULL default '0',
+tarifcode varchar(80) default NULL,
+recycle char(1) default NULL,
+sim varchar(30) default NULL,
+mcbs_tpl varchar(30) default NULL,
+emp_nr int(11) NOT NULL default '0',
+laufzeit int(11) default NULL,
+hdl_name varchar(30) default NULL,
+prov_hdl_nr int(11) NOT NULL default '0',
+auto_wirknetz varchar(50) default NULL,
+auto_billing varchar(50) default NULL,
+touch timestamp NOT NULL,
+kategorie varchar(50) default NULL,
+kundentyp varchar(20) NOT NULL default '',
+sammel_rech_msisdn varchar(30) NOT NULL default '',
+p_nr varchar(9) NOT NULL default '',
+suffix char(3) NOT NULL default '',
+PRIMARY KEY (cont_nr),
+KEY idx_aufnr(aufnr),
+KEY idx_hdl_nr(hdl_nr),
+KEY idx_st_klasse(st_klasse),
+KEY ver_nr(ver_nr),
+KEY eintrag_idx(eintrag),
+KEY emp_nr_idx(emp_nr),
+KEY wf_igz(wf_igz),
+KEY touch(touch),
+KEY hdl_tag(eintrag,hdl_nr),
+KEY prov_hdl_nr(prov_hdl_nr),
+KEY mcbs_aufnr(mcbs_aufnr),
+KEY kundentyp(kundentyp),
+KEY p_nr(p_nr,suffix)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (3359356,405,3359356,'Mustermann Musterfrau',52500,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1485525,2122316,'+','','N',1909160,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',3,24,'MobilCom Shop Koeln',52500,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359357,468,3359357,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1503580,2139699,'+','','P',1909171,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359358,407,3359358,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1501358,2137473,'N','','N',1909159,'MobilComSuper92000D2',NULL,NULL,'MS9ND2',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359359,468,3359359,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1507831,2143894,'+','','P',1909162,'MobilComSuper9D1T10SFreisprech(Akquise)',NULL,NULL,'MS9NS1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359360,0,0,'Mustermann Musterfrau',29674907,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1900169997,2414578,'+',NULL,'N',1909148,'',NULL,NULL,'RV99066_2',20,NULL,'POS',29674907,NULL,NULL,20010202105916,'Mobilfunk','','','97317481','007');
+INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag storniert','','(7001-84):Storno, Kd. möchte nicht mehr','privat',NULL,0,'+','','P',1909150,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',325,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','','');
+SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie;
+Kundentyp kategorie
+Privat (Private Nutzung) Mobilfunk
+Warnings:
+Warning 1052 Column 'kundentyp' in group statement is ambiguous
+drop table t1;
+SHOW STATUS LIKE 'Ssl_cipher';
+Variable_name Value
+Ssl_cipher DHE-RSA-AES256-SHA
diff --git a/mysql-test/r/strict_autoinc_1myisam.result b/mysql-test/r/strict_autoinc_1myisam.result
index 5d3c2698cda..90a69bedc74 100644
--- a/mysql-test/r/strict_autoinc_1myisam.result
+++ b/mysql-test/r/strict_autoinc_1myisam.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
set @org_mode=@@sql_mode;
create table t1
(
diff --git a/mysql-test/r/strict_autoinc_2innodb.result b/mysql-test/r/strict_autoinc_2innodb.result
index f1936ff4de3..8a5243173e4 100644
--- a/mysql-test/r/strict_autoinc_2innodb.result
+++ b/mysql-test/r/strict_autoinc_2innodb.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
set @org_mode=@@sql_mode;
create table t1
(
diff --git a/mysql-test/r/strict_autoinc_3heap.result b/mysql-test/r/strict_autoinc_3heap.result
index aa0be270ac5..7dc48357c46 100644
--- a/mysql-test/r/strict_autoinc_3heap.result
+++ b/mysql-test/r/strict_autoinc_3heap.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
set @org_mode=@@sql_mode;
create table t1
(
diff --git a/mysql-test/r/strict_autoinc_4bdb.result b/mysql-test/r/strict_autoinc_4bdb.result
index 73683b645e2..89c4d2537f5 100644
--- a/mysql-test/r/strict_autoinc_4bdb.result
+++ b/mysql-test/r/strict_autoinc_4bdb.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
set @org_mode=@@sql_mode;
create table t1
(
diff --git a/mysql-test/r/strict_autoinc_5ndb.result b/mysql-test/r/strict_autoinc_5ndb.result
index d0d62d05b32..715f9a4b98b 100644
--- a/mysql-test/r/strict_autoinc_5ndb.result
+++ b/mysql-test/r/strict_autoinc_5ndb.result
@@ -1,3 +1,4 @@
+drop table if exists t1;
set @org_mode=@@sql_mode;
create table t1
(
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 98e482a7ff9..43247b56096 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -2717,8 +2717,7 @@ select (1,2,3) = (select * from t1);
ERROR 21000: Operand should contain 3 column(s)
select (select * from t1) = (1,2,3);
ERROR 21000: Operand should contain 2 column(s)
-drop table t1
-#;
+drop table t1;
CREATE TABLE `t1` (
`itemid` bigint(20) unsigned NOT NULL auto_increment,
`sessionid` bigint(20) unsigned default NULL,
diff --git a/mysql-test/r/synchronization.result b/mysql-test/r/synchronization.result
index 0b84697066c..29557b6cfd4 100644
--- a/mysql-test/r/synchronization.result
+++ b/mysql-test/r/synchronization.result
@@ -1,6 +1,6 @@
drop table if exists t1;
CREATE TABLE t1 (x1 int);
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -8,7 +8,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -16,7 +16,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -24,7 +24,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -32,7 +32,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -40,7 +40,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -48,7 +48,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -56,7 +56,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -64,7 +64,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -72,7 +72,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -80,7 +80,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -88,7 +88,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -96,7 +96,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -104,7 +104,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -112,7 +112,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -120,7 +120,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -128,7 +128,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -136,7 +136,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -144,7 +144,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x1 x2 int;
+ALTER TABLE t1 CHANGE x1 x2 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
@@ -152,7 +152,7 @@ t2 CREATE TABLE `t2` (
`xx` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
- ALTER TABLE t1 CHANGE x2 x1 int;
+ALTER TABLE t1 CHANGE x2 x1 int;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result
index 10944c3706e..1223fff36c6 100644
--- a/mysql-test/r/timezone.result
+++ b/mysql-test/r/timezone.result
@@ -41,7 +41,7 @@ Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2
DROP TABLE t1;
select unix_timestamp('1970-01-01 01:00:00'),
unix_timestamp('1970-01-01 01:00:01'),
-unix_timestamp('2038-01-01 00:59:59'),
-unix_timestamp('2038-01-01 01:00:00');
-unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-01 00:59:59') unix_timestamp('2038-01-01 01:00:00')
-0 1 2145916799 0
+unix_timestamp('2038-01-19 04:14:07'),
+unix_timestamp('2038-01-19 04:14:08');
+unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-19 04:14:07') unix_timestamp('2038-01-19 04:14:08')
+0 1 2147483647 0
diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result
index a1ae2f63212..bb1d764ac8c 100644
--- a/mysql-test/r/timezone2.result
+++ b/mysql-test/r/timezone2.result
@@ -116,7 +116,7 @@ create table t1 (ts timestamp);
set time_zone='UTC';
insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'),
('1970-01-01 00:00:00'),('1970-01-01 00:00:01'),
-('2037-12-31 23:59:59'),('2038-01-01 00:00:00');
+('2038-01-19 03:14:07'),('2038-01-19 03:14:08');
Warnings:
Warning 1264 Out of range value adjusted for column 'ts' at row 2
Warning 1264 Out of range value adjusted for column 'ts' at row 3
@@ -127,13 +127,13 @@ ts
0000-00-00 00:00:00
0000-00-00 00:00:00
1970-01-01 00:00:01
-2037-12-31 23:59:59
+2038-01-19 03:14:07
0000-00-00 00:00:00
delete from t1;
set time_zone='MET';
insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'),
('1970-01-01 01:00:00'),('1970-01-01 01:00:01'),
-('2038-01-01 00:59:59'),('2038-01-01 01:00:00');
+('2038-01-19 04:14:07'),('2038-01-19 04:14:08');
Warnings:
Warning 1264 Out of range value adjusted for column 'ts' at row 2
Warning 1264 Out of range value adjusted for column 'ts' at row 3
@@ -144,13 +144,13 @@ ts
0000-00-00 00:00:00
0000-00-00 00:00:00
1970-01-01 01:00:01
-2038-01-01 00:59:59
+2038-01-19 04:14:07
0000-00-00 00:00:00
delete from t1;
set time_zone='+01:30';
insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'),
('1970-01-01 01:30:00'),('1970-01-01 01:30:01'),
-('2038-01-01 01:29:59'),('2038-01-01 01:30:00');
+('2038-01-19 04:44:07'),('2038-01-19 04:44:08');
Warnings:
Warning 1264 Out of range value adjusted for column 'ts' at row 2
Warning 1264 Out of range value adjusted for column 'ts' at row 3
@@ -161,7 +161,7 @@ ts
0000-00-00 00:00:00
0000-00-00 00:00:00
1970-01-01 01:30:01
-2038-01-01 01:29:59
+2038-01-19 04:44:07
0000-00-00 00:00:00
drop table t1;
show variables like 'time_zone';
@@ -223,12 +223,12 @@ convert_tz('2003-10-26 02:59:59', 'MET', 'UTC')
select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC');
convert_tz('2003-10-26 04:00:00', 'MET', 'UTC')
2003-10-26 03:00:00
-select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC');
-convert_tz('2038-01-01 00:59:59', 'MET', 'UTC')
-2037-12-31 23:59:59
-select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC');
-convert_tz('2038-01-01 01:00:00', 'MET', 'UTC')
-2038-01-01 01:00:00
+select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC');
+convert_tz('2038-01-19 04:14:07', 'MET', 'UTC')
+2038-01-19 03:14:07
+select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC');
+convert_tz('2038-01-19 04:14:08', 'MET', 'UTC')
+2038-01-19 04:14:08
select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC');
convert_tz('2103-01-01 04:00:00', 'MET', 'UTC')
2103-01-01 04:00:00
diff --git a/mysql-test/r/timezone4.result b/mysql-test/r/timezone4.result
new file mode 100644
index 00000000000..28028bea657
--- /dev/null
+++ b/mysql-test/r/timezone4.result
@@ -0,0 +1,6 @@
+select from_unixtime(0);
+from_unixtime(0)
+1969-12-31 14:00:00
+select unix_timestamp('1969-12-31 14:00:01');
+unix_timestamp('1969-12-31 14:00:01')
+1
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 0b0bf1086db..9f34f60eb1a 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -1073,10 +1073,11 @@ SELECT @x;
NULL
SET @x=2;
UPDATE t1 SET i1 = @x;
-ERROR 22012: Division by 0
+Warnings:
+Error 1365 Division by 0
SELECT @x;
@x
-2
+NULL
SET SQL_MODE='';
SET @x=3;
INSERT INTO t1 VALUES (@x);
@@ -1085,10 +1086,12 @@ SELECT @x;
NULL
SET @x=4;
UPDATE t1 SET i1 = @x;
-ERROR 22012: Division by 0
+Warnings:
+Error 1365 Division by 0
+Error 1365 Division by 0
SELECT @x;
@x
-4
+NULL
SET @@sql_mode=@save_sql_mode;
DROP TRIGGER t1_ai;
DROP TRIGGER t1_au;
@@ -1174,6 +1177,59 @@ ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghi
DROP TABLE t1;
DROP TABLE t2;
drop table if exists t1;
+drop table if exists t2;
+drop table if exists t3;
+drop table if exists t4;
+SET @save_sql_mode=@@sql_mode;
+SET sql_mode='TRADITIONAL'|
+create table t1 (id int(10) not null primary key, v int(10) )|
+create table t2 (id int(10) not null primary key, v int(10) )|
+create table t3 (id int(10) not null primary key, v int(10) )|
+create table t4 (c int)|
+create trigger t4_bi before insert on t4 for each row set @t4_bi_called:=1|
+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
+select 1/0 from t1|
+1/0
+NULL
+Warnings:
+Error 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
+drop trigger t1_bi|
+create trigger t1_bi before insert on t1 for each row
+begin
+insert into t2 values (new.id, new.v);
+update t2 set v=v+1 where id= new.id;
+replace t3 values (new.id, 0);
+update t2, t3 set t2.v=new.v, t3.v=new.v where t2.id=t3.id;
+create temporary table t5 select * from t1;
+delete from t5;
+insert into t5 select * from t1;
+insert into t4 values (0);
+set @check= (select count(*) from t5);
+update t4 set c= @check;
+drop temporary table t5;
+set @a:=1/0;
+end|
+set @check=0, @t4_bi_called=0, @t4_bu_called=0|
+insert into t1 values(30, 30)|
+Warnings:
+Error 1365 Division by 0
+select @check, @t4_bi_called, @t4_bu_called|
+@check @t4_bi_called @t4_bu_called
+2 1 1
+SET @@sql_mode=@save_sql_mode;
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table if exists t1;
create table t1 (i int, j int key);
insert into t1 values (1,1), (2,2), (3,3);
create trigger t1_bu before update on t1 for each row
@@ -1185,4 +1241,41 @@ i j
2 2
13 13
drop table t1;
+drop table if exists t1;
+drop function if exists f1;
+create table t1 (i int);
+create function f1() returns int return 10;
+create trigger t1_bi before insert on t1 for each row set @a:= f1() + 10;
+insert into t1 values ();
+select @a;
+@a
+20
+insert into t1 values ();
+select @a;
+@a
+20
+drop table t1;
+drop function f1;
+drop table if exists t1;
+create table t1(a int, b varchar(50));
+drop trigger not_a_trigger;
+ERROR HY000: Trigger does not exist
+drop trigger if exists not_a_trigger;
+Warnings:
+Note 1360 Trigger does not exist
+create trigger t1_bi before insert on t1
+for each row set NEW.b := "In trigger t1_bi";
+insert into t1 values (1, "a");
+drop trigger if exists t1_bi;
+insert into t1 values (2, "b");
+drop trigger if exists t1_bi;
+Warnings:
+Note 1360 Trigger does not exist
+insert into t1 values (3, "c");
+select * from t1;
+a b
+1 In trigger t1_bi
+2 b
+3 c
+drop table t1;
End of 5.0 tests
diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result
index bd58e83bb3f..f3883077919 100644
--- a/mysql-test/r/type_bit.result
+++ b/mysql-test/r/type_bit.result
@@ -610,4 +610,12 @@ select hex(a), b from t1;
hex(a) b
1 2
drop table t1;
+create table t1(bit_field bit(2), int_field int, key a(bit_field));
+insert into t1 values (1,2);
+handler t1 open as t1;
+handler t1 read a=(1);
+bit_field int_field
+ 2
+handler t1 close;
+drop table t1;
End of 5.0 tests
diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result
index 23e6f8266e9..e65e76ded3f 100644
--- a/mysql-test/r/type_newdecimal.result
+++ b/mysql-test/r/type_newdecimal.result
@@ -978,8 +978,6 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
drop procedure if exists wg2;
-Warnings:
-Note 1305 PROCEDURE wg2 does not exist
create procedure wg2()
begin
declare v int default 1;
@@ -1420,3 +1418,8 @@ f1
20101112000000.000014
101112.000000
drop table t1;
+select cast(19999999999999999999 as unsigned);
+cast(19999999999999999999 as unsigned)
+18446744073709551615
+Warnings:
+Error 1292 Truncated incorrect DECIMAL value: ''
diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result
index 1d707b83a4d..f6c2f4d01a6 100644
--- a/mysql-test/r/type_varchar.result
+++ b/mysql-test/r/type_varchar.result
@@ -453,3 +453,39 @@ id name_id id en cz
2 3 2 en string 2 cz string 2
3 3 3 en string 3 cz string 3
drop table t1, t2, t3;
+CREATE TABLE t1 (a CHAR(2));
+INSERT INTO t1 VALUES (10), (50), (30), ('1a'), (60), ('t');
+SELECT a,(a + 0) FROM t1 ORDER BY a;
+a (a + 0)
+10 10
+1a 1
+30 30
+50 50
+60 60
+t 0
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: '1a'
+Warning 1292 Truncated incorrect DOUBLE value: 't '
+SELECT a,(a DIV 2) FROM t1 ORDER BY a;
+a (a DIV 2)
+10 5
+1a 0
+30 15
+50 25
+60 30
+t 0
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '1a'
+Warning 1292 Truncated incorrect INTEGER value: 't '
+SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a;
+a CAST(a AS SIGNED)
+10 10
+1a 1
+30 30
+50 50
+60 60
+t 0
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '1a'
+Warning 1292 Truncated incorrect INTEGER value: 't'
+DROP TABLE t1;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 12463658bf9..dc174e35c8f 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -836,27 +836,27 @@ count(*)
26
show status like 'Slow_queries';
Variable_name Value
-Slow_queries 1
+Slow_queries 0
select count(*) from t1 where b=13;
count(*)
10
show status like 'Slow_queries';
Variable_name Value
-Slow_queries 3
+Slow_queries 1
select count(*) from t1 where b=13 union select count(*) from t1 where a=7;
count(*)
10
26
show status like 'Slow_queries';
Variable_name Value
-Slow_queries 5
+Slow_queries 2
select count(*) from t1 where a=7 union select count(*) from t1 where b=13;
count(*)
26
10
show status like 'Slow_queries';
Variable_name Value
-Slow_queries 7
+Slow_queries 3
flush status;
select a from t1 where b not in (1,2,3) union select a from t1 where b not in (4,5,6);
a
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 1664a907c99..90954fc1ede 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -215,6 +215,7 @@ select @@version;
select @@global.version;
@@global.version
#
+End of 4.1 tests
set @first_var= NULL;
create table t1 select @first_var;
show create table t1;
@@ -301,3 +302,11 @@ select @var;
@var
3
drop table t1;
+insert into city 'blah';
+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 ''blah'' at line 1
+SHOW COUNT(*) WARNINGS;
+@@session.warning_count
+1
+SHOW COUNT(*) ERRORS;
+@@session.error_count
+1
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index b7d2d13d495..81711f95ae6 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -12,6 +12,9 @@ create table t1 (a int, b int);
insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
ERROR HY000: View's SELECT contains a variable or parameter
+create view v1 (c,d) as select a,b from t1
+where a = @@global.max_user_connections;
+ERROR HY000: View's SELECT contains a variable or parameter
create view v1 (c) as select b+1 from t1;
select c from v1;
c
@@ -596,11 +599,6 @@ ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function
drop view v1;
create view v1 (a,a) as select 'a','a';
ERROR 42S21: Duplicate column name 'a'
-drop procedure if exists p1;
-create procedure p1 () begin declare v int; create view v1 as select v; end;//
-call p1();
-ERROR HY000: View's SELECT contains a variable or parameter
-drop procedure p1;
create table t1 (col1 int,col2 char(22));
insert into t1 values(5,'Hello, world of views');
create view v1 as select * from t1;
@@ -886,6 +884,8 @@ ERROR HY000: View's SELECT contains a 'INTO' clause
create table t1 (a int);
create view v1 as select a from t1 procedure analyse();
ERROR HY000: View's SELECT contains a 'PROCEDURE' clause
+create view v1 as select 1 from (select 1) as d1;
+ERROR HY000: View's SELECT contains a subquery in the FROM clause
drop table t1;
create table t1 (s1 int, primary key (s1));
create view v1 as select * from t1;
@@ -1980,7 +1980,7 @@ v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI
drop view v1;
drop table t1;
set sql_mode='strict_all_tables';
-CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
+CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL);
CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
INSERT INTO t1 (col1) VALUES(12);
@@ -2032,7 +2032,7 @@ f3 f1
1 3
drop view v1;
drop table t1;
-CREATE TABLE t1 (f1 char) ENGINE = innodb;
+CREATE TABLE t1 (f1 char);
INSERT INTO t1 VALUES ('A');
CREATE VIEW v1 AS SELECT * FROM t1;
INSERT INTO t1 VALUES('B');
@@ -2956,6 +2956,20 @@ View Create View
v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`pk` AS `pk` from (`t1` join `t2` on(((`t2`.`fk` = `t1`.`pk`) and (`t2`.`ver` = (select max(`t`.`ver`) AS `MAX(t.ver)` from `t2` `t` where (`t`.`org` = `t2`.`org`))))))
DROP VIEW v1;
DROP TABLE t1, t2;
+DROP FUNCTION IF EXISTS f1;
+DROP VIEW IF EXISTS v1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT);
+INSERT INTO t1 VALUES (1);
+CREATE VIEW v1 AS SELECT MAX(i) FROM t1;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+SET NEW.i = (SELECT * FROM v1) + 1;
+INSERT INTO t1 VALUES (1);
+CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1);
+UPDATE t1 SET i= f1();
+DROP FUNCTION f1;
+DROP VIEW v1;
+DROP TABLE t1;
CREATE TABLE t1(id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, val INT UNSIGNED NOT NULL);
CREATE VIEW v1 AS SELECT id, val FROM t1 WHERE val >= 1 AND val <= 5 WITH CHECK OPTION;
INSERT INTO v1 (val) VALUES (2);
@@ -2966,4 +2980,38 @@ UPDATE v1 SET val=6 WHERE id=2;
ERROR HY000: CHECK OPTION failed 'test.v1'
DROP VIEW v1;
DROP TABLE t1;
+DROP VIEW IF EXISTS v1, v2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT);
+CREATE VIEW v1 AS SELECT j FROM t1;
+CREATE VIEW v2 AS SELECT * FROM t1;
+INSERT INTO t1 (j) VALUES (1);
+SELECT LAST_INSERT_ID();
+LAST_INSERT_ID()
+1
+INSERT INTO v1 (j) VALUES (2);
+# LAST_INSERT_ID() should not change.
+SELECT LAST_INSERT_ID();
+LAST_INSERT_ID()
+1
+INSERT INTO v2 (j) VALUES (3);
+# LAST_INSERT_ID() should be updated.
+SELECT LAST_INSERT_ID();
+LAST_INSERT_ID()
+3
+INSERT INTO v1 (j) SELECT j FROM t1;
+# LAST_INSERT_ID() should not change.
+SELECT LAST_INSERT_ID();
+LAST_INSERT_ID()
+3
+SELECT * FROM t1;
+i j
+1 1
+2 2
+3 3
+4 1
+5 2
+6 3
+DROP VIEW v1, v2;
+DROP TABLE t1;
End of 5.0 tests.
diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result
index 35e7afc0a7b..1e8aa1d05db 100644
--- a/mysql-test/r/view_grant.result
+++ b/mysql-test/r/view_grant.result
@@ -712,3 +712,22 @@ DROP FUNCTION f1;
DROP VIEW v2;
DROP VIEW v1;
DROP USER mysqltest_u1@localhost;
+CREATE DATABASE db17254;
+USE db17254;
+CREATE TABLE t1 (f1 INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE USER def_17254@localhost;
+GRANT SELECT ON db17254.* TO def_17254@localhost;
+CREATE USER inv_17254@localhost;
+GRANT SELECT ON db17254.t1 TO inv_17254@localhost;
+GRANT CREATE VIEW ON db17254.* TO def_17254@localhost;
+CREATE VIEW v1 AS SELECT * FROM t1;
+DROP USER def_17254@localhost;
+for a user
+SELECT * FROM v1;
+ERROR 42000: SELECT command denied to user 'inv_17254'@'localhost' for table 'v1'
+for a superuser
+SELECT * FROM v1;
+ERROR HY000: There is no 'def_17254'@'localhost' registered
+DROP USER inv_17254@localhost;
+DROP DATABASE db17254;
diff --git a/mysql-test/std_data/bad_gis_data.dat b/mysql-test/std_data/bad_gis_data.dat
new file mode 100644
index 00000000000..257cc5642cb
--- /dev/null
+++ b/mysql-test/std_data/bad_gis_data.dat
@@ -0,0 +1 @@
+foo
diff --git a/mysql-test/std_data/server-cert-des.pem b/mysql-test/std_data/server-cert-des.pem
new file mode 100644
index 00000000000..3b93d865d5b
--- /dev/null
+++ b/mysql-test/std_data/server-cert-des.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICljCCAX4CAQEwDQYJKoZIhvcNAQEEBQAwUTELMAkGA1UEBhMCU0UxEDAOBgNV
+BAgTB1VwcHNhbGExETAPBgNVBAoTCE15U1FMIEFCMRAwDgYDVQQLEwdTdXBwb3J0
+MQswCQYDVQQDEwJDQTAeFw0wNjA4MjgxMTA4NTlaFw0wOTA1MjQxMTA4NTlaMFUx
+CzAJBgNVBAYTAlNFMRAwDgYDVQQIEwdVcHBzYWxhMREwDwYDVQQKEwhNeVNRTCBB
+QjEQMA4GA1UECxMHU3VwcG9ydDEPMA0GA1UEAxMGc2VydmVyMIGfMA0GCSqGSIb3
+DQEBAQUAA4GNADCBiQKBgQDEiOVZcWYzZe7I8xhhUwCzvmkZifAXeMTH+8XKGLHX
+NWF3FLduAmeAad9oOZgBKb+oWTdRDWXqwu6nYYUBfrUpaY27/wLkgWRgewL3LZnw
+W2FjhNsjx3gI2NK+Pix47q9d+a+5T4AW5+lK499l0K0k2cvyFdIerhDW8R0t8Uru
+twIDAQABMA0GCSqGSIb3DQEBBAUAA4IBAQC2LQcqLg52RbelWrKutlJ5E6rzugnJ
+ZAlbN9sM98O2xFiIGDA3tb5j9LAEjE0E+RqdptEYnvy9b3szhLYXtIILZTkClf9r
+Uwu1nUYPTyp+9ZYCa4fovOU5h1Ogv+9UZPds/LPDwWEn8K+lvscB4X57wJyuoEck
+1Mu41OA6h77181MydSdgZo0oquJDWhdCsYHXVFVs0F6naMm2uPMCTDiQVlhHJuTO
+VQMNIwxRFtvsv2tpsXsaP/8sT32d5CFebfxxSVnqQvJ4ZdIrphl6L43XU01rsEcE
+K8KYujZQ6SKws+HVcGqsr7TPgJfJE6D+5RazvvIQISPvx4eduebqzqdC
+-----END CERTIFICATE-----
diff --git a/mysql-test/std_data/server-key-des.pem b/mysql-test/std_data/server-key-des.pem
new file mode 100644
index 00000000000..b35d4ab223b
--- /dev/null
+++ b/mysql-test/std_data/server-key-des.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,D2BE7598C7E3BDA5
+
+1W3qPgw5ut80OhaAGVZZe/tfFiBAlwpX1SohdApWj+QYP+dK/mdEBhgI3BXTFNLW
+pJqDTzGlKtft7hHN6QDFEdZMKxej5+2iLu14V62o+5yQgUoqswoXcmmqJCJ7AvyJ
+yMBmGAzxRFlQsT8lf6o5TS1/efBvjvWhh3NG2Zq2LpyhWRRqA3kNhzktzt2WjDZe
+ZkKmZJJnArr/Aw7jEBC4sH+nmgxoR18GzDddRG12hv1AWyHc3+VisTBpyNzeBy17
+rxuQtqLzkAJmId723ddw83RVNSvBUUS3G0rx5O3HPobvZK89UqVxcXtIgc11WTVU
+N3DbcJq5it43Loo0W3gAngtESDm2E3rTadrmdUSDGv2wQ5dNFl6cQ1f397Sdd/WC
+A0grn1tKjJ6COp80Ymdyvn+stjv/+Rl1/KHSeG0lNeZxqjPPOJ7NHaKv7qjYsJ6W
+LT35/Xc3oCo5qk9FOlq/0tGjHxf6RcFr5U7k5ILKZs+RmvJ4Sv/VYShLfLTcfGbJ
+wBNfRKvcHZBQJQBb1+s/kRrjFFtvhrUwLz4+c9kskp+t4qRVYywUAnGGGsMs/GPm
+wYsLQZO6Bs5/taaVUyaJQW015J7FGGv+/7/A1dIhu73S/Xl/YcFbX/CMEVq2Lxxd
+hZdFIuaZ7LE+0MDQWsvYMYPDPLDH11diczb/jeKBdLPOzk/FUqVx3Fin1PpcaBxY
+b+7oZJhYdg/rAWDeQ/nji9qnEG8waK6x1hdkYPOrqqWQPfgM/LPsSrgWeuTSdx2B
+Ixi01UlBb5UP4K7UrjyddPobmcVjXaQLNe7zaq0+OS3UnIG85GtHrQ==
+-----END RSA PRIVATE KEY-----
diff --git a/mysql-test/t/bdb-alter-table-2-master.opt b/mysql-test/t/bdb-alter-table-2-master.opt
index 15ad73c500f..c2dca33445b 100644
--- a/mysql-test/t/bdb-alter-table-2-master.opt
+++ b/mysql-test/t/bdb-alter-table-2-master.opt
@@ -1,2 +1,2 @@
---skip-external-locking
+--force-restart
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index fef9d4552e6..2147d5b71af 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -55,6 +55,7 @@ flush privileges;
connect (con10,localhost,test,gambling2,);
connect (con5,localhost,test,gambling2,mysql);
+connection con5;
set password="";
--error 1372
set password='gambling3';
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index db73782fdbf..eef6ec85bfa 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -550,7 +550,7 @@ create table t1 (
a varchar(112) charset utf8 collate utf8_bin not null,
primary key (a)
) select 'test' as a ;
---warning 1364
+#--warning 1364
show create table t1;
drop table t1;
@@ -563,7 +563,7 @@ CREATE TABLE t2 (
);
insert into t2 values(111);
---warning 1364
+#--warning 1364
create table t1 (
a varchar(12) charset utf8 collate utf8_bin not null,
b int not null, primary key (a)
@@ -571,7 +571,7 @@ create table t1 (
show create table t1;
drop table t1;
---warning 1364
+#--warning 1364
create table t1 (
a varchar(12) charset utf8 collate utf8_bin not null,
b int not null, primary key (a)
@@ -579,7 +579,7 @@ create table t1 (
show create table t1;
drop table t1;
---warning 1364
+#--warning 1364
create table t1 (
a varchar(12) charset utf8 collate utf8_bin not null,
b int null, primary key (a)
@@ -587,7 +587,7 @@ create table t1 (
show create table t1;
drop table t1;
---warning 1364
+#--warning 1364
create table t1 (
a varchar(12) charset utf8 collate utf8_bin not null,
b int not null, primary key (a)
@@ -595,7 +595,7 @@ create table t1 (
show create table t1;
drop table t1;
---warning 1364
+#--warning 1364
create table t1 (
a varchar(12) charset utf8 collate utf8_bin,
b int not null, primary key (a)
@@ -609,7 +609,7 @@ create table t1 (
);
insert into t1 values (1,1,1, 1,1,1, 1,1,1);
---warning 1364
+#--warning 1364
create table t2 (
a1 varchar(12) charset utf8 collate utf8_bin not null,
a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int,
@@ -617,20 +617,20 @@ create table t2 (
) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1 ;
drop table t2;
---warning 1364
+#--warning 1364
create table t2 (
a1 varchar(12) charset utf8 collate utf8_bin,
a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int
) select a1,a2,a3,a4,a5,a6,a7,a8,a9 from t1;
drop table t1, t2;
---warning 1364
+#--warning 1364
create table t1 (
a1 int, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int
);
insert into t1 values (1,1,1, 1,1,1, 1,1,1);
---warning 1364
+#--warning 1364
create table t2 (
a1 varchar(12) charset utf8 collate utf8_bin not null,
a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int,
@@ -667,14 +667,6 @@ show create table t1;
drop table t1;
#
-# Bug#17530: Incorrect key truncation on table creation caused server crash.
-#
-create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb
- character set utf8 collate utf8_general_ci;
-insert into t1 values('aaa');
-drop table t1;
-
-#
# Bug#21772: can not name a column 'upgrade' when create a table
#
create table t1 (upgrade int);
diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test
index 8bd48b7da2c..830bdaa3cf0 100644
--- a/mysql-test/t/csv.test
+++ b/mysql-test/t/csv.test
@@ -1295,7 +1295,7 @@ SELECT fld3 FROM t2;
#
DROP TABLE t1;
-ALTER TABLE t2 RENAME t1
+ALTER TABLE t2 RENAME t1;
#
# Drop and recreate
@@ -1360,27 +1360,27 @@ DROP TABLE bug14672;
create table t1 (a int) engine=csv;
insert t1 values (1);
--enable_info
-delete from t1; -- delete_row
-delete from t1; -- delete_all_rows
+delete from t1; # delete_row
+delete from t1; # delete_all_rows
--disable_info
insert t1 values (1),(2);
--enable_info
-delete from t1; -- delete_all_rows
+delete from t1; # delete_all_rows
--disable_info
insert t1 values (1),(2),(3);
flush tables;
--enable_info
-delete from t1; -- delete_row
+delete from t1; # delete_row
--disable_info
insert t1 values (1),(2),(3),(4);
flush tables;
select count(*) from t1;
--enable_info
-delete from t1; -- delete_all_rows
+delete from t1; # delete_all_rows
--disable_info
insert t1 values (1),(2),(3),(4),(5);
--enable_info
-truncate table t1; -- truncate
+truncate table t1; # truncate
--disable_info
drop table t1;
diff --git a/mysql-test/t/ctype_collate.test b/mysql-test/t/ctype_collate.test
index e59693680bf..aca240b46bc 100644
--- a/mysql-test/t/ctype_collate.test
+++ b/mysql-test/t/ctype_collate.test
@@ -59,7 +59,7 @@ INSERT INTO t1 (latin1_f) VALUES (_latin1'Z');
INSERT INTO t1 (latin1_f) VALUES (_latin1'z');
--- ORDER BY
+# ORDER BY
SELECT latin1_f FROM t1 ORDER BY latin1_f;
SELECT latin1_f FROM t1 ORDER BY latin1_f COLLATE latin1_swedish_ci;
@@ -69,9 +69,9 @@ SELECT latin1_f FROM t1 ORDER BY latin1_f COLLATE latin1_bin;
--error 1253
SELECT latin1_f FROM t1 ORDER BY latin1_f COLLATE koi8r_general_ci;
---SELECT latin1_f COLLATE koi8r FROM t1 ;
+# SELECT latin1_f COLLATE koi8r FROM t1 ;
--- AS + ORDER BY
+# AS + ORDER BY
SELECT latin1_f COLLATE latin1_swedish_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as;
SELECT latin1_f COLLATE latin1_german2_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as;
SELECT latin1_f COLLATE latin1_general_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as;
@@ -80,7 +80,7 @@ SELECT latin1_f COLLATE latin1_bin AS latin1_f_as FROM t1 ORDER BY latin1
SELECT latin1_f COLLATE koi8r_general_ci AS latin1_f_as FROM t1 ORDER BY latin1_f_as;
--- GROUP BY
+# GROUP BY
SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f;
SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f COLLATE latin1_swedish_ci;
@@ -91,7 +91,7 @@ SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f COLLATE latin1_bin;
SELECT latin1_f,count(*) FROM t1 GROUP BY latin1_f COLLATE koi8r_general_ci;
--- DISTINCT
+# DISTINCT
SELECT DISTINCT latin1_f FROM t1;
SELECT DISTINCT latin1_f COLLATE latin1_swedish_ci FROM t1;
@@ -102,21 +102,20 @@ SELECT DISTINCT latin1_f COLLATE latin1_bin FROM t1;
SELECT DISTINCT latin1_f COLLATE koi8r FROM t1;
--- Aggregates
---SELECT MAX(k COLLATE latin1_german2_ci)
---FROM t1
-
-
--- WHERE
---SELECT *
---FROM t1
---WHERE (_latin1'Mu"ller' COLLATE latin1_german2_ci) = k
-
---HAVING
---SELECT *
---FROM t1
---HAVING (_latin1'Mu"ller' COLLATE latin1_german2_ci) = k
-
+# Aggregates
+
+--disable_parsing
+SELECT MAX(k COLLATE latin1_german2_ci)
+FROM t1
+WHERE
+SELECT *
+FROM t1
+WHERE (_latin1'Mu"ller' COLLATE latin1_german2_ci) = k
+HAVING
+SELECT *
+FROM t1
+HAVING (_latin1'Mu"ller' COLLATE latin1_german2_ci) = k;
+--enable_parsing
#
# Check that SHOW displays COLLATE clause
diff --git a/mysql-test/t/ctype_cp1250_ch.test b/mysql-test/t/ctype_cp1250_ch.test
index 65550e0c193..86eb8c31d99 100644
--- a/mysql-test/t/ctype_cp1250_ch.test
+++ b/mysql-test/t/ctype_cp1250_ch.test
@@ -1,5 +1,9 @@
-- source include/have_cp1250_ch.inc
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
SHOW COLLATION LIKE 'cp1250_czech_cs';
#
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 6c814368c88..5a3720dc431 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -298,7 +298,7 @@ INSERT INTO t1 VALUES (0xA),(0xAA),(0xAAA),(0xAAAA),(0xAAAAA);
SELECT HEX(a) FROM t1;
DROP TABLE t1;
--- the same should be also done with enum and set
+# the same should be also done with enum and set
#
@@ -455,6 +455,23 @@ drop table t1;
deallocate prepare stmt;
#
+# Bug#22052 Trailing spaces are not removed from UNICODE fields in an index
+#
+create table t1 (
+ a char(10) unicode not null,
+ index a (a)
+) engine=myisam;
+insert into t1 values (repeat(0x201f, 10));
+insert into t1 values (repeat(0x2020, 10));
+insert into t1 values (repeat(0x2021, 10));
+# make sure "index read" is used
+explain select hex(a) from t1 order by a;
+select hex(a) from t1 order by a;
+alter table t1 drop index a;
+select hex(a) from t1 order by a;
+drop table t1;
+
+#
# Bug #20076: server crashes for a query with GROUP BY if MIN/MAX aggregation
# over a 'ucs2' field uses a temporary table
#
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 29e6eab03de..71259dab0c9 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1228,21 +1228,49 @@ set @a:=null;
execute my_stmt using @a;
drop table if exists t1;
+
+#
+# Bug#21505 Create view - illegal mix of collation for operation 'UNION'
+#
+--disable_warnings
+drop table if exists t1;
+drop view if exists v1, v2;
+--enable_warnings
+set names utf8;
+create table t1(col1 varchar(12) character set utf8 collate utf8_unicode_ci);
+insert into t1 values('t1_val');
+create view v1 as select 'v1_val' as col1;
+select coercibility(col1), collation(col1) from v1;
+create view v2 as select col1 from v1 union select col1 from t1;
+select coercibility(col1), collation(col1)from v2;
+drop view v1, v2;
+create view v1 as select 'v1_val' collate utf8_swedish_ci as col1;
+select coercibility(col1), collation(col1) from v1;
+create view v2 as select col1 from v1 union select col1 from t1;
+select coercibility(col1), collation(col1) from v2;
+drop view v1, v2;
+drop table t1;
+
+
#
# Bug#19960: Inconsistent results when joining
# InnoDB tables using partial UTF8 indexes
#
+--disable_warnings
CREATE TABLE t1 (
colA int(11) NOT NULL,
colB varchar(255) character set utf8 NOT NULL,
PRIMARY KEY (colA)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+--enable_warnings
INSERT INTO t1 (colA, colB) VALUES (1, 'foo'), (2, 'foo bar');
+--disable_warnings
CREATE TABLE t2 (
colA int(11) NOT NULL,
colB varchar(255) character set utf8 NOT NULL,
KEY bad (colA,colB(3))
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+--enable_warnings
INSERT INTO t2 (colA, colB) VALUES (1, 'foo'),(2, 'foo bar');
SELECT * FROM t1 JOIN t2 ON t1.colA=t2.colA AND t1.colB=t2.colB
WHERE t1.colA < 3;
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 007847fab37..df56165950f 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -11,3 +11,4 @@
##############################################################################
ndb_load : Bug#17233
+user_limits : Bug#23921 random failure of user_limits.test
diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test
index eeb5d509b94..68f07f258bf 100644
--- a/mysql-test/t/func_compress.test
+++ b/mysql-test/t/func_compress.test
@@ -56,7 +56,19 @@ insert into t1 values(NULL), (compress('a'));
select uncompress(a), uncompressed_length(a) from t1;
drop table t1;
-# End of 4.1 tests
+#
+# Bug #23254: problem with compress(NULL)
+#
+
+create table t1(a blob);
+insert into t1 values ('0'), (NULL), ('0');
+--disable_result_log
+select compress(a), compress(a) from t1;
+--enable_result_log
+select compress(a) is null from t1;
+drop table t1;
+
+--echo End of 4.1 tests
#
# Bug #18539: uncompress(d) is null: impossible?
diff --git a/mysql-test/t/func_date_add.test b/mysql-test/t/func_date_add.test
index e01fce30577..b575eeececa 100644
--- a/mysql-test/t/func_date_add.test
+++ b/mysql-test/t/func_date_add.test
@@ -64,4 +64,17 @@ insert into t1 values (date_add('2000-01-04', INTERVAL NULL DAY));
select * from t1;
drop table t1;
-# End of 4.1 tests
+--echo End of 4.1 tests
+
+#
+# Bug#21811
+#
+# Make sure we end up with an appropriate
+# date format (DATE) after addition operation
+#
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY;
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH;
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR;
+SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK;
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index 1065bb5b93e..3ff4b35873b 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -29,8 +29,10 @@ select grp,group_concat(c order by c) from t1 group by grp;
select grp,group_concat(c order by c desc) from t1 group by grp;
select grp,group_concat(d order by a) from t1 group by grp;
select grp,group_concat(d order by a desc) from t1 group by grp;
+--disable_warnings
select grp,group_concat(a order by a,d+c-ascii(c)-a) from t1 group by grp;
select grp,group_concat(a order by d+c-ascii(c),a) from t1 group by grp;
+--enable_warnings
select grp,group_concat(c order by 1) from t1 group by grp;
select grp,group_concat(distinct c order by c) from t1 group by grp;
select grp,group_concat(distinct c order by c desc) from t1 group by grp;
@@ -98,7 +100,7 @@ select ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'withou
select distinct ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'with distinct: cutoff at length of shortname' from t1;
drop table t1;
-# check zero rows
+# check zero rows (bug#836)
create table t1(id int);
create table t2(id int);
insert into t1 values(0),(1);
@@ -461,3 +463,38 @@ SELECT GROUP_CONCAT(a), x
GROUP BY x;
DROP TABLE t1;
+#
+# Bug#23451 GROUP_CONCAT truncates a multibyte utf8 character
+#
+set names utf8;
+create table t1
+(
+ x text character set utf8 not null,
+ y integer not null
+);
+insert into t1 values (repeat('a', 1022), 0), (repeat(_utf8 0xc3b7, 4), 0);
+let $1= 10;
+while ($1)
+{
+ eval set group_concat_max_len= 1022 + $1;
+ --disable_result_log
+ select @x:=group_concat(x) from t1 group by y;
+ --enable_result_log
+ select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12);
+ dec $1;
+}
+drop table t1;
+set group_concat_max_len=1024;
+set names latin1;
+
+#
+# Bug#14169 type of group_concat() result changed to blob if tmp_table was used
+#
+create table t1 (f1 int unsigned, f2 varchar(255));
+insert into t1 values (1,repeat('a',255)),(2,repeat('b',255));
+--enable_metadata
+select f2,group_concat(f1) from t1 group by f2;
+--disable_metadata
+drop table t1;
+
+# End of 4.1 tests
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 089f5ed9911..bccd4d9e762 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -29,7 +29,9 @@ select count(distinct a),count(distinct grp) from t1;
select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
+--disable_warnings
select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
+--enable_warnings
create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index 8ddf1fbe314..d48606ac6e6 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -109,7 +109,28 @@ select count(*) from t1 where id not in (1);
select count(*) from t1 where id not in (1,2);
drop table t1;
-# End of 4.1 tests
+
+#
+# BUG#17047: CHAR() and IN() can return NULL without signaling NULL
+# result
+#
+# The problem was in the IN() function that ignored maybe_null flags
+# of all arguments except the first (the one _before_ the IN
+# keyword, '1' in the test case below).
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 SELECT 1 IN (2, NULL);
+--echo SELECT should return NULL.
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+
+--echo End of 4.1 tests
+
#
# Bug #11885: WHERE condition with NOT IN (one element)
@@ -232,3 +253,6 @@ select some_id from t1 where some_id not in(2,-1);
select some_id from t1 where some_id not in(-4,-1,-4);
select some_id from t1 where some_id not in(-4,-1,3423534,2342342);
drop table t1;
+
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test
index 97101fba615..77d7366afe6 100644
--- a/mysql-test/t/func_sapdb.test
+++ b/mysql-test/t/func_sapdb.test
@@ -35,7 +35,7 @@ SET @@SQL_MODE="ALLOW_INVALID_DATES";
select datediff("1997-11-31 23:59:59.000001","1997-12-31");
SET @@SQL_MODE="";
--- This will give a warning
+# This will give a warning
select datediff("1997-11-31 23:59:59.000001","1997-12-31");
select datediff("1997-11-30 23:59:59.000001",null);
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 45415882ac7..af4f8b9a9d2 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -300,18 +300,26 @@ select POSITION(_latin1'B' COLLATE latin1_general_ci IN _latin1'abcd' COLLATE la
select POSITION(_latin1'B' IN _latin2'abcd');
select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d');
---fix this:
---select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d' COLLATE latin1_bin);
---select FIND_IN_SET(_latin1'B' COLLATE latin1_bin,_latin1'a,b,c,d');
+
+# fix this:
+--disable_parsing
+select FIND_IN_SET(_latin1'B',_latin1'a,b,c,d' COLLATE latin1_bin);
+select FIND_IN_SET(_latin1'B' COLLATE latin1_bin,_latin1'a,b,c,d');
+--enable_parsing
+
--error 1267
select FIND_IN_SET(_latin1'B' COLLATE latin1_general_ci,_latin1'a,b,c,d' COLLATE latin1_bin);
--error 1267
select FIND_IN_SET(_latin1'B',_latin2'a,b,c,d');
select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd',2);
---fix this:
---select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_bin,_latin1'd',2);
---select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd' COLLATE latin1_bin,2);
+
+# fix this:
+--disable_parsing
+select SUBSTRING_INDEX(_latin1'abcdabcdabcd' COLLATE latin1_bin,_latin1'd',2);
+select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin1'd' COLLATE latin1_bin,2);
+--enable_parsing
+
--error 1267
select SUBSTRING_INDEX(_latin1'abcdabcdabcd',_latin2'd',2);
--error 1267
@@ -780,4 +788,208 @@ SELECT * FROM t1 INNER JOIN t2 ON code=id
DROP TABLE t1,t2;
+
+#
+# Bug #10963
+# 4294967296 18446744073709551616
+
+select locate('he','hello',-2);
+select locate('lo','hello',-4294967295);
+select locate('lo','hello',4294967295);
+select locate('lo','hello',-4294967296);
+select locate('lo','hello',4294967296);
+select locate('lo','hello',-4294967297);
+select locate('lo','hello',4294967297);
+select locate('lo','hello',-18446744073709551615);
+select locate('lo','hello',18446744073709551615);
+select locate('lo','hello',-18446744073709551616);
+select locate('lo','hello',18446744073709551616);
+select locate('lo','hello',-18446744073709551617);
+select locate('lo','hello',18446744073709551617);
+
+select left('hello', 10);
+select left('hello', 0);
+select left('hello', -1);
+select left('hello', -4294967295);
+select left('hello', 4294967295);
+select left('hello', -4294967296);
+select left('hello', 4294967296);
+select left('hello', -4294967297);
+select left('hello', 4294967297);
+select left('hello', -18446744073709551615);
+select left('hello', 18446744073709551615);
+select left('hello', -18446744073709551616);
+select left('hello', 18446744073709551616);
+select left('hello', -18446744073709551617);
+select left('hello', 18446744073709551617);
+
+select right('hello', 10);
+select right('hello', 0);
+select right('hello', -1);
+select right('hello', -4294967295);
+select right('hello', 4294967295);
+select right('hello', -4294967296);
+select right('hello', 4294967296);
+select right('hello', -4294967297);
+select right('hello', 4294967297);
+select right('hello', -18446744073709551615);
+select right('hello', 18446744073709551615);
+select right('hello', -18446744073709551616);
+select right('hello', 18446744073709551616);
+select right('hello', -18446744073709551617);
+select right('hello', 18446744073709551617);
+
+select substring('hello', 2, -1);
+
+select substring('hello', -1, 1);
+select substring('hello', -2, 1);
+select substring('hello', -4294967295, 1);
+select substring('hello', 4294967295, 1);
+select substring('hello', -4294967296, 1);
+select substring('hello', 4294967296, 1);
+select substring('hello', -4294967297, 1);
+select substring('hello', 4294967297, 1);
+select substring('hello', -18446744073709551615, 1);
+select substring('hello', 18446744073709551615, 1);
+select substring('hello', -18446744073709551616, 1);
+select substring('hello', 18446744073709551616, 1);
+select substring('hello', -18446744073709551617, 1);
+select substring('hello', 18446744073709551617, 1);
+select substring('hello', 1, -1);
+select substring('hello', 1, -4294967295);
+select substring('hello', 1, 4294967295);
+select substring('hello', 1, -4294967296);
+select substring('hello', 1, 4294967296);
+select substring('hello', 1, -4294967297);
+select substring('hello', 1, 4294967297);
+select substring('hello', 1, -18446744073709551615);
+select substring('hello', 1, 18446744073709551615);
+select substring('hello', 1, -18446744073709551616);
+select substring('hello', 1, 18446744073709551616);
+select substring('hello', 1, -18446744073709551617);
+select substring('hello', 1, 18446744073709551617);
+select substring('hello', -1, -1);
+select substring('hello', -4294967295, -4294967295);
+select substring('hello', 4294967295, 4294967295);
+select substring('hello', -4294967296, -4294967296);
+select substring('hello', 4294967296, 4294967296);
+select substring('hello', -4294967297, -4294967297);
+select substring('hello', 4294967297, 4294967297);
+select substring('hello', -18446744073709551615, -18446744073709551615);
+select substring('hello', 18446744073709551615, 18446744073709551615);
+select substring('hello', -18446744073709551616, -18446744073709551616);
+select substring('hello', 18446744073709551616, 18446744073709551616);
+select substring('hello', -18446744073709551617, -18446744073709551617);
+select substring('hello', 18446744073709551617, 18446744073709551617);
+
+select insert('hello', -1, 1, 'hi');
+select insert('hello', -4294967295, 1, 'hi');
+select insert('hello', 4294967295, 1, 'hi');
+select insert('hello', -4294967296, 1, 'hi');
+select insert('hello', 4294967296, 1, 'hi');
+select insert('hello', -4294967297, 1, 'hi');
+select insert('hello', 4294967297, 1, 'hi');
+select insert('hello', -18446744073709551615, 1, 'hi');
+select insert('hello', 18446744073709551615, 1, 'hi');
+select insert('hello', -18446744073709551616, 1, 'hi');
+select insert('hello', 18446744073709551616, 1, 'hi');
+select insert('hello', -18446744073709551617, 1, 'hi');
+select insert('hello', 18446744073709551617, 1, 'hi');
+select insert('hello', 1, -1, 'hi');
+select insert('hello', 1, -4294967295, 'hi');
+select insert('hello', 1, 4294967295, 'hi');
+select insert('hello', 1, -4294967296, 'hi');
+select insert('hello', 1, 4294967296, 'hi');
+select insert('hello', 1, -4294967297, 'hi');
+select insert('hello', 1, 4294967297, 'hi');
+select insert('hello', 1, -18446744073709551615, 'hi');
+select insert('hello', 1, 18446744073709551615, 'hi');
+select insert('hello', 1, -18446744073709551616, 'hi');
+select insert('hello', 1, 18446744073709551616, 'hi');
+select insert('hello', 1, -18446744073709551617, 'hi');
+select insert('hello', 1, 18446744073709551617, 'hi');
+select insert('hello', -1, -1, 'hi');
+select insert('hello', -4294967295, -4294967295, 'hi');
+select insert('hello', 4294967295, 4294967295, 'hi');
+select insert('hello', -4294967296, -4294967296, 'hi');
+select insert('hello', 4294967296, 4294967296, 'hi');
+select insert('hello', -4294967297, -4294967297, 'hi');
+select insert('hello', 4294967297, 4294967297, 'hi');
+select insert('hello', -18446744073709551615, -18446744073709551615, 'hi');
+select insert('hello', 18446744073709551615, 18446744073709551615, 'hi');
+select insert('hello', -18446744073709551616, -18446744073709551616, 'hi');
+select insert('hello', 18446744073709551616, 18446744073709551616, 'hi');
+select insert('hello', -18446744073709551617, -18446744073709551617, 'hi');
+select insert('hello', 18446744073709551617, 18446744073709551617, 'hi');
+
+select repeat('hello', -1);
+select repeat('hello', -4294967295);
+select repeat('hello', 4294967295);
+select repeat('hello', -4294967296);
+select repeat('hello', 4294967296);
+select repeat('hello', -4294967297);
+select repeat('hello', 4294967297);
+select repeat('hello', -18446744073709551615);
+select repeat('hello', 18446744073709551615);
+select repeat('hello', -18446744073709551616);
+select repeat('hello', 18446744073709551616);
+select repeat('hello', -18446744073709551617);
+select repeat('hello', 18446744073709551617);
+
+select space(-1);
+select space(-4294967295);
+select space(4294967295);
+select space(-4294967296);
+select space(4294967296);
+select space(-4294967297);
+select space(4294967297);
+select space(-18446744073709551615);
+select space(18446744073709551615);
+select space(-18446744073709551616);
+select space(18446744073709551616);
+select space(-18446744073709551617);
+select space(18446744073709551617);
+
+select rpad('hello', -1, '1');
+select rpad('hello', -4294967295, '1');
+select rpad('hello', 4294967295, '1');
+select rpad('hello', -4294967296, '1');
+select rpad('hello', 4294967296, '1');
+select rpad('hello', -4294967297, '1');
+select rpad('hello', 4294967297, '1');
+select rpad('hello', -18446744073709551615, '1');
+select rpad('hello', 18446744073709551615, '1');
+select rpad('hello', -18446744073709551616, '1');
+select rpad('hello', 18446744073709551616, '1');
+select rpad('hello', -18446744073709551617, '1');
+select rpad('hello', 18446744073709551617, '1');
+
+select lpad('hello', -1, '1');
+select lpad('hello', -4294967295, '1');
+select lpad('hello', 4294967295, '1');
+select lpad('hello', -4294967296, '1');
+select lpad('hello', 4294967296, '1');
+select lpad('hello', -4294967297, '1');
+select lpad('hello', 4294967297, '1');
+select lpad('hello', -18446744073709551615, '1');
+select lpad('hello', 18446744073709551615, '1');
+select lpad('hello', -18446744073709551616, '1');
+select lpad('hello', 18446744073709551616, '1');
+select lpad('hello', -18446744073709551617, '1');
+select lpad('hello', 18446744073709551617, '1');
+
+
+#
+# BUG#17047: CHAR() and IN() can return NULL without signaling NULL
+# result
+#
+SET @orig_sql_mode = @@SQL_MODE;
+SET SQL_MODE=traditional;
+
+SELECT CHAR(0xff,0x8f USING utf8);
+SELECT CHAR(0xff,0x8f USING utf8) IS NULL;
+
+SET SQL_MODE=@orig_sql_mode;
+
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test
index 0ea89cd0913..77bf3be5e72 100644
--- a/mysql-test/t/func_test.test
+++ b/mysql-test/t/func_test.test
@@ -108,6 +108,40 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
+#
+# Bug#23411: The "%" (MOD) operator is not documented; MOD-ing zero returns strange result
+# Manual: "Division by zero produces a NULL result"
+#
+select (12%0) <=> null as '1';
+select (12%0) is null as '1';
+select 12%0 as 'NULL';
+select 12%2 as '0';
+select 12%NULL as 'NULL';
+select 12 % null as 'NULL';
+select null % 12 as 'NULL';
+select null % 0 as 'NULL';
+select 0 % null as 'NULL';
+select null % null as 'NULL';
+
+select (12 mod 0) <=> null as '1';
+select (12 mod 0) is null as '1';
+select 12 mod 0 as 'NULL';
+select 12 mod 2 as '0';
+select 12 mod null as 'NULL';
+select null mod 12 as 'NULL';
+select null mod 0 as 'NULL';
+select 0 mod null as 'NULL';
+select null mod null as 'NULL';
+
+select mod(12.0, 0) as 'NULL';
+select mod(12, 0.0) as 'NULL';
+select mod(12, NULL) as 'NULL';
+select mod(12.0, NULL) as 'NULL';
+select mod(NULL, 2) as 'NULL';
+select mod(NULL, 2.0) as 'NULL';
+
+
+#
# Bug#6726: NOT BETWEEN parse failure
#
create table t1 (a int, b int);
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 2b3fb86829d..a3985998b13 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -255,17 +255,57 @@ select unix_timestamp(@a);
select unix_timestamp('1969-12-01 19:00:01');
#
-# Test for bug #6439 "unix_timestamp() function returns wrong datetime
-# values for too big argument" and bug #7515 "from_unixtime(0) now
-# returns NULL instead of the epoch". unix_timestamp() should return error
-# for too big or negative argument. It should return Epoch value for zero
-# argument since it seems that many user's rely on this fact.
+# Tests for bug #6439 "unix_timestamp() function returns wrong datetime
+# values for too big argument", bug #7515 "from_unixtime(0) now
+# returns NULL instead of the epoch" and bug #9191
+# "TIMESTAMP/from_unixtime() no longer accepts 2^31-1."
+# unix_timestamp() should return error for too big or negative argument.
+# It should return Epoch value for zero argument since it seems that many
+# users rely on this fact, from_unixtime() should work with values
+# up to INT_MAX32 because of the same reason.
#
select from_unixtime(-1);
-select from_unixtime(2145916800);
+# check for from_unixtime(2^31-1) and from_unixtime(2^31)
+select from_unixtime(2147483647);
+select from_unixtime(2147483648);
select from_unixtime(0);
#
+# Some more tests for bug #9191 "TIMESTAMP/from_unixtime() no
+# longer accepts 2^31-1". Here we test that from_unixtime and
+# unix_timestamp are consistent, when working with boundary dates.
+#
+select unix_timestamp(from_unixtime(2147483647));
+select unix_timestamp(from_unixtime(2147483648));
+
+# check for invalid dates
+
+# bad year
+select unix_timestamp('2039-01-20 01:00:00');
+select unix_timestamp('1968-01-20 01:00:00');
+# bad month
+select unix_timestamp('2038-02-10 01:00:00');
+select unix_timestamp('1969-11-20 01:00:00');
+# bad day
+select unix_timestamp('2038-01-20 01:00:00');
+select unix_timestamp('1969-12-30 01:00:00');
+
+#
+# Check negative shift (we subtract several days for boundary dates during
+# conversion).
+select unix_timestamp('2038-01-17 12:00:00');
+
+#
+# Check positive shift. (it happens only on
+# platfroms with unsigned time_t, such as QNX)
+#
+select unix_timestamp('1970-01-01 03:00:01');
+
+# check bad date, close to the boundary (we cut them off in the very end)
+select unix_timestamp('2038-01-19 07:14:07');
+
+
+#
# Test types from + INTERVAL
#
@@ -447,6 +487,47 @@ show create table t1;
drop table t1;
#
+# Bug #11655: Wrong time is returning from nested selects - maximum time exists
+#
+# check if SEC_TO_TIME() handles out-of-range values correctly
+SELECT SEC_TO_TIME(3300000);
+SELECT SEC_TO_TIME(3300000)+0;
+SELECT SEC_TO_TIME(3600 * 4294967296);
+
+# check if TIME_TO_SEC() handles out-of-range values correctly
+SELECT TIME_TO_SEC('916:40:00');
+
+# check if ADDTIME() handles out-of-range values correctly
+SELECT ADDTIME('500:00:00', '416:40:00');
+SELECT ADDTIME('916:40:00', '416:40:00');
+
+# check if SUBTIME() handles out-of-range values correctly
+SELECT SUBTIME('916:40:00', '416:40:00');
+SELECT SUBTIME('-916:40:00', '416:40:00');
+
+# check if MAKETIME() handles out-of-range values correctly
+SELECT MAKETIME(916,0,0);
+SELECT MAKETIME(4294967296, 0, 0);
+SELECT MAKETIME(-4294967296, 0, 0);
+SELECT MAKETIME(0, 4294967296, 0);
+SELECT MAKETIME(0, 0, 4294967296);
+SELECT MAKETIME(CAST(-1 AS UNSIGNED), 0, 0);
+
+# check if EXTRACT() handles out-of-range values correctly
+SELECT EXTRACT(HOUR FROM '100000:02:03');
+
+# check if we get proper warnings if both input string truncation
+# and out-of-range value occur
+CREATE TABLE t1(f1 TIME);
+INSERT INTO t1 VALUES('916:00:00 a');
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Bug #20927: sec_to_time treats big unsigned as signed
+#
+# check if SEC_TO_TIME() handles BIGINT UNSIGNED values correctly
+SELECT SEC_TO_TIME(CAST(-1 AS UNSIGNED));
# 21913: DATE_FORMAT() Crashes mysql server if I use it through
# mysql-connector-j driver.
#
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index 7bba34be3ff..95fdf642b94 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -375,6 +375,20 @@ drop table t1;
select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000))));
select (asWKT(geomfromwkb((0x010100000000000000000024400000000000002440))));
+--enable_metadata
+create table t1 (g GEOMETRY);
+select * from t1;
+select asbinary(g) from t1;
+--disable_metadata
+drop table t1;
+
+create table t1 (a TEXT, b GEOMETRY NOT NULL, SPATIAL KEY(b));
+alter table t1 disable keys;
+--error 1263
+load data infile '../std_data_ln/bad_gis_data.dat' into table t1;
+alter table t1 enable keys;
+drop table t1;
+
# End of 4.1 tests
#
@@ -410,15 +424,7 @@ alter table t1 add primary key pti(pt);
alter table t1 add primary key pti(pt(20));
drop table t1;
---enable_metadata
-create table t1 (g GEOMETRY);
-select * from t1;
-select asbinary(g) from t1;
---disable_metadata
-drop table t1;
-
create table t1 select GeomFromText('point(1 1)');
desc t1;
drop table t1;
-
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index d3781d58780..2f5e3dced22 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -118,7 +118,7 @@ drop table t1;
#
--error 1221
GRANT FILE on mysqltest.* to mysqltest_1@localhost;
-select 1; -- To test that the previous command didn't cause problems
+select 1; # To test that the previous command didn't cause problems
#
# Bug #4898: User privileges depending on ORDER BY Settings of table db
diff --git a/mysql-test/t/greedy_optimizer.test b/mysql-test/t/greedy_optimizer.test
index e547d85b7f3..049d0ab09f7 100644
--- a/mysql-test/t/greedy_optimizer.test
+++ b/mysql-test/t/greedy_optimizer.test
@@ -140,18 +140,18 @@ insert into t7 values (21,2,3,4,5,6);
select @@optimizer_search_depth;
select @@optimizer_prune_level;
--- This value swithes back to the old implementation of 'find_best()'
--- set optimizer_search_depth=63; - old (independent of the optimizer_prune_level)
---
--- These are the values for the parameters that control the greedy optimizer
--- (total 6 combinations - 3 for optimizer_search_depth, 2 for optimizer_prune_level):
+# This value swithes back to the old implementation of 'find_best()'
+# set optimizer_search_depth=63; - old (independent of the optimizer_prune_level)
+#
+# These are the values for the parameters that control the greedy optimizer
+# (total 6 combinations - 3 for optimizer_search_depth, 2 for optimizer_prune_level):
--
--- set optimizer_search_depth=0; - automatic
--- set optimizer_search_depth=1; - min
--- set optimizer_search_depth=62; - max (default)
+# set optimizer_search_depth=0; - automatic
+# set optimizer_search_depth=1; - min
+# set optimizer_search_depth=62; - max (default)
--
--- set optimizer_prune_level=0 - exhaustive;
--- set optimizer_prune_level=1 - heuristic; -- default
+# set optimizer_prune_level=0 - exhaustive;
+# set optimizer_prune_level=1 - heuristic; # default
#
@@ -170,17 +170,17 @@ select @@optimizer_prune_level;
set optimizer_search_depth=63;
select @@optimizer_search_depth;
--- 6-table join, chain
+# 6-table join, chain
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, star
+# 6-table join, star
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, clique
+# 6-table join, clique
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
@@ -195,17 +195,17 @@ select @@optimizer_prune_level;
set optimizer_search_depth=0;
select @@optimizer_search_depth;
--- 6-table join, chain
+# 6-table join, chain
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, star
+# 6-table join, star
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, clique
+# 6-table join, clique
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
@@ -214,17 +214,17 @@ show status like 'Last_query_cost';
set optimizer_search_depth=1;
select @@optimizer_search_depth;
--- 6-table join, chain
+# 6-table join, chain
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, star
+# 6-table join, star
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, clique
+# 6-table join, clique
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
@@ -233,17 +233,17 @@ show status like 'Last_query_cost';
set optimizer_search_depth=62;
select @@optimizer_search_depth;
--- 6-table join, chain
+# 6-table join, chain
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, star
+# 6-table join, star
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, clique
+# 6-table join, clique
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
@@ -256,17 +256,17 @@ select @@optimizer_prune_level;
set optimizer_search_depth=0;
select @@optimizer_search_depth;
--- 6-table join, chain
+# 6-table join, chain
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, star
+# 6-table join, star
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, clique
+# 6-table join, clique
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
@@ -275,17 +275,17 @@ show status like 'Last_query_cost';
set optimizer_search_depth=1;
select @@optimizer_search_depth;
--- 6-table join, chain
+# 6-table join, chain
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, star
+# 6-table join, star
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, clique
+# 6-table join, clique
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
@@ -294,17 +294,17 @@ show status like 'Last_query_cost';
set optimizer_search_depth=62;
select @@optimizer_search_depth;
--- 6-table join, chain
+# 6-table join, chain
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, star
+# 6-table join, star
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71;
show status like 'Last_query_cost';
--- 6-table join, clique
+# 6-table join, clique
explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
show status like 'Last_query_cost';
explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76;
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index 08f0f54df60..b3049498f90 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -57,8 +57,8 @@ create index idx_t1_1 on t1 (a1,a2,b,c);
create index idx_t1_2 on t1 (a1,a2,b);
analyze table t1;
--- t2 is the same as t1, but with some NULLs in the MIN/MAX column, and one more
--- nullable attribute
+# t2 is the same as t1, but with some NULLs in the MIN/MAX column, and
+# one more nullable attribute
--disable_warnings
drop table if exists t2;
@@ -68,7 +68,7 @@ create table t2 (
a1 char(64), a2 char(64) not null, b char(16), c char(16), d char(16), dummy char(64) default ' '
);
insert into t2 select * from t1;
--- add few rows with NULL's in the MIN/MAX column
+# add few rows with NULL's in the MIN/MAX column
insert into t2 (a1, a2, b, c, d) values
('a','a',NULL,'a777','xyz'),('a','a',NULL,'a888','xyz'),('a','a',NULL,'a999','xyz'),
('a','a','a',NULL,'xyz'),
@@ -92,10 +92,10 @@ create index idx_t2_1 on t2 (a1,a2,b,c);
create index idx_t2_2 on t2 (a1,a2,b);
analyze table t2;
--- Table t3 is the same as t1, but with smaller column lenghts.
--- This allows to test different branches of the cost computation procedure
--- when the number of keys per block are less than the number of keys in the
--- sub-groups formed by predicates over non-group attributes.
+# Table t3 is the same as t1, but with smaller column lenghts.
+# This allows to test different branches of the cost computation procedure
+# when the number of keys per block are less than the number of keys in the
+# sub-groups formed by predicates over non-group attributes.
--disable_warnings
drop table if exists t3;
@@ -164,11 +164,11 @@ create index idx_t3_2 on t3 (a1,a2,b);
analyze table t3;
---
--- Queries without a WHERE clause. These queries do not use ranges.
---
+#
+# Queries without a WHERE clause. These queries do not use ranges.
+#
--- plans
+# plans
explain select a1, min(a2) from t1 group by a1;
explain select a1, max(a2) from t1 group by a1;
explain select a1, min(a2), max(a2) from t1 group by a1;
@@ -176,31 +176,31 @@ explain select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b;
explain select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b;
--replace_column 7 # 9 #
explain select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b;
--- Select fields in different order
+# Select fields in different order
explain select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1;
explain select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b;
explain select min(a2) from t1 group by a1;
explain select a2, min(c), max(c) from t1 group by a1,a2,b;
--- queries
+# queries
select a1, min(a2) from t1 group by a1;
select a1, max(a2) from t1 group by a1;
select a1, min(a2), max(a2) from t1 group by a1;
select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b;
select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b;
select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b;
--- Select fields in different order
+# Select fields in different order
select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1;
select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b;
select min(a2) from t1 group by a1;
select a2, min(c), max(c) from t1 group by a1,a2,b;
---
--- Queries with a where clause
---
+#
+# Queries with a where clause
+#
--- A) Preds only over the group 'A' attributes
--- plans
+# A) Preds only over the group 'A' attributes
+# plans
explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
@@ -238,7 +238,7 @@ explain select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
--replace_column 9 #
explain select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
--- queries
+# queries
select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
@@ -264,8 +264,8 @@ select a1,a2,b,min(c),max(c) from t2 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or
select a1,min(c),max(c) from t2 where a1 >= 'b' group by a1,a2,b;
select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
--- B) Equalities only over the non-group 'B' attributes
--- plans
+# B) Equalities only over the non-group 'B' attributes
+# plans
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
explain select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
explain select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2;
@@ -278,11 +278,11 @@ explain select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2;
explain select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
explain select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
--- these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost()
+# these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost()
explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
explain select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
--- queries
+# queries
select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2;
@@ -295,20 +295,20 @@ select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2;
select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
--- these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost()
+# these queries test case 2) in TRP_GROUP_MIN_MAX::update_cost()
select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
--- IS NULL (makes sense for t2 only)
--- plans
+# IS NULL (makes sense for t2 only)
+# plans
explain select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
explain select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
explain select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
explain select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2;
explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
--- queries
+# queries
select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
@@ -316,8 +316,8 @@ select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2;
select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
--- C) Range predicates for the MIN/MAX attribute
--- plans
+# C) Range predicates for the MIN/MAX attribute
+# plans
--replace_column 9 #
explain select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b;
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b;
@@ -367,7 +367,7 @@ explain select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or
--replace_column 9 #
explain select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
--- queries
+# queries
select a1,a2,b, max(c) from t1 where (c > 'b1') group by a1,a2,b;
select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b;
select a1,a2,b, max(c) from t1 where (c > 'f123') group by a1,a2,b;
@@ -401,19 +401,19 @@ select a1,a2,b,min(c),max(c) from t2 where (c > 'b111') and (c <= 'g112') group
select a1,a2,b,min(c),max(c) from t2 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
select a1,a2,b,min(c),max(c) from t2 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
--- analyze the sub-select
+# analyze the sub-select
explain select a1,a2,b,min(c),max(c) from t1
where exists ( select * from t2 where t2.c = t1.c )
group by a1,a2,b;
--- the sub-select is unrelated to MIN/MAX
+# the sub-select is unrelated to MIN/MAX
explain select a1,a2,b,min(c),max(c) from t1
where exists ( select * from t2 where t2.c > 'b1' )
group by a1,a2,b;
--- A,B,C) Predicates referencing mixed classes of attributes
--- plans
+# A,B,C) Predicates referencing mixed classes of attributes
+# plans
explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
explain select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
@@ -435,7 +435,7 @@ explain select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2
--replace_column 9 #
explain select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
--- queries
+# queries
select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
@@ -452,11 +452,11 @@ select a1,a2,b,min(c) from t2 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b')
select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
---
--- GROUP BY queries without MIN/MAX
---
+#
+# GROUP BY queries without MIN/MAX
+#
--- plans
+# plans
explain select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
explain select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
explain select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
@@ -471,7 +471,7 @@ explain select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121'
--replace_column 9 #
explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
--- queries
+# queries
select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
@@ -482,11 +482,11 @@ select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
---
--- DISTINCT queries
---
+#
+# DISTINCT queries
+#
--- plans
+# plans
explain select distinct a1,a2,b from t1;
explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a');
explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
@@ -502,7 +502,7 @@ explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c
explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
explain select distinct b from t2 where (a2 >= 'b') and (b = 'a');
--- queries
+# queries
select distinct a1,a2,b from t1;
select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a');
select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
@@ -515,22 +515,22 @@ select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121
select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
select distinct b from t2 where (a2 >= 'b') and (b = 'a');
--- BUG #6303
+# BUG #6303
select distinct t_00.a1
from t1 t_00
where exists ( select * from t2 where a1 = t_00.a1 );
--- BUG #8532 - SELECT DISTINCT a, a causes server to crash
+# BUG #8532 - SELECT DISTINCT a, a causes server to crash
select distinct a1,a1 from t1;
select distinct a2,a1,a2,a1 from t1;
select distinct t1.a1,t2.a1 from t1,t2;
---
--- DISTINCT queries with GROUP-BY
---
+#
+# DISTINCT queries with GROUP-BY
+#
--- plans
+# plans
explain select distinct a1,a2,b from t1;
explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
@@ -548,7 +548,7 @@ explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b =
--replace_column 9 #
explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
--- queries
+# queries
select distinct a1,a2,b from t1;
select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
@@ -562,9 +562,9 @@ select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') gr
select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
---
--- COUNT (DISTINCT cols) queries
---
+#
+# COUNT (DISTINCT cols) queries
+#
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');
@@ -578,9 +578,9 @@ select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b =
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');
---
--- Queries with expressions in the select clause
---
+#
+# Queries with expressions in the select clause
+#
explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
@@ -595,48 +595,48 @@ select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
---
--- Negative examples: queries that should NOT be treated as optimizable by
--- QUICK_GROUP_MIN_MAX_SELECT
---
+#
+# Negative examples: queries that should NOT be treated as optimizable by
+# QUICK_GROUP_MIN_MAX_SELECT
+#
--- select a non-indexed attribute
+# select a non-indexed attribute
explain select a1,a2,b,d,min(c),max(c) from t1 group by a1,a2,b;
explain select a1,a2,b,d from t1 group by a1,a2,b;
--- predicate that references an attribute that is after the MIN/MAX argument
--- in the index
+# predicate that references an attribute that is after the MIN/MAX argument
+# in the index
explain select a1,a2,min(b),max(b) from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2;
--- predicate that references a non-indexed attribute
+# predicate that references a non-indexed attribute
explain select a1,a2,b,min(c),max(c) from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b;
explain select a1,a2,b,c from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c;
--- non-equality predicate for a non-group select attribute
+# non-equality predicate for a non-group select attribute
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1;
explain select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b;
--- non-group field with an equality predicate that references a keypart after the
--- MIN/MAX argument
+# non-group field with an equality predicate that references a keypart after the
+# MIN/MAX argument
explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
--- disjunction for a non-group select attribute
+# disjunction for a non-group select attribute
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b = 'a') group by a1;
--- non-range predicate for the MIN/MAX attribute
+# non-range predicate for the MIN/MAX attribute
explain select a1,a2,b,min(c),max(c) from t2
where (c > 'a000') and (c <= 'd999') and (c like '_8__') group by a1,a2,b;
--- not all attributes are indexed by one index
+# not all attributes are indexed by one index
explain select a1, a2, b, c, min(d), max(d) from t1 group by a1,a2,b,c;
--- other aggregate functions than MIN/MAX
+# other aggregate functions than MIN/MAX
explain select a1,a2,count(a2) from t1 group by a1,a2,b;
explain select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
@@ -765,24 +765,24 @@ INSERT INTO t4 VALUES(1);
INSERT INTO t5 VALUES(1,1);
INSERT INTO t6 VALUES(1);
--- original bug query
+# original bug query
SELECT * FROM
t1
NATURAL JOIN
(t2 JOIN (t3 NATURAL JOIN t4, t5 NATURAL JOIN t6)
ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5));
--- inner join swapped
+# inner join swapped
SELECT * FROM
t1
NATURAL JOIN
(((t3 NATURAL JOIN t4) join (t5 NATURAL JOIN t6) on t3.id4 = t5.id5) JOIN t2
ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5));
--- one join less, no ON cond
+# one join less, no ON cond
SELECT * FROM t1 NATURAL JOIN ((t3 join (t5 NATURAL JOIN t6)) JOIN t2);
--- wrong error message: 'id2' - ambiguous column
+# wrong error message: 'id2' - ambiguous column
SELECT * FROM
(t2 JOIN (t3 NATURAL JOIN t4, t5 NATURAL JOIN t6)
ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5))
@@ -810,3 +810,63 @@ explain SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
DROP TABLE t1,t2;
+
+#
+# Bug#24156: Loose index scan not used with CREATE TABLE ...SELECT and similar statements
+#
+
+CREATE TABLE t1 (a INT, b INT, INDEX (a,b));
+INSERT INTO t1 (a, b) VALUES (1,1), (1,2), (1,3), (1,4), (1,5),
+ (2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6);
+EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
+FLUSH STATUS;
+SELECT max(b), a FROM t1 GROUP BY a;
+SHOW STATUS LIKE 'handler_read__e%';
+EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
+FLUSH STATUS;
+CREATE TABLE t2 SELECT max(b), a FROM t1 GROUP BY a;
+SHOW STATUS LIKE 'handler_read__e%';
+FLUSH STATUS;
+SELECT * FROM (SELECT max(b), a FROM t1 GROUP BY a) b;
+SHOW STATUS LIKE 'handler_read__e%';
+FLUSH STATUS;
+(SELECT max(b), a FROM t1 GROUP BY a) UNION
+ (SELECT max(b), a FROM t1 GROUP BY a);
+SHOW STATUS LIKE 'handler_read__e%';
+EXPLAIN (SELECT max(b), a FROM t1 GROUP BY a) UNION
+ (SELECT max(b), a FROM t1 GROUP BY a);
+
+EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
+ FROM t1 AS t1_outer;
+EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS
+ (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
+EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
+ (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
+EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
+ a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
+EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
+ a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
+EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2
+ ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2)
+ AND t1_outer1.b = t1_outer2.b;
+EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
+ FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2;
+
+CREATE TABLE t3 LIKE t1;
+FLUSH STATUS;
+INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a;
+SHOW STATUS LIKE 'handler_read__e%';
+DELETE FROM t3;
+FLUSH STATUS;
+INSERT INTO t3 SELECT 1, (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2)
+ FROM t1 LIMIT 1;
+SHOW STATUS LIKE 'handler_read__e%';
+FLUSH STATUS;
+DELETE FROM t3 WHERE (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) > 10000;
+SHOW STATUS LIKE 'handler_read__e%';
+FLUSH STATUS;
+DELETE FROM t3 WHERE (SELECT (SELECT MAX(b) FROM t1 GROUP BY a HAVING a < 2) x
+ FROM t1) > 10000;
+SHOW STATUS LIKE 'handler_read__e%';
+
+DROP TABLE t1,t2,t3;
diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest
index acd1f0d887b..acd615809f3 100644
--- a/mysql-test/t/im_daemon_life_cycle.imtest
+++ b/mysql-test/t/im_daemon_life_cycle.imtest
@@ -6,47 +6,73 @@
#
###########################################################################
---source include/im_check_env.inc
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle im_daemon_life_cycle.imtest started.
###########################################################################
-# Kill the IM main process and check that the IM Angel will restart the main
-# process.
+--source include/im_check_env.inc
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30
+# 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;
+#
+###########################################################################
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Main-test: starting...
+
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Killing IM-main...
+--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 im_daemon_life_cycle
+
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Waiting for IM-main to start accepting connections...
+--exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 im_daemon_life_cycle
+
+--exec $MYSQL_TEST_DIR/t/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 --------------------------------------------------------------------
-# Give some time to begin accepting connections after restart.
-# FIXME: race condition here.
-
---sleep 3
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle BUG12751: starting...
# 1. Start mysqld;
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: starting...
START INSTANCE mysqld2;
-# FIXME: START INSTANCE should be synchronous.
---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
-# 2. Restart IM-main: kill it and IM-angel will restart it.
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: waiting to start...
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_daemon_life_cycle
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: started.
-# 3. Issue some statement -- connection should be re-established.
+# 2. Restart IM-main;
+
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Killing IM-main...
+--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 im_daemon_life_cycle
+
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Waiting for IM-main to start accepting connections...
+--exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 im_daemon_life_cycle
-# Give some time to begin accepting connections after restart.
-# FIXME: race condition here.
+# 3. Issue some statement -- connection should be re-established.
---sleep 3
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Checking that IM-main processing commands...
--replace_column 3 VERSION
SHOW INSTANCE STATUS mysqld1;
@@ -55,6 +81,13 @@ SHOW INSTANCE STATUS mysqld1;
# So, if it we do not stop it, it will be stopped by mysql-test-run.pl with
# warning.
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: stopping...
STOP INSTANCE mysqld2;
-# FIXME: STOP INSTANCE should be synchronous.
---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped
+
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: waiting to stop...
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped im_daemon_life_cycle
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: stopped.
+
+###########################################################################
+
+--exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle BUG12751: done.
diff --git a/mysql-test/t/im_life_cycle.imtest b/mysql-test/t/im_life_cycle.imtest
index ddfb62d312e..3721b92e2b7 100644
--- a/mysql-test/t/im_life_cycle.imtest
+++ b/mysql-test/t/im_life_cycle.imtest
@@ -25,7 +25,7 @@
START INSTANCE mysqld2;
# FIXME: START INSTANCE should be synchronous.
---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
+--exec $MYSQL_TEST_DIR/t/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
@@ -58,7 +58,7 @@ SHOW VARIABLES LIKE 'port';
STOP INSTANCE mysqld2;
# FIXME: STOP INSTANCE should be synchronous.
---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped
+--exec $MYSQL_TEST_DIR/t/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
@@ -121,7 +121,7 @@ STOP INSTANCE mysqld3;
--echo -- 1.1.6.
--echo --------------------------------------------------------------------
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD1_PATH_PID restarted 30
+--exec $MYSQL_TEST_DIR/t/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.
@@ -143,7 +143,7 @@ SHOW INSTANCES;
START INSTANCE mysqld2;
# FIXME: START INSTANCE should be synchronous.
---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
+--exec $MYSQL_TEST_DIR/t/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
@@ -151,7 +151,7 @@ START INSTANCE mysqld2;
# mysqld has started.
# SHOW INSTANCES;
---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_MYSQLD2_PATH_PID killed 10
+--exec $MYSQL_TEST_DIR/t/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
diff --git a/mysql-test/t/im_utils.imtest b/mysql-test/t/im_utils.imtest
index 52878f6c2b5..0866b87204a 100644
--- a/mysql-test/t/im_utils.imtest
+++ b/mysql-test/t/im_utils.imtest
@@ -31,10 +31,10 @@ SHOW INSTANCE OPTIONS mysqld2;
#
START INSTANCE mysqld2;
---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_utils
STOP INSTANCE mysqld2;
---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped
+--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped im_utils
#
# Check 'SHOW LOG FILES' command:
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index 9e5dac8b853..dd203add344 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -930,4 +930,61 @@ SELECT table_name from information_schema.tables
WHERE table_name=(SELECT MAX(table_name)
FROM information_schema.tables);
+#
+# Bug #23037: Bug in field "Default" of query "SHOW COLUMNS FROM table"
+#
+# Note, MyISAM/InnoDB can't take more that 65532 chars, because the row
+# size is limited to 65535 bytes (BLOBs not counted)
+#
+--disable_warnings
+DROP TABLE IF EXISTS bug23037;
+DROP FUNCTION IF EXISTS get_value;
+--enable_warnings
+--disable_query_log
+DELIMITER |;
+CREATE FUNCTION get_value()
+ RETURNS TEXT
+ DETERMINISTIC
+BEGIN
+ DECLARE col1, col2, col3, col4, col6 CHAR(255);
+ DECLARE default_val VARCHAR(65532);
+ DECLARE done INT DEFAULT 0;
+ DECLARE cur1 CURSOR FOR SHOW COLUMNS FROM bug23037;
+ DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
+ OPEN cur1;
+ FETCH cur1 INTO col1, col2, col3, col4, default_val, col6;
+ CLOSE cur1;
+ RETURN default_val;
+end|
+DELIMITER ;|
+
+let $body=`SELECT REPEAT('A', 65532)`;
+eval CREATE TABLE bug23037(fld1 VARCHAR(65532) CHARACTER SET latin1 DEFAULT "$body");
+--enable_query_log
+
+SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='bug23037';
+
+SELECT MD5(get_value());
+
+SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT), COLUMN_DEFAULT=get_value() FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='bug23037';
+
+DROP TABLE bug23037;
+DROP FUNCTION get_value;
+
+
+
+
+#
+# Bug#22413: EXPLAIN SELECT FROM view with ORDER BY yield server crash
+#
+create view v1 as
+select table_schema as object_schema,
+ table_name as object_name,
+ table_type as object_type
+from information_schema.tables
+order by object_schema;
+explain select * from v1;
+explain select * from (select table_name from information_schema.tables) as a;
+drop view v1;
+
# End of 5.0 tests.
diff --git a/mysql-test/t/init_file.test b/mysql-test/t/init_file.test
index 6b5e032fd99..31a6ef5a541 100644
--- a/mysql-test/t/init_file.test
+++ b/mysql-test/t/init_file.test
@@ -4,7 +4,7 @@
#
# See mysql-test/std_data/init_file.dat and
# mysql-test/t/init_file-master.opt for the actual test
-#
+#
--echo ok
--echo end of 4.1 tests
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 561d47253d2..20f07ccdde0 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1482,7 +1482,7 @@ INSERT INTO t1 (id) VALUES (NULL);
SELECT * FROM t1;
DROP TABLE t2, t1;
--- Test that foreign keys in temporary tables are not accepted (bug #12084)
+# Test that foreign keys in temporary tables are not accepted (bug #12084)
CREATE TABLE t1
(
id INT PRIMARY KEY
diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test
index 4d87e9dfb02..06cfe71ef11 100644
--- a/mysql-test/t/innodb_mysql.test
+++ b/mysql-test/t/innodb_mysql.test
@@ -117,6 +117,29 @@ INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES
SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND `id3` = 2);
DROP TABLE t1, t2;
+
+#
+# Bug #22728 - Handler_rollback value is growing
+#
+
+let $before= `show /*!50002 GLOBAL */ status like 'Handler_rollback'`;
+create table t1 (c1 int) engine=innodb;
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+connection con2;
+handler t1 open;
+handler t1 read first;
+disconnect con2;
+connection con1;
+let $after= `show /*!50002 GLOBAL */ status like 'Handler_rollback'`;
+# Compare the before and after value, it should be equal
+--disable_query_log
+eval select STRCMP("$before", "$after") as "Before and after comparison";
+--enable_query_log
+connection default;
+drop table t1;
+disconnect con1;
+--echo End of 4.1 tests
#
# Bug #12882 min/max inconsistent on empty table
#
@@ -246,6 +269,36 @@ select distinct a1 from t4 where pk_col not in (1,2,3,4);
drop table t1,t4;
+
+#
+# BUG#18819: DELETE IGNORE hangs on foreign key parent delete
+#
+# The bug itself does not relate to InnoDB, but we have to use foreign
+# keys to reproduce it.
+#
+--disable_warnings
+DROP TABLE IF EXISTS t2, t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE= InnoDB;
+CREATE TABLE t2 (
+ i INT NOT NULL,
+ FOREIGN KEY (i) REFERENCES t1 (i) ON DELETE NO ACTION
+) ENGINE= InnoDB;
+
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (1);
+
+DELETE IGNORE FROM t1 WHERE i = 1;
+
+SELECT * FROM t1, t2;
+
+DROP TABLE t2, t1;
+
+
+--echo End of 4.1 tests.
+
+
#
# Bug #6142: a problem with the empty innodb table
# (was part of group_min_max.test)
@@ -304,6 +357,15 @@ SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id
DROP TABLE t1,t2;
#
+# Bug#17530: Incorrect key truncation on table creation caused server crash.
+#
+create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb
+ character set utf8 collate utf8_general_ci;
+insert into t1 values('aaa');
+drop table t1;
+
+
+#
# Bug#22781: SQL_BIG_RESULT fails to influence sort plan
#
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c FLOAT, KEY b(b)) ENGINE = INNODB;
@@ -320,3 +382,6 @@ INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20), 1 FROM t1;
EXPLAIN SELECT b, SUM(c) FROM t1 GROUP BY b;
EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b;
DROP TABLE t1;
+
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index f6804ed3db5..ab85cc5bed2 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -362,38 +362,38 @@ insert into t4 values (2, 3);
insert into t5 values (11,4);
insert into t6 values (2, 3);
--- Views with simple natural join.
+# Views with simple natural join.
create algorithm=merge view v1a as
select * from t1 natural join t2;
--- as above, but column names are cross-renamed: a->c, c->b, b->a
+# as above, but column names are cross-renamed: a->c, c->b, b->a
create algorithm=merge view v1b(a,b,c) as
select * from t1 natural join t2;
--- as above, but column names are aliased: a->c, c->b, b->a
+# as above, but column names are aliased: a->c, c->b, b->a
create algorithm=merge view v1c as
select b as a, c as b, a as c from t1 natural join t2;
--- as above, but column names are cross-renamed, and aliased
--- a->c->b, c->b->a, b->a->c
+# as above, but column names are cross-renamed, and aliased
+# a->c->b, c->b->a, b->a->c
create algorithm=merge view v1d(b, a, c) as
select a as c, c as b, b as a from t1 natural join t2;
--- Views with JOIN ... ON
+# Views with JOIN ... ON
create algorithm=merge view v2a as
select t1.c, t1.b, t2.a from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c;
create algorithm=merge view v2b as
select t1.c as b, t1.b as a, t2.a as c
from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c;
--- Views with bigger natural join
+# Views with bigger natural join
create algorithm=merge view v3a as
select * from t1 natural join t2 natural join t3;
create algorithm=merge view v3b as
select * from t1 natural join (t2 natural join t3);
--- View over views with mixed natural join and join ... on
+# View over views with mixed natural join and join ... on
create algorithm=merge view v4 as
select * from v2a natural join v3a;
--- Nested natural/using joins.
+# Nested natural/using joins.
select * from (t1 natural join t2) natural join (t3 natural join t4);
select * from (t1 natural join t2) natural left join (t3 natural join t4);
select * from (t3 natural join t4) natural right join (t1 natural join t2);
@@ -402,12 +402,12 @@ select * from (t4 natural right join t3) natural right join (t2 natural right jo
select * from t1 natural join t2 natural join t3 natural join t4;
select * from ((t1 natural join t2) natural join t3) natural join t4;
select * from t1 natural join (t2 natural join (t3 natural join t4));
--- BUG#15355: this query fails in 'prepared statements' mode
--- select * from ((t3 natural join (t1 natural join t2)) natural join t4) natural join t5;
--- select * from ((t3 natural left join (t1 natural left join t2)) natural left join t4) natural left join t5;
+# BUG#15355: this query fails in 'prepared statements' mode
+# select * from ((t3 natural join (t1 natural join t2)) natural join t4) natural join t5;
+# select * from ((t3 natural left join (t1 natural left join t2)) natural left join t4) natural left join t5;
select * from t5 natural right join (t4 natural right join ((t2 natural right join t1) natural right join t3));
select * from (t1 natural join t2), (t3 natural join t4);
--- MySQL extension - nested comma ',' operator instead of cross join.
+# MySQL extension - nested comma ',' operator instead of cross join.
select * from t5 natural join ((t1 natural join t2), (t3 natural join t4));
select * from ((t1 natural join t2), (t3 natural join t4)) natural join t5;
select * from t5 natural join ((t1 natural join t2) cross join (t3 natural join t4));
@@ -417,7 +417,7 @@ select * from (t1 join t2 using (b)) join (t3 join t4 using (c)) using (c);
select * from (t1 join t2 using (b)) natural join (t3 join t4 using (c));
--- Other clauses refer to NJ columns.
+# Other clauses refer to NJ columns.
select a,b,c from (t1 natural join t2) natural join (t3 natural join t4)
where b + 1 = y or b + 10 = y group by b,c,a having min(b) < max(y) order by a;
select * from (t1 natural join t2) natural left join (t3 natural join t4)
@@ -425,23 +425,23 @@ where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a
select * from (t3 natural join t4) natural right join (t1 natural join t2)
where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y;
--- Qualified column references to NJ columns.
+# Qualified column references to NJ columns.
select * from t1 natural join t2 where t1.c > t2.a;
select * from t1 natural join t2 where t1.b > t2.b;
select * from t1 natural left join (t4 natural join t5) where t5.z is not NULL;
--- Nested 'join ... on' - name resolution of ON conditions
+# Nested 'join ... on' - name resolution of ON conditions
select * from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c;
select * from (t2 join t4 on b + 1 = y) join t1 on t1.c = t4.c;
select * from t1 natural join (t2 join t4 on b + 1 = y);
select * from (t1 cross join t2) join (t3 cross join t4) on (a < y and t2.b < t3.c);
--- MySQL extension - 'join ... on' over nested comma operator
+# MySQL extension - 'join ... on' over nested comma operator
select * from (t1, t2) join (t3, t4) on (a < y and t2.b < t3.c);
select * from (t1 natural join t2) join (t3 natural join t4) on a = y;
select * from ((t3 join (t1 join t2 on c > a) on t3.b < t2.a) join t4 on y > t1.c) join t5 on z = t1.b + 3;
--- MySQL extension - refererence qualified coalesced columns
+# MySQL extension - refererence qualified coalesced columns
select * from t1 natural join t2 where t1.b > 0;
select * from t1 natural join (t4 natural join t5) where t4.y > 7;
select * from (t4 natural join t5) natural join t1 where t4.y > 7;
@@ -449,11 +449,11 @@ select * from t1 natural left join (t4 natural join t5) where t4.y > 7;
select * from (t4 natural join t5) natural right join t1 where t4.y > 7;
select * from (t1 natural join t2) join (t3 natural join t4) on t1.b = t3.b;
--- MySQL extension - select qualified columns of NJ columns
+# MySQL extension - select qualified columns of NJ columns
select t1.*, t2.* from t1 natural join t2;
select t1.*, t2.*, t3.*, t4.* from (t1 natural join t2) natural join (t3 natural join t4);
--- Queries over subselects in the FROM clause
+# Queries over subselects in the FROM clause
select * from (select * from t1 natural join t2) as t12
natural join
(select * from t3 natural join t4) as t34;
@@ -464,7 +464,7 @@ select * from (select * from t3 natural join t4) as t34
natural right join
(select * from t1 natural join t2) as t12;
--- Queries over views
+# Queries over views
select * from v1a;
select * from v1b;
select * from v1c;
@@ -481,13 +481,13 @@ select * from v1c join v2a on v1c.b = v2a.c;
select * from v1d join v2a on v1d.a = v2a.c;
select * from v1a join (t3 natural join t4) on a = y;
--- TODO: add tests with correlated subqueries for natural join/join on.
--- related to BUG#15269
+# TODO: add tests with correlated subqueries for natural join/join on.
+# related to BUG#15269
-----------------------------------------------------------------------
--- Negative tests (tests for errors)
-----------------------------------------------------------------------
+#--------------------------------------------------------------------
+# Negative tests (tests for errors)
+#--------------------------------------------------------------------
-- error 1052
select * from t1 natural join (t3 cross join t4); -- works in Oracle - bug
-- error 1052
@@ -504,7 +504,7 @@ select * from t6 natural join ((t1 natural join t2), (t3 natural join t4));
select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4);
-- error 1052
select * from (t3 natural join t4) natural join (t1 join t2 on t1.b=t2.b);
--- this one is OK, the next equivalent one is incorrect (bug in Oracle)
+# this one is OK, the next equivalent one is incorrect (bug in Oracle)
-- error 1052
select * from (t3 join (t4 natural join t5) on (b < z))
natural join
@@ -580,12 +580,12 @@ insert into t3 values (2,3);
insert into t4 values (1,3);
insert into t5 values (1,4);
--- this fails
+# this fails
prepare stmt1 from "select * from ((t3 natural join (t1 natural join t2))
natural join t4) natural join t5";
execute stmt1;
--- this works
+# this works
select * from ((t3 natural join (t1 natural join t2)) natural join t4)
natural join t5;
drop table t1, t2, t3, t4, t5;
diff --git a/mysql-test/t/kill_n_check.sh b/mysql-test/t/kill_n_check.sh
index a54fb6ef8bb..96c402a638c 100755
--- a/mysql-test/t/kill_n_check.sh
+++ b/mysql-test/t/kill_n_check.sh
@@ -2,74 +2,101 @@
###########################################################################
-# NOTE: this script returns 0 (success) even in case of failure. 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.
+# 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=$?
- if [ $? -eq 0 -a "$original_pid" = "$new_pid" ]; then
+ 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 3 ]; then
- echo "Usage: kill_n_check.sh <pid file path> killed|restarted <timeout>"
- exit 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.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
- echo "Error: invalid second argument ('killed' or 'restarted' expected)."
- exit 0
+ log_error "Invalid second argument ($expected_result): 'killed' or 'restarted' expected."
+ quit 0
fi
if [ -z "$pid_path" ]; then
- echo "Error: invalid PID path ($pid_path)."
- exit 0
+ log_error "Invalid PID path ($pid_path)."
+ quit 0
fi
if [ ! -r "$pid_path" ]; then
- echo "Error: PID file ($pid_path) does not exist."
- exit 0
+ log_error "PID file ($pid_path) does not exist."
+ quit 0
fi
if [ -z "$total_timeout" ]; then
- echo "Error: timeout is not specified."
- exit 0
+ log_error "Timeout is not specified."
+ quit 0
fi
###########################################################################
original_pid=`cat "$pid_path"`
+log_debug "original_pid: $original_pid."
-echo "Killing the process..."
+log_info "Killing the process..."
kill -9 $original_pid
###########################################################################
-echo "Sleeping..."
+log_info "Waiting..."
if [ "$expected_result" = "restarted" ]; then
@@ -79,37 +106,42 @@ if [ "$expected_result" = "restarted" ]; then
while true; do
+ log_debug "cur_attempt: $cur_attempt."
+
if check_restart; then
- echo "Success: $user_msg."
- exit 0
+ 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
- echo "Error: $user_msg."
- exit 0
+ 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
- echo "Error: the process was restarted."
+ log_error "The process was restarted."
else
- echo "Success: the process was killed."
+ log_info "Success: the process was killed."
fi
- exit 0
+ quit 0
fi
diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test
index cf7789428b2..2eb4e6cbbb2 100644
--- a/mysql-test/t/limit.test
+++ b/mysql-test/t/limit.test
@@ -7,7 +7,7 @@ drop table if exists t1;
--enable_warnings
create table t1 (a int not null default 0 primary key, b int not null default 0);
-insert into t1 () values (); -- Testing default values
+insert into t1 () values (); # Testing default values
insert into t1 values (1,1),(2,1),(3,1);
update t1 set a=4 where b=1 limit 1;
select * from t1;
diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test
index 466f312757b..d3eeee3b41c 100644
--- a/mysql-test/t/lock_multi.test
+++ b/mysql-test/t/lock_multi.test
@@ -217,7 +217,10 @@ DROP TABLE t1;
# Bug #17264: MySQL Server freeze
#
connection locker;
+# Disable warnings to allow test to run also without InnoDB
+--disable_warnings
create table t1 (f1 int(12) unsigned not null auto_increment, primary key(f1)) engine=innodb;
+--enable_warnings
lock tables t1 write;
connection writer;
--sleep 2
diff --git a/mysql-test/t/log.sh b/mysql-test/t/log.sh
new file mode 100755
index 00000000000..20b265087cc
--- /dev/null
+++ b/mysql-test/t/log.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+###########################################################################
+
+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.log"
+
+shift
+
+log_debug "$*"
diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test
index 96437bc7636..31513f1bd06 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -85,3 +85,23 @@ drop table t1, t2;
show tables;
# End of 4.1 tests
+
+
+#
+# Bug#20404: SHOW CREATE TABLE fails with Turkish I
+#
+set names utf8;
+--disable_warnings
+drop table if exists Ä°,Ä°Ä°;
+--enable_warnings
+create table Ä° (s1 int);
+show create table Ä°;
+show tables;
+drop table Ä°;
+create table Ä°Ä° (s1 int);
+show create table Ä°Ä°;
+show tables;
+drop table Ä°Ä°;
+set names latin1;
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test
index 65338448555..a6ebfdc14c1 100644
--- a/mysql-test/t/metadata.test
+++ b/mysql-test/t/metadata.test
@@ -61,4 +61,23 @@ drop table t1;//
delimiter ;//
--disable_info
+#
+# Bug #20191: getTableName gives wrong or inconsistent result when using VIEWs
+#
+--enable_metadata
+create table t1 (id int(10));
+insert into t1 values (1);
+CREATE VIEW v1 AS select t1.id as id from t1;
+CREATE VIEW v2 AS select t1.id as renamed from t1;
+CREATE VIEW v3 AS select t1.id + 12 as renamed from t1;
+select * from v1 group by id limit 1;
+select * from v1 group by id limit 0;
+select * from v1 where id=1000 group by id;
+select * from v1 where id=1 group by id;
+select * from v2 where renamed=1 group by renamed;
+select * from v3 where renamed=1 group by renamed;
+drop table t1;
+drop view v1,v2,v3;
+--disable_metadata
+
# End of 4.1 tests
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index f3296e6f706..cb4a5593de7 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -143,6 +143,24 @@ drop table t1;
--exec diff $MYSQLTEST_VARDIR/tmp/bug20328_1.result $MYSQLTEST_VARDIR/tmp/bug20328_2.result
#
+# Bug #19216: Client crashes on long SELECT
+#
+--exec echo "select" > $MYSQLTEST_VARDIR/tmp/b19216.tmp
+# 3400 * 20 makes 68000 columns that is more than the max number that can fit
+# in a 16 bit number.
+let $i= 3400;
+while ($i)
+{
+ --exec echo "'a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a','a'," >> $MYSQLTEST_VARDIR/tmp/b19216.tmp
+ dec $i;
+}
+
+--exec echo "'b';" >> $MYSQLTEST_VARDIR/tmp/b19216.tmp
+--disable_query_log
+--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/b19216.tmp >/dev/null
+--enable_query_log
+
+#
# Bug #20103: Escaping with backslash does not work
#
--exec echo "SET SQL_MODE = 'NO_BACKSLASH_ESCAPES';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql
@@ -153,4 +171,74 @@ drop table t1;
--exec echo "SELECT '\';';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1
+#
+# Bug#17583: mysql drops connection when stdout is not writable
+#
+create table t17583 (a int);
+insert into t17583 (a) values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+insert into t17583 select a from t17583;
+# Close to the minimal data needed to exercise bug.
+select count(*) from t17583;
+--exec echo "select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; select count(*) from t17583; " |$MYSQL test >&-
+drop table t17583;
+
+#
+# Bug#20984: Reproducible MySQL client segmentation fault
+# + additional tests for the "com_connect" function in mysql
+#
+#
+--echo Test connect without db- or host-name => reconnect
+--exec $MYSQL test -e "\r" 2>&1
+--exec $MYSQL test -e "connect" 2>&1
+
+--echo Test connect with dbname only => new dbname, old hostname
+--exec $MYSQL test -e "\r test" 2>&1
+--exec $MYSQL test -e "connect test" 2>&1
+--exec $MYSQL test -e "\rtest" 2>&1
+--error 1
+--exec $MYSQL test -e "connecttest" 2>&1
+
+--echo Test connect with _invalid_ dbname only => new invalid dbname, old hostname
+--error 1
+--exec $MYSQL test -e "\r invalid" 2>&1
+--error 1
+--exec $MYSQL test -e "connect invalid" 2>&1
+
+--echo Test connect with dbname + hostname
+--exec $MYSQL test -e "\r test localhost" 2>&1
+--exec $MYSQL test -e "connect test localhost" 2>&1
+
+--echo Test connect with dbname + _invalid_ hostname
+# Mask the errno of the error message
+--replace_regex /\([0-9]*\)/(errno)/
+--error 1
+--exec $MYSQL test -e "\r test invalid_hostname" 2>&1
+--replace_regex /\([0-9]*\)/(errno)/
+--error 1
+--exec $MYSQL test -e "connect test invalid_hostname" 2>&1
+
+--echo The commands reported in the bug report
+--replace_regex /\([0-9]*\)/(errno)/
+--error 1
+--exec $MYSQL test -e "\r\r\n\r\n cyril\ has\ found\ a\ bug\ :)XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 2>&1
+
+#--replace_regex /\([0-9]*\)/(errno)/
+#--error 1
+#--exec echo '\r\r\n\r\n cyril\ has\ found\ a\ bug\ :)XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' | $MYSQL 2>&1
+
+--echo Too long dbname
+--error 1
+--exec $MYSQL test -e "\r test_really_long_dbnamexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx localhost" 2>&1
+
+--echo Too long hostname
+--replace_regex /\([0-9]*\)/(errno)/
+--error 1
+--exec $MYSQL test -e "\r test cyrils_superlonghostnameXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 2>&1
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/mysqldump-max.test b/mysql-test/t/mysqldump-max.test
index fbea84808b4..359c4ea5793 100644
--- a/mysql-test/t/mysqldump-max.test
+++ b/mysql-test/t/mysqldump-max.test
@@ -3,14 +3,9 @@
--source include/have_innodb.inc
--source include/have_archive.inc
---disable-warnings
-drop table if exists t1;
-drop table if exists t2;
-drop table if exists t3;
-drop table if exists t4;
-drop table if exists t5;
-drop table if exists t6;
---enable-warnings
+--disable_warnings
+drop table if exists t1, t2, t3, t4, t5, t6;
+--enable_warnings
create table t1 (id int(8), name varchar(32));
create table t2 (id int(8), name varchar(32)) ENGINE="MyISAM";
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index 6dfb24c2e75..72aad395ec0 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -1413,5 +1413,20 @@ DROP TABLE `t1`;
--enable_warnings
--echo #
+--echo # Bug #19745: mysqldump --xml produces invalid xml
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (f1 int(10), data MEDIUMBLOB);
+INSERT INTO t1 VALUES(1,0xff00fef0);
+
+--exec $MYSQL_DUMP --xml --hex-blob --skip-create-options test t1
+
+DROP TABLE t1;
+
+--echo #
--echo # End of 5.0 tests
--echo #
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index c30af8c8f26..3c20b38722f 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -317,7 +317,6 @@ select 3 from t1 ;
#
#select 3 from t1 ;
-# End of 4.1 tests
--error 1
--exec echo "disable_abort_on_error; enable_abort_on_error; error 1064; select 3 from t1; select 3 from t1;" | $MYSQL_TEST 2>&1
@@ -360,18 +359,80 @@ select 3 from t1 ;
# Missing delimiter
# The comment will be "sucked into" the sleep command since
# delimiter is missing until after "show status"
---system echo "sleep 4" > $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "# A comment" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "show status;" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+sleep 4
+# A comment
+show status;
+EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
#
# Missing delimiter until eof
# The comment will be "sucked into" the sleep command since
-# delimiter is missing
---system echo "sleep 7" > $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "# Another comment" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+# delimiter is missing
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+sleep 7
+# Another comment
+EOF
+--error 1
+--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
+
+#
+# Missing delimiter until "disable_query_log"
+#
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+disconnect default
+
+#
+# comment
+# comment 3
+disable_query_log;
+EOF
+--error 1
+--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
+
+#
+# Missing delimiter until "disable_query_log"
+#
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+disconnect default
+
+#
+# comment
+
+# comment 3
+disable_query_log;
+EOF
+--error 1
+--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
+
+#
+# Missing delimiter until eof
+#
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+disconnect default
+
+#
+# comment
+# comment2
+
+# comment 3
+--disable_query_log
+EOF
+--error 1
+--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
+
+#
+# Missing delimiter until eof
+#
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+disconnect default # comment
+# comment part2
+
+# comment 3
+--disable_query_log
+EOF
--error 1
--exec $MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/mysqltest.sql 2>&1
@@ -388,6 +449,67 @@ select 3 from t1 ;
--sleep 1 # Wait for insert delayed to be executed.
--sleep 1 # Wait for insert delayed to be executed.
+# ----------------------------------------------------------------------------
+# Test error
+# ----------------------------------------------------------------------------
+
+# Missing argument
+--error 1
+--exec echo "error;" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error" | $MYSQL_TEST 2>&1
+
+# First char must be uppercase 'S' or 'E' or [0-9]
+--error 1
+--exec echo "--error s99999" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error e99999" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error 9eeeee" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error 1sssss" | $MYSQL_TEST 2>&1
+
+# First char 'S' but too long
+--error 1
+--exec echo "--error S999999" | $MYSQL_TEST 2>&1
+
+# First char 'S' but lowercase char found
+--error 1
+--exec echo "--error S99a99" | $MYSQL_TEST 2>&1
+
+# First char 'S' but too short
+--error 1
+--exec echo "--error S9999" | $MYSQL_TEST 2>&1
+
+# First char 'E' but not found in error array
+--error 1
+--exec echo "--error E9999" | $MYSQL_TEST 2>&1
+
+# First char [0-9] but contains chars
+--error 1
+--exec echo "--error 999e9" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--error 9b" | $MYSQL_TEST 2>&1
+
+# Multiple errorcodes separated by ','
+--error 1,1,1,1
+#--error 9,ER_PARSE_ERROR
+#--error ER_PARSE_ERROR
+#--error 9,ER_PARSE_ERROR,9,ER_PARSE_ERROR
+#--error 9, ER_PARSE_ERROR, 9, ER_PARSE_ERROR
+#--error 9,S00000,9,ER_PARSE_ERROR
+#--error 9,S00000,9,ER_PARSE_ERROR,ER_PARSE_ERROR,ER_PARSE_ERROR,9,10,11,12
+--error 9,S00000,9
+--error 9,S00000,9,9,10,11,12
+--error 9 ,10
+--error 9 , 10
+--error 9 , 10
+--error 9 , 10
+
+# Too many errorcodes specified
+--error 1
+--exec echo "--error 1,2,3,4,5,6,7,8,9,10,11" | $MYSQL_TEST 2>&1
+
# ----------------------------------------------------------------------------
# Test echo command
@@ -411,8 +533,8 @@ echo - MySQL: The world''s
- source database;
echo - MySQL: The world''s
--- most popular open
--- source database;
+-- most popular
+-- open source database;
echo # MySQL: The
--world''s
@@ -469,8 +591,8 @@ echo $message;
let $message= -- MySQL: The
-- world''s most
--- popular open
--- source database;
+-- popular
+-- open source database;
echo $message;
let $message= # MySQL: The
@@ -533,9 +655,6 @@ echo Not a banana: $cat;
--exec echo "let \$=hi;" | $MYSQL_TEST 2>&1
--error 1
---exec echo "let hi=hi;" | $MYSQL_TEST 2>&1
-
---error 1
--exec echo "let \$1 hi;" | $MYSQL_TEST 2>&1
--error 1
@@ -613,6 +732,7 @@ echo $var3_var3;
# Fix win paths
--replace_result \\ /
+# Source a nonexisting file
--error 1
--exec echo "source non_existingFile;" | $MYSQL_TEST 2>&1
@@ -630,13 +750,16 @@ echo $var3_var3;
# Test execution of source in a while loop
+--write_file $MYSQLTEST_VARDIR/tmp/sourced.inc
+echo here is the sourced script;
+EOF
--disable_query_log
let $outer= 2; # Number of outer loops
while ($outer)
{
eval SELECT '$outer = outer loop variable after while' AS "";
- --source include/sourced.inc
+ --source $MYSQLTEST_VARDIR/tmp/sourced.inc
eval SELECT '$outer = outer loop variable before dec' AS "";
dec $outer;
@@ -664,11 +787,12 @@ let $num= 9;
while ($num)
{
SELECT 'In loop' AS "";
- --source include/sourced1.inc
+ --source $MYSQLTEST_VARDIR/tmp/sourced.inc
dec $num;
}
--enable_abort_on_error
--enable_query_log
+--remove_file $MYSQLTEST_VARDIR/tmp/sourced.inc
# ----------------------------------------------------------------------------
# Test sleep command
@@ -820,10 +944,150 @@ while (!$i)
}
# Exceed max nesting level
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest_while.inc
+let $1 = 10;
+while ($1)
+{
+while ($1)
+{
+while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ while ($1)
+{
+ echo $1;
+ dec $1;
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+}
+EOF
# Fix win path
---replace_result \\ /
+--replace_result \\ / $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
--error 1
---exec echo "source include/mysqltest_while.inc;" | $MYSQL_TEST 2>&1
+--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest_while.inc;" | $MYSQL_TEST 2>&1
+--remove_file $MYSQLTEST_VARDIR/tmp/mysqltest_while.inc
--error 1
--exec echo "while \$i;" | $MYSQL_TEST 2>&1
--error 1
@@ -928,12 +1192,6 @@ select "a" as col1, "c" as col2;
--error 1
--exec echo "connect (con2,);" | $MYSQL_TEST 2>&1
--error 1
---exec echo "connect (con2,localhost);" | $MYSQL_TEST 2>&1
---error 1
---exec echo "connect (con2, localhost, root);" | $MYSQL_TEST 2>&1
---error 1
---exec echo "connect (con2, localhost, root,);" | $MYSQL_TEST 2>&1
---error 1
--exec echo "connect (con2,localhost,root,,illegal_db);" | $MYSQL_TEST 2>&1
--error 1
--exec echo "connect (con1,localhost,root,,,illegal_port,);" | $MYSQL_TEST 2>&1
@@ -941,13 +1199,15 @@ select "a" as col1, "c" as col2;
--exec echo "connect (con1,localhost,root,,,,,SMTP POP);" | $MYSQL_TEST 2>&1
# Repeat connect/disconnect
---system echo "let \$i=100;" > $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "while (\$i)" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "{" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo " connect (test_con1,localhost,root,,); " >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo " disconnect test_con1; " >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo " dec \$i; " >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
---system echo "}" >> $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+--write_file $MYSQLTEST_VARDIR/tmp/mysqltest.sql
+let $i=100;
+while ($i)
+{
+ connect (test_con1,localhost,root,,);
+ disconnect test_con1;
+ dec $i;
+}
+EOF
--exec echo "source $MYSQLTEST_VARDIR/tmp/mysqltest.sql; echo OK;" | $MYSQL_TEST 2>&1
# Repeat connect/disconnect, exceed max number of connections
@@ -1136,7 +1396,6 @@ drop table t1;
--exec test -s $MYSQLTEST_VARDIR/tmp/bug11731.out
drop table t1;
-
#
# Bug#19890 mysqltest: "query" command is broken
#
@@ -1152,3 +1411,156 @@ query sleep;
# Just an empty query command
--error 1065
query ;
+
+# test for replace_regex
+--replace_regex /at/b/
+select "at" as col1, "c" as col2;
+
+--replace_regex /at/b/i
+select "at" as col1, "AT" as col2, "c" as col3;
+
+--replace_regex /a/b/ /ct/d/
+select "a" as col1, "ct" as col2;
+
+--replace_regex /(strawberry)/raspberry and \1/ /blueberry/blackberry/ /potato/tomato/;
+select "strawberry","blueberry","potato";
+
+--error 1
+--exec echo "--replace_regex a" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--replace_regex a;" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "replace_regex a;" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "replace_regex a ;" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "replace_regex a b; echo OK;" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "--replace_regex /a b c" | $MYSQL_TEST 2>&1
+--error 1
+--exec echo "replace_regex /a /b c ;" | $MYSQL_TEST 2>&1
+
+# REQUIREMENT
+# replace_regex should replace substitutions from left to right in output
+
+create table t1 (a int, b int);
+insert into t1 values (1,3);
+insert into t1 values (2,4);
+--replace_regex /A/C/ /B/D/i /3/2/ /2/1/
+select * from t1;
+drop table t1;
+
+# ----------------------------------------------------------------------------
+# test for remove_file
+# ----------------------------------------------------------------------------
+
+--error 1
+--exec echo "remove_file ;" | $MYSQL_TEST 2>&1
+
+--error 1
+remove_file non_existing_file;
+
+# ----------------------------------------------------------------------------
+# test for write_file
+# ----------------------------------------------------------------------------
+--error 1
+--exec echo "write_file ;" | $MYSQL_TEST 2>&1
+
+--error 1
+--exec echo "write_file filename ;" | $MYSQL_TEST 2>&1
+
+--error 1
+--exec echo "write_file filename \";" | $MYSQL_TEST 2>&1
+
+write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+Content for test_file1
+EOF
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+
+write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp END_DELIMITER;
+Content for test_file1 contains EOF
+END_DELIMITER
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+
+# ----------------------------------------------------------------------------
+# test for file_exist
+# ----------------------------------------------------------------------------
+--error 1
+--exec echo "file_exists ;" | $MYSQL_TEST 2>&1
+
+--error 0,1
+remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+--error 1
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+write_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+Content for test_file1
+EOF
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+--error 1
+file_exists $MYSQLTEST_VARDIR/tmp/test_file1.tmp;
+
+
+# ----------------------------------------------------------------------------
+# test for copy_file
+# ----------------------------------------------------------------------------
+--write_file $MYSQLTEST_VARDIR/tmp/file1.tmp
+file1
+EOF
+
+copy_file $MYSQLTEST_VARDIR/tmp/file1.tmp $MYSQLTEST_VARDIR/tmp/file2.tmp;
+file_exists $MYSQLTEST_VARDIR/tmp/file2.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/file1.tmp;
+remove_file $MYSQLTEST_VARDIR/tmp/file2.tmp;
+
+--error 1
+--exec echo "copy_file ;" | $MYSQL_TEST 2>&1
+
+--error 1
+--exec echo "copy_file from_file;" | $MYSQL_TEST 2>&1
+
+# ----------------------------------------------------------------------------
+# test for perl
+# ----------------------------------------------------------------------------
+--perl
+print "hello\n";
+EOF
+
+--perl EOF
+print "hello\n";
+EOF
+
+--perl DELIMITER
+print "hello\n";
+DELIMITER
+
+--error 1
+--exec echo "perl TOO_LONG_DELIMITER ;" | $MYSQL_TEST 2>&1
+
+perl;
+print "hello\n";
+EOF
+
+perl;
+ # Print "hello"
+ print "hello\n";
+EOF
+
+# ----------------------------------------------------------------------------
+# test for die
+# ----------------------------------------------------------------------------
+
+--error 1
+--exec echo "die test of die;" | $MYSQL_TEST 2>&1
+
+
+# ----------------------------------------------------------------------------
+# test for exit
+# ----------------------------------------------------------------------------
+
+--exec echo "echo Some output; exit; echo Not this;" | $MYSQL_TEST 2>&1
+
+
+--echo End of tests
diff --git a/mysql-test/t/ndb_condition_pushdown.test b/mysql-test/t/ndb_condition_pushdown.test
index cc138b32b7e..748c26e2a9a 100644
--- a/mysql-test/t/ndb_condition_pushdown.test
+++ b/mysql-test/t/ndb_condition_pushdown.test
@@ -1649,6 +1649,16 @@ set engine_condition_pushdown = on;
explain select * from t5 where b like '%jo%';
select * from t5 where b like '%jo%' order by a;
+# bug#21056 ndb pushdown equal/setValue error on datetime
+set engine_condition_pushdown = off;
+select auto from t1 where date_time like '1902-02-02 %' order by auto;
+select auto from t1 where date_time not like '1902-02-02 %' order by auto;
+set engine_condition_pushdown = on;
+explain select auto from t1 where date_time like '1902-02-02 %';
+select auto from t1 where date_time like '1902-02-02 %' order by auto;
+explain select auto from t1 where date_time not like '1902-02-02 %';
+select auto from t1 where date_time not like '1902-02-02 %' order by auto;
+
# bug#17421 -1
drop table t1;
create table t1 (a int, b varchar(3), primary key using hash(a))
diff --git a/mysql-test/t/ndb_config.test b/mysql-test/t/ndb_config.test
index 4787abe86e2..f63c0087c1e 100644
--- a/mysql-test/t/ndb_config.test
+++ b/mysql-test/t/ndb_config.test
@@ -16,3 +16,8 @@
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster1 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --ndb-shm --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
+
+
+--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=nodeid --host=localhost --config-file=$NDB_BACKUP_DIR/config.ini 2> /dev/null
+--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=nodeid --host=1.2.3.4 --config-file=$NDB_BACKUP_DIR/config.ini 2> /dev/null
+--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=nodeid --host=127.0.0.1 --config-file=$NDB_BACKUP_DIR/config.ini 2> /dev/null
diff --git a/mysql-test/t/ndb_multi.test b/mysql-test/t/ndb_multi.test
index 1183f2b283f..3bc735b60d4 100644
--- a/mysql-test/t/ndb_multi.test
+++ b/mysql-test/t/ndb_multi.test
@@ -37,9 +37,6 @@ drop table t1;
create table t1 (a int) engine=ndbcluster;
insert into t1 value (2);
connection server1;
-# Currently a retry is required remotely
---error 1296
-select * from t1;
flush table t1;
select * from t1;
@@ -69,4 +66,26 @@ drop table t1, t2, t3, t4;
connection server2;
drop table t1, t3, t4;
+# bug#21378
+connection server1;
+create table t1(c1 int key)ENGINE=MyISAM;
+insert into t1 values(1),(3),(5);
+select * from t1 order by c1;
+
+connection server2;
+create table t1(c1 int key)ENGINE=MyISAM;
+insert into t1 values(100),(344),(533);
+select * from t1 order by c1;
+
+connection server1;
+alter table t1 engine=ndb;
+
+connection server2;
+show tables;
+select * from t1 order by c1;
+drop table t1;
+
+connection server1;
+select * from t1 order by c1;
+drop table t1;
# End of 4.1 tests
diff --git a/mysql-test/t/not_embedded_server-master.opt b/mysql-test/t/not_embedded_server-master.opt
index 35fcc5f30c6..cef79bc8585 100644
--- a/mysql-test/t/not_embedded_server-master.opt
+++ b/mysql-test/t/not_embedded_server-master.opt
@@ -1 +1 @@
---loose-to-force-a-restart
+--force-restart
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index 4aec745f3f7..65e09b006ec 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -177,7 +177,7 @@ drop table t1;
# non-null string collation, i.e. case insensitively,
# rather than according to NULL's collation, i.e. case sensitively
#
--- in field
+# in field
select
case 'str' when 'STR' then 'str' when null then 'null' end as c01,
case 'str' when null then 'null' when 'STR' then 'str' end as c02,
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 30dc4d2653e..d7cf0e2a375 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -514,11 +514,6 @@ set max_sort_length=20;
select a from t1 order by a;
drop table t1;
-create table t1 (a int not null, b int not null, c int not null);
-insert t1 values (1,1,1),(1,1,2),(1,2,1);
-select a, b from t1 group by a, b order by sum(c);
-drop table t1;
-
#
# Bug #7331
#
@@ -594,6 +589,10 @@ SELECT a.a + 1 AS num FROM t1 a JOIN t1 b ON num = b.a;
DROP TABLE t1;
# End of 4.1 tests
+create table t1 (a int not null, b int not null, c int not null);
+insert t1 values (1,1,1),(1,1,2),(1,2,1);
+select a, b from t1 group by a, b order by sum(c);
+drop table t1;
#
# Bug#21302: Result not properly sorted when using an ORDER BY on a second
diff --git a/mysql-test/t/ps-master.opt b/mysql-test/t/ps-master.opt
new file mode 100644
index 00000000000..3eb98fc3d6b
--- /dev/null
+++ b/mysql-test/t/ps-master.opt
@@ -0,0 +1 @@
+--log-slow-queries --log-long-format --log-queries-not-using-indexes
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index f1e8e77d94e..547f9a766d1 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -354,14 +354,14 @@ create table t1 (a int, b int);
insert into t1 (a, b) values (1,1), (1,2), (2,1), (2,2);
prepare stmt from
"explain select * from t1 where t1.a=2 and t1.a=t1.b and t1.b > 1 + ?";
---replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
set @v=5;
-execute stmt using @v;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
-set @v=0;
execute stmt using @v;
+set @v=0;
--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
+execute stmt using @v;
set @v=5;
+--replace_column 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -
execute stmt using @v;
drop table t1;
deallocate prepare stmt;
@@ -848,6 +848,9 @@ drop table t1;
# Bug#16365 Prepared Statements: DoS with too many open statements
# Check that the limit @@max_prpeared_stmt_count works.
#
+# This is also the test for bug#23159 prepared_stmt_count should be
+# status variable.
+#
# Save the old value
set @old_max_prepared_stmt_count= @@max_prepared_stmt_count;
#
@@ -857,17 +860,17 @@ set @old_max_prepared_stmt_count= @@max_prepared_stmt_count;
#
--disable_ps_protocol
#
-# A. Check that the new variables are present in SHOW VARIABLES list.
+# A. Check that the new variables are present in SHOW VARIABLES and
+# SHOW STATUS lists.
#
show variables like 'max_prepared_stmt_count';
-show variables like 'prepared_stmt_count';
+show status like 'prepared_stmt_count';
#
-# B. Check that the new variables are selectable.
+# B. Check that the new system variable is selectable.
#
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
+select @@max_prepared_stmt_count;
#
-# C. Check that max_prepared_stmt_count is settable (global only),
-# whereas prepared_stmt_count is readonly.
+# C. Check that max_prepared_stmt_count is settable (global only).
#
set global max_prepared_stmt_count=-1;
select @@max_prepared_stmt_count;
@@ -881,12 +884,6 @@ set @@max_prepared_stmt_count=1;
set max_prepared_stmt_count=1;
--error ER_GLOBAL_VARIABLE
set local max_prepared_stmt_count=1;
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-set local prepared_stmt_count=0;
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-set @@prepared_stmt_count=0;
---error ER_INCORRECT_GLOBAL_LOCAL_VAR
-set global prepared_stmt_count=1;
# set to a reasonable limit works
set global max_prepared_stmt_count=1;
select @@max_prepared_stmt_count;
@@ -894,47 +891,50 @@ select @@max_prepared_stmt_count;
# D. Check that the variables actually work.
#
set global max_prepared_stmt_count=0;
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
+select @@max_prepared_stmt_count;
+show status like 'prepared_stmt_count';
--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt from "select 1";
-select @@prepared_stmt_count;
+show status like 'prepared_stmt_count';
set global max_prepared_stmt_count=1;
prepare stmt from "select 1";
-select @@prepared_stmt_count;
+show status like 'prepared_stmt_count';
--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt1 from "select 1";
-select @@prepared_stmt_count;
+show status like 'prepared_stmt_count';
deallocate prepare stmt;
-select @@prepared_stmt_count;
+show status like 'prepared_stmt_count';
#
# E. Check that we can prepare a statement with the same name
# successfully, without hitting the limit.
#
prepare stmt from "select 1";
-select @@prepared_stmt_count;
+show status like 'prepared_stmt_count';
prepare stmt from "select 2";
-select @@prepared_stmt_count;
+show status like 'prepared_stmt_count';
#
# F. We can set the max below the current count. In this case no new
# statements should be allowed to prepare.
#
-select @@prepared_stmt_count, @@max_prepared_stmt_count;
+show status like 'prepared_stmt_count';
+select @@max_prepared_stmt_count;
set global max_prepared_stmt_count=0;
--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt from "select 1";
# Result: the old statement is deallocated, the new is not created.
---error 1243 # ER_UNKNOWN_STMT_HANDLER
+--error ER_UNKNOWN_STMT_HANDLER
execute stmt;
-select @@prepared_stmt_count;
+show status like 'prepared_stmt_count';
--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt from "select 1";
-select @@prepared_stmt_count;
+show status like 'prepared_stmt_count';
#
# G. Show that the variables are up to date even after a connection with all
# statements in it was terminated.
#
set global max_prepared_stmt_count=3;
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
+select @@max_prepared_stmt_count;
+show status like 'prepared_stmt_count';
prepare stmt from "select 1";
connect (con1,localhost,root,,);
connection con1;
@@ -943,26 +943,20 @@ prepare stmt1 from "select 3";
--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt2 from "select 4";
connection default;
---error ER_MAX_PREPARED_STMT_COUNT_REACHED
+--error ER_MAX_PREPARED_STMT_COUNT_REACHED
prepare stmt2 from "select 4";
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
+select @@max_prepared_stmt_count;
+show status like 'prepared_stmt_count';
disconnect con1;
connection default;
-# Wait for the connection to die: deal with a possible race
deallocate prepare stmt;
-let $count= `select @@prepared_stmt_count`;
-if ($count)
-{
---sleep 2
- let $count= `select @@prepared_stmt_count`;
-}
-select @@max_prepared_stmt_count, @@prepared_stmt_count;
#
# Restore the old value.
#
set global max_prepared_stmt_count= @old_max_prepared_stmt_count;
--enable_ps_protocol
+
#
# Bug#19399 "Stored Procedures 'Lost Connection' when dropping/creating
# tables"
@@ -988,6 +982,7 @@ execute stmt;
drop temporary table t1;
deallocate prepare stmt;
+
#
# BUG#22085: Crash on the execution of a prepared statement that
# uses an IN subquery with aggregate functions in HAVING
@@ -1040,7 +1035,82 @@ EXECUTE STMT USING @id,@id;
DEALLOCATE PREPARE STMT;
DROP TABLE t1;
---echo End of 4.1 tests
+
+#
+# BUG#21354: (COUNT(*) = 1) not working in SELECT inside prepared
+# statement
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT, INDEX(i));
+INSERT INTO t1 VALUES (1);
+
+PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?";
+SET @a = 0;
+EXECUTE stmt USING @a;
+SET @a = 1;
+EXECUTE stmt USING @a;
+SET @a = 0;
+EXECUTE stmt USING @a;
+
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+
+
+--echo End of 4.1 tests.
+
+
+
############################# 5.0 tests start ################################
#
#
@@ -1437,4 +1507,60 @@ DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
+#
+# BUG#20327: Marking of a wrong field leads to a wrong result on select with
+# view, prepared statement and subquery.
+#
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+INSERT INTO t1 VALUES (1), (2);
+
+let $query = SELECT t1.i FROM t1 JOIN v1 ON t1.i = v1.i
+ WHERE EXISTS (SELECT * FROM t1 WHERE v1.i = 1);
+eval $query;
+eval PREPARE stmt FROM "$query";
+# Statement execution should return '1'.
+EXECUTE stmt;
+# Check re-execution.
+EXECUTE stmt;
+
+DEALLOCATE PREPARE stmt;
+DROP VIEW v1;
+DROP TABLE t1;
+
+
+#
+# BUG#21856: Prepared Statments: crash if bad create
+#
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+--enable_warnings
+
+let $iterations= 100;
+--disable_query_log
+--disable_result_log
+while ($iterations > 0)
+{
+ --error ER_PARSE_ERROR
+ PREPARE stmt FROM "CREATE PROCEDURE p1()";
+ dec $iterations;
+}
+--enable_query_log
+--enable_result_log
+
+#
+# Bug 19764: SHOW commands end up in the slow log as table scans
+#
+
+flush status;
+prepare sq from 'show status like "slow_queries"';
+execute sq;
+prepare no_index from 'select 1 from information_schema.tables limit 1';
+execute sq;
+execute no_index;
+execute sq;
+deallocate prepare no_index;
+deallocate prepare sq;
+
--echo End of 5.0 tests.
diff --git a/mysql-test/t/ps_11bugs.test b/mysql-test/t/ps_11bugs.test
index ff1c87f3bd8..515bcc03c1a 100644
--- a/mysql-test/t/ps_11bugs.test
+++ b/mysql-test/t/ps_11bugs.test
@@ -144,3 +144,37 @@ prepare st_18492 from 'select * from t1 where 3 in (select (1+1) union select 1)
execute st_18492;
drop table t1;
+
+#
+# Bug#19356: Assertion failure with undefined @uservar in prepared statement execution
+#
+create table t1 (a int, b varchar(4));
+create table t2 (a int, b varchar(4), primary key(a));
+
+prepare stmt1 from 'insert into t1 (a, b) values (?, ?)';
+prepare stmt2 from 'insert into t2 (a, b) values (?, ?)';
+
+set @intarg= 11;
+set @varchararg= '2222';
+execute stmt1 using @intarg, @varchararg;
+execute stmt2 using @intarg, @varchararg;
+set @intarg= 12;
+execute stmt1 using @intarg, @UNDEFINED;
+execute stmt2 using @intarg, @UNDEFINED;
+set @intarg= 13;
+execute stmt1 using @UNDEFINED, @varchararg;
+--error 1048
+execute stmt2 using @UNDEFINED, @varchararg;
+set @intarg= 14;
+set @nullarg= Null;
+execute stmt1 using @UNDEFINED, @nullarg;
+--error 1048
+execute stmt2 using @nullarg, @varchararg;
+
+select * from t1;
+select * from t2;
+
+drop table t1;
+drop table t2;
+
+--echo End of 5.0 tests.
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index 8d0f9885e80..33b86dde9ed 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -316,8 +316,8 @@ prepare stmt4 from ' show table status from test like ''t9%'' ';
--replace_column 8 # 12 # 13 # 14 #
# Bug#4288
execute stmt4;
---replace_column 2 #
prepare stmt4 from ' show status like ''Threads_running'' ';
+--replace_column 2 #
execute stmt4;
prepare stmt4 from ' show variables like ''sql_mode'' ';
execute stmt4;
diff --git a/mysql-test/t/ps_grant.test b/mysql-test/t/ps_grant.test
index 81c842de459..22ac8675328 100644
--- a/mysql-test/t/ps_grant.test
+++ b/mysql-test/t/ps_grant.test
@@ -35,7 +35,7 @@ use mysqltest;
--source include/ps_create.inc
--source include/ps_renew.inc
--enable_query_log
-eval use $DB;
+use test;
grant usage on mysqltest.* to second_user@localhost
identified by 'looser' ;
grant select on mysqltest.t9 to second_user@localhost
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index d416f34ce45..f6e480282ff 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -695,7 +695,7 @@ select a from t1;
flush query cache;
drop table t1, t2;
-set GLOBAL query_cache_size=1355776
+set GLOBAL query_cache_size=1355776;
#
@@ -870,3 +870,32 @@ select * from t1 where a > 3;
show status like 'last_query_cost';
drop table t1;
SET GLOBAL query_cache_size=0;
+
+#
+# Bug #20045: Server crash on INSERT ... SELECT ... FROM non-mergeable view
+#
+set global query_cache_size=1024*1024;
+flush status;
+create table t1 (a int);
+insert into t1 (a) values (1), (2), (3);
+select * from t1;
+show status like 'Qcache_hits';
+select * from t1;
+show status like 'Qcache_hits';
+create table t2 like t1;
+select * from t1;
+show status like 'Qcache_hits';
+insert into t2 select * from t1;
+select * from t1;
+show status like 'Qcache_hits';
+drop table t1, t2;
+
+create table t1(c1 int);
+create table t2(c1 int);
+create table t3(c1 int);
+create view v1 as select t3.c1 as c1 from t3,t2 where t3.c1 = t2.c1;
+start transaction;
+insert into t1(c1) select c1 from v1;
+drop table t1, t2, t3;
+drop view v1;
+set global query_cache_size=0;
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index 240851e6ac4..5a146bbcf86 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -515,7 +515,17 @@ OR ((pk4 =1) AND (((pk1 IN ( 7, 2, 1 ))) OR (pk1 =522)) AND ((pk2 IN ( 0, 2635))
) AND (pk3 >=1000000);
drop table t1, t2;
-# End of 4.1 tests
+#
+# Bug #20732: Partial index and long sjis search with '>' fails sometimes
+#
+
+create table t1(a char(2), key(a(1)));
+insert into t1 values ('x'), ('xx');
+explain select a from t1 where a > 'x';
+select a from t1 where a > 'x';
+drop table t1;
+
+--echo End of 4.1 tests
#
# Test for optimization request #10561: to use keys for
diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test
index dab2c629fdd..fce37d8466d 100644
--- a/mysql-test/t/rename.test
+++ b/mysql-test/t/rename.test
@@ -39,8 +39,8 @@ select * from t3;
drop table if exists t1,t2,t3,t4;
#
-# Test-case for Bug #2397 RENAME TABLES is not blocked by
-# FLUSH TABLES WITH READ LOCK
+# Bug #2397 RENAME TABLES is not blocked by
+# FLUSH TABLES WITH READ LOCK
#
connect (con1,localhost,root,,);
@@ -54,12 +54,17 @@ FLUSH TABLES WITH READ LOCK;
connection con1;
send RENAME TABLE t1 TO t2, t3 to t4;
connection con2;
-sleep 1;
show tables;
UNLOCK TABLES;
connection con1;
reap;
connection con2;
+
+# Wait for the the tables to be renamed
+# i.e the query below succeds
+let $query= select * from t2, t4;
+source include/wait_for_query_to_suceed.inc;
+
show tables;
drop table t2, t4;
@@ -68,6 +73,10 @@ disconnect con2;
disconnect con1;
connection default;
+
+--echo End of 4.1 tests
+
+
#
# Bug#14959: ALTER TABLE isn't able to rename a view
#
@@ -81,4 +90,6 @@ rename table v2 to v1;
rename table v2 to v1;
drop view v1;
drop table t1;
-# End of 4.1 tests
+
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/rpl000018.test b/mysql-test/t/rpl000018.test
deleted file mode 100644
index bc6d887cc99..00000000000
--- a/mysql-test/t/rpl000018.test
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Running test with abort-slave-event-count=1
-# This will force slave to reconnect after every event
-#
-
-require_manager;
-connect (master,localhost,root,,test,0,$MASTER_MYPORT);
-connect (slave,localhost,root,,test,0,slave.sock);
-connection master;
-reset master;
-server_stop master;
-server_start master;
-connection slave;
-reset slave;
-start slave;
-connection master;
-show binary logs;
---disable_warnings
-drop table if exists t1;
---enable_warnings
-create table t1(n int);
-insert into t1 values (3351);
-sync_slave_with_master;
-select * from t1;
-connection master;
-drop table t1;
-sync_slave_with_master;
-
-# End of 4.1 tests
diff --git a/mysql-test/t/rpl_chain_temp_table.test b/mysql-test/t/rpl_chain_temp_table.test
deleted file mode 100644
index 96e228a17a1..00000000000
--- a/mysql-test/t/rpl_chain_temp_table.test
+++ /dev/null
@@ -1,101 +0,0 @@
- # This test makes some assumptions about values of thread ids, which should be
-# true if the servers have been restarted for this test. So we want to
-# stop/restart servers. Note that if assumptions are wrong, the test will not
-# fail; it will just fail to test the error-prone scenario.
-# Using the manager is the only way to have more than one slave server.
-# So you must run this test with --manager.
-
-require_manager;
-server_stop master;
-server_start master;
-server_stop slave;
-server_start slave;
-# no need for slave_sec (no assumptions on thread ids for this server).
-
-source include/master-slave.inc;
-connect (slave_sec,localhost,root,,test,0,slave.sock-1);
-connection master;
-save_master_pos;
-connection slave;
-sync_with_master;
-reset master;
-save_master_pos;
-connection slave_sec;
-eval change master to master_host='127.0.0.1',master_port=$SLAVE_MYPORT, master_user='root';
-start slave;
-sync_with_master;
-
-# :P now we have a chain ready-to-test.
-
-connection master;
-create temporary table t1 (a int);
-save_master_pos;
-connection slave;
-sync_with_master;
-connection master1;
-create temporary table t1 (a int);
-save_master_pos;
-connection slave;
-sync_with_master;
-save_master_pos;
-
-# First test:
-
-connection slave_sec;
-# Before BUG#1686 ("If 2 master threads with same-name temp table, slave makes
-# bad binlog") was fixed, sync_with_master failed
-sync_with_master;
-show status like 'slave_open_temp_tables';
-
-# 'master' and 'master1' usually have thread id 2-3 or 3-4.
-# 'slave' and 'slave1' usually have thread id 2-3.
-connection slave;
-create temporary table t1 (a int);
-connection slave1;
-create temporary table t1 (a int);
-# So it's likely that in the binlog of slave we get
-# server_id=of_master thread_id=3 create temp...
-# server_id=of_slave thread_id=3 create temp...
-# which would confuse slave-sec unless slave-sec uses server id to distinguish
-# between temp tables (here thread id is obviously not enough to distinguish).
-
-save_master_pos;
-
-# Second test:
-
-connection slave_sec;
-# If we did not use the server id to distinguish between temp tables,
-# sync_with_master would fail
-sync_with_master;
-show status like 'slave_open_temp_tables';
-
-# Third test (BUG#1240 "slave of slave breaks when STOP SLAVE was issud on
-# parent slave and temp tables").
-stop slave;
-connection slave;
-insert into t1 values(1);
-create table t2 as select * from t1;
-save_master_pos;
-connection slave_sec;
-start slave;
-sync_with_master;
-show status like 'slave_open_temp_tables';
-select * from t2;
-
-# clean up
-connection slave;
-drop table t2;
-save_master_pos;
-connection slave_sec;
-sync_with_master;
-
-# On purpose, we don't delete the temporary tables explicitely.
-# So temp tables remain on slave (remember they are not deleted when the slave
-# SQL thread terminates). If you run this test with
-# --valgrind --valgrind-options=--show-reachable=yes
-# you will see if they get cleaned up at slave's shutdown (that is, if the
-# memory they use is freed (it should) by mysqld before it terminates).
-# If they wouldn't be cleaned up, you would see some "still reachable" blocks in
-# Valgrind.
-
-# End of 4.1 tests
diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test
index 684cb54611c..6c5f942cec9 100644
--- a/mysql-test/t/rpl_deadlock.test
+++ b/mysql-test/t/rpl_deadlock.test
@@ -16,7 +16,8 @@ source include/master-slave.inc;
connection master;
create table t1 (a int not null, key(a)) engine=innodb;
create table t2 (a int not null, key(a)) engine=innodb;
-create table t3 (a int) engine=innodb;
+# requiring 'unique' for the timeout part of the test
+create table t3 (a int unique) engine=innodb;
create table t4 (a int) engine=innodb;
show variables like 'slave_transaction_retries';
sync_slave_with_master;
@@ -31,8 +32,7 @@ stop slave;
connection master;
begin;
# Let's keep BEGIN and the locked statement in two different relay logs.
-let $1=200;
-disable_query_log;
+let $1=200;disable_query_log;
while ($1)
{
eval insert into t3 values( $1 );
@@ -59,7 +59,7 @@ enable_query_log;
select * from t1 for update;
start slave;
--real_sleep 3 # hope that slave is blocked now
-insert into t2 values(22); # provoke deadlock, slave should be victim
+insert into t2 values(201); # provoke deadlock, slave should be victim
commit;
sync_with_master;
select * from t1; # check that slave succeeded finally
@@ -74,11 +74,13 @@ show slave status;
# 2) Test lock wait timeout
stop slave;
-change master to master_log_pos=532; # the BEGIN log event
+delete from t3;
+change master to master_log_pos=539; # the BEGIN log event
begin;
select * from t2 for update; # hold lock
start slave;
--real_sleep 10 # slave should have blocked, and be retrying
+select count(*) from t3 /* must be zero */; # replaying begins after rollback
commit;
sync_with_master;
select * from t1; # check that slave succeeded finally
@@ -97,11 +99,13 @@ set global max_relay_log_size=0;
# This is really copy-paste of 2) of above
stop slave;
-change master to master_log_pos=532;
+delete from t3;
+change master to master_log_pos=539;
begin;
select * from t2 for update;
start slave;
--real_sleep 10
+select count(*) from t3 /* must be zero */; # replaying begins after rollback
commit;
sync_with_master;
select * from t1;
diff --git a/mysql-test/t/rpl_dual_pos_advance-master.opt b/mysql-test/t/rpl_dual_pos_advance-master.opt
index 35fcc5f30c6..cef79bc8585 100644
--- a/mysql-test/t/rpl_dual_pos_advance-master.opt
+++ b/mysql-test/t/rpl_dual_pos_advance-master.opt
@@ -1 +1 @@
---loose-to-force-a-restart
+--force-restart
diff --git a/mysql-test/t/rpl_empty_master_crash-master.opt b/mysql-test/t/rpl_empty_master_crash-master.opt
new file mode 100644
index 00000000000..cef79bc8585
--- /dev/null
+++ b/mysql-test/t/rpl_empty_master_crash-master.opt
@@ -0,0 +1 @@
+--force-restart
diff --git a/mysql-test/t/rpl_failsafe.test b/mysql-test/t/rpl_failsafe.test
deleted file mode 100644
index 4336d897fc0..00000000000
--- a/mysql-test/t/rpl_failsafe.test
+++ /dev/null
@@ -1,24 +0,0 @@
-require_manager;
-source include/master-slave.inc;
-connect (slave_sec,localhost,root,,test,0,slave.sock-1);
-connect (slave_ter,localhost,root,,test,0,slave.sock-2);
-connection master;
-show variables like 'rpl_recovery_rank';
-show status like 'Rpl_status';
-create table t1(n int);
-drop table t1;
-sync_slave_with_master;
-show variables like 'rpl_recovery_rank';
-show status like 'Rpl_status';
-connection slave_sec;
-start slave;
-sync_with_master;
-show variables like 'rpl_recovery_rank';
-show status like 'Rpl_status';
-connection slave_ter;
-start slave;
-sync_with_master;
-show variables like 'rpl_recovery_rank';
-show status like 'Rpl_status';
-
-# End of 4.1 tests
diff --git a/mysql-test/t/rpl_flush_tables.test b/mysql-test/t/rpl_flush_tables.test
index bbc5c33770c..f7c8774286a 100644
--- a/mysql-test/t/rpl_flush_tables.test
+++ b/mysql-test/t/rpl_flush_tables.test
@@ -8,6 +8,8 @@
# merge table getting renamed.
--source include/not_windows.inc
+let $SERVER_VERSION=`select version()`;
+
create table t1 (a int);
insert into t1 values (10);
create table t2 (a int);
diff --git a/mysql-test/t/rpl_heap.test b/mysql-test/t/rpl_heap.test
deleted file mode 100644
index 3ee335fe58d..00000000000
--- a/mysql-test/t/rpl_heap.test
+++ /dev/null
@@ -1,51 +0,0 @@
-# You must run this test with --manager.
-
-require_manager;
-
-# Don't know why, but using TCP/IP connections makes this test fail
-# with "Lost connection to MySQL server during query" when we
-# issue a query after the server restart.
-# Maybe this is something awkward in mysqltest or in the manager?
-# So we use sockets.
-connect (master,localhost,root,,test,0,$MASTER_MYPORT);
-connect (slave,localhost,root,,test,0,slave.sock);
-
-connection master;
-reset master;
-drop table if exists t1;
-# we use CREATE SELECT to verify that DELETE does not get into binlog
-# before CREATE SELECT
-create table t1 type=HEAP select 10 as a;
-insert into t1 values(11);
-save_master_pos;
-show binlog events from 79;
-connection slave;
-reset slave;
-start slave;
-sync_with_master;
-show create table t1;
-select * from t1; # should be one row
-
-server_stop master;
-server_start master;
-
-connection master;
-select * from t1;
-# to check that DELETE is not written twice
-# (the LIMIT is to not use the query cache)
-select * from t1 limit 10;
-save_master_pos;
-show binlog events in 'master-bin.002' from 79;
-
-connection slave;
-sync_with_master;
-select * from t1; # should be empty
-
-# clean up
-connection master;
-drop table t1;
-save_master_pos;
-connection slave;
-sync_with_master;
-
-# End of 4.1 tests
diff --git a/mysql-test/t/rpl_ignore_table-slave.opt b/mysql-test/t/rpl_ignore_table-slave.opt
index cb49119bfcb..3aabbb2e0f5 100644
--- a/mysql-test/t/rpl_ignore_table-slave.opt
+++ b/mysql-test/t/rpl_ignore_table-slave.opt
@@ -1 +1 @@
---replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3
+--replicate-ignore-table=test.t1 --replicate-ignore-table=test.t2 --replicate-ignore-table=test.t3 --replicate-wild-ignore-table=%.tmptbl%
diff --git a/mysql-test/t/rpl_ignore_table.test b/mysql-test/t/rpl_ignore_table.test
index bc651779208..b875075f71c 100644
--- a/mysql-test/t/rpl_ignore_table.test
+++ b/mysql-test/t/rpl_ignore_table.test
@@ -26,3 +26,26 @@ SELECT * FROM t4;
connection master;
DROP TABLE t1;
DROP TABLE t4;
+
+
+#
+# bug#22877 replication character sets get out of sync
+# using replicate-wild-ignore-table
+#
+--disable_warnings
+DROP TABLE IF EXISTS t5;
+--enable_warnings
+CREATE TABLE t5 (
+ word varchar(50) collate utf8_unicode_ci NOT NULL default ''
+) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+SET @@session.character_set_client=33,@@session.collation_connection=192;
+CREATE TEMPORARY TABLE tmptbl504451f4258$1 (id INT NOT NULL) ENGINE=MEMORY;
+INSERT INTO t5 (word) VALUES ('TEST’');
+SELECT HEX(word) FROM t5;
+sync_slave_with_master;
+connection slave;
+SELECT HEX(word) FROM t5;
+--error 1146
+SELECT * FROM tmptbl504451f4258$1;
+connection master;
+DROP TABLE t5;
diff --git a/mysql-test/t/rpl_log-master.opt b/mysql-test/t/rpl_log-master.opt
index e0d075c3fbd..cef79bc8585 100644
--- a/mysql-test/t/rpl_log-master.opt
+++ b/mysql-test/t/rpl_log-master.opt
@@ -1 +1 @@
---skip-external-locking
+--force-restart
diff --git a/mysql-test/t/rpl_packet-master.opt b/mysql-test/t/rpl_packet-master.opt
new file mode 100644
index 00000000000..42d4f94c999
--- /dev/null
+++ b/mysql-test/t/rpl_packet-master.opt
@@ -0,0 +1 @@
+-O max_allowed_packet=1024 -O net_buffer_length=1024
diff --git a/mysql-test/t/rpl_packet-slave.opt b/mysql-test/t/rpl_packet-slave.opt
new file mode 100644
index 00000000000..42d4f94c999
--- /dev/null
+++ b/mysql-test/t/rpl_packet-slave.opt
@@ -0,0 +1 @@
+-O max_allowed_packet=1024 -O net_buffer_length=1024
diff --git a/mysql-test/t/rpl_packet.test b/mysql-test/t/rpl_packet.test
new file mode 100644
index 00000000000..d01979a4731
--- /dev/null
+++ b/mysql-test/t/rpl_packet.test
@@ -0,0 +1,39 @@
+#
+# Check replication protocol packet size handling
+# Bug#19402 SQL close to the size of the max_allowed_packet fails on slave
+#
+
+# max-out size db name
+source include/master-slave.inc;
+
+let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________;
+disable_warnings;
+eval drop database if exists $db;
+enable_warnings;
+eval create database $db;
+
+connection master;
+select @@net_buffer_length, @@max_allowed_packet;
+disconnect master;
+
+# alas, can't use eval here; if db name changed apply the change here
+connect (master,localhost,root,,DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________);
+
+connection master;
+create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM;
+
+INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023');
+save_master_pos;
+
+connection slave;
+sync_with_master;
+eval select count(*) from `$db`.`t1` /* must be 1 */;
+
+connection master;
+eval drop database $db;
+save_master_pos;
+
+connection slave;
+sync_with_master;
+
+# End of tests
diff --git a/mysql-test/t/rpl_slave_status.test b/mysql-test/t/rpl_slave_status.test
index 985cebabe7e..b97b769d181 100644
--- a/mysql-test/t/rpl_slave_status.test
+++ b/mysql-test/t/rpl_slave_status.test
@@ -9,7 +9,7 @@ start slave;
connection master;
--disable_warnings
drop table if exists t1;
---enable_warning
+--enable_warnings
create table t1 (n int);
insert into t1 values (1);
save_master_pos;
diff --git a/mysql-test/t/rpl_trigger.test b/mysql-test/t/rpl_trigger.test
index 3c8cbb97b31..faba89e7a73 100644
--- a/mysql-test/t/rpl_trigger.test
+++ b/mysql-test/t/rpl_trigger.test
@@ -62,7 +62,7 @@ select get_lock("bug12480",2);
connection default;
create table t1 (a datetime,b datetime, c datetime);
---ignore_warnings
+--disable_warnings
drop function if exists bug12480;
--enable_warnings
@@ -423,6 +423,43 @@ DROP TABLE t2;
--sync_with_master
--connection master
+#
+# BUG#23703: DROP TRIGGER needs an IF EXISTS
+#
+
+connection master;
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1(a int, b varchar(50));
+
+-- error ER_TRG_DOES_NOT_EXIST
+drop trigger not_a_trigger;
+
+drop trigger if exists not_a_trigger;
+
+create trigger t1_bi before insert on t1
+for each row set NEW.b := "In trigger t1_bi";
+
+insert into t1 values (1, "a");
+drop trigger if exists t1_bi;
+insert into t1 values (2, "b");
+drop trigger if exists t1_bi;
+insert into t1 values (3, "c");
+
+select * from t1;
+
+save_master_pos;
+connection slave;
+sync_with_master;
+
+select * from t1;
+
+connection master;
+
+drop table t1;
#
# End of tests
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 0f096d97d25..0c82cef867f 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -2700,7 +2700,7 @@ insert into t2 values ('58013'),('58014'),('58015'),('58016');
create table t3 (a_id int(11) not null, b_id char(16) character set utf8);
insert into t3 values (123,null),(123,null),(123,null),(123,null),(123,null),(123,'58013');
--- both queries are equivalent
+# both queries are equivalent
select count(*)
from t1 inner join (t3 left join t2 on t2.id = t3.b_id) on t1.id = t3.a_id;
@@ -2940,7 +2940,7 @@ create table t2 (
insert into t1 (b,c) values (0,1), (0,1);
insert into t2 (b,c) values (0,1);
--- Row 1 should succeed. Row 2 should fail. Both fail.
+# Row 1 should succeed. Row 2 should fail. Both fail.
select t1.a, t1.b + 0, t1.c + 0, t2.a, t2.b + 0, t2.c, t2.d
from t1 left outer join t2 on t1.a = t2.c and t2.b <> 1
where t1.b <> 1 order by t1.a;
diff --git a/mysql-test/t/show_check-master.opt b/mysql-test/t/show_check-master.opt
new file mode 100644
index 00000000000..3eb98fc3d6b
--- /dev/null
+++ b/mysql-test/t/show_check-master.opt
@@ -0,0 +1 @@
+--log-slow-queries --log-long-format --log-queries-not-using-indexes
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index d162f250fd7..369ae9bff65 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -399,7 +399,8 @@ show create table t1;
drop table t1;
-# End of 4.1 tests
+--echo End of 4.1 tests
+
#
# BUG 12183 - SHOW OPEN TABLES behavior doesn't match grammar
# First we close all open tables with FLUSH tables and then we open some.
@@ -505,4 +506,16 @@ SHOW TABLES FROM no_such_database;
SHOW COLUMNS FROM no_such_table;
-# End of 5.0 tests.
+#
+# Bug #19764: SHOW commands end up in the slow log as table scans
+#
+flush status;
+show status like 'slow_queries';
+show tables;
+show status like 'slow_queries';
+# Table scan query, to ensure that slow_queries does still get incremented
+# (mysqld is started with --log-queries-not-using-indexes)
+select 1 from information_schema.tables limit 1;
+show status like 'slow_queries';
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index abb36f040d2..77bd5259eb5 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -319,7 +319,7 @@ begin
declare x int;
end|
---error 1332
+--error 1332
create procedure p()
begin
declare c condition for 1064;
@@ -1768,6 +1768,47 @@ END;
#
+# BUG#20953: create proc with a create view that uses local
+# vars/params should fail to create
+#
+# See test case for what syntax is forbidden in a view.
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT);
+
+# We do not have to drop this procedure and view because they won't be
+# created.
+--error ER_VIEW_SELECT_CLAUSE
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @a;
+--error ER_VIEW_SELECT_CLAUSE
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file";
+--error ER_VIEW_SELECT_CLAUSE
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file";
+--error ER_VIEW_SELECT_CLAUSE
+CREATE PROCEDURE bug20953()
+ CREATE VIEW v AS SELECT i FROM t1 PROCEDURE ANALYSE();
+--error ER_VIEW_SELECT_DERIVED
+CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1;
+--error ER_VIEW_SELECT_VARIABLE
+CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i;
+delimiter |;
+--error ER_VIEW_SELECT_VARIABLE
+CREATE PROCEDURE bug20953()
+BEGIN
+ DECLARE i INT;
+ CREATE VIEW v AS SELECT i;
+END |
+delimiter ;|
+--error ER_VIEW_SELECT_VARIABLE
+PREPARE stmt FROM "CREATE VIEW v AS SELECT ?";
+
+DROP TABLE t1;
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test
index b94de6236d3..cc3e3b93e06 100644
--- a/mysql-test/t/sp-prelocking.test
+++ b/mysql-test/t/sp-prelocking.test
@@ -209,7 +209,7 @@ select f3() //
call sp1() //
----------------
+# ---------------
drop procedure sp1//
drop function f3//
diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test
index 48dbd4de7aa..7cf92dc5d0d 100644
--- a/mysql-test/t/sp-vars.test
+++ b/mysql-test/t/sp-vars.test
@@ -15,6 +15,7 @@ DROP FUNCTION IF EXISTS sp_vars_check_ret1;
DROP FUNCTION IF EXISTS sp_vars_check_ret2;
DROP FUNCTION IF EXISTS sp_vars_check_ret3;
DROP FUNCTION IF EXISTS sp_vars_check_ret4;
+DROP FUNCTION IF EXISTS sp_vars_div_zero;
--enable_warnings
@@ -49,6 +50,8 @@ SELECT sp_vars_check_ret3();
SELECT sp_vars_check_ret4();
+SELECT sp_vars_div_zero();
+
# Check that changing sql_mode after creating a store procedure does not
# matter.
@@ -72,6 +75,8 @@ SELECT sp_vars_check_ret3();
SELECT sp_vars_check_ret4();
+SELECT sp_vars_div_zero();
+
# Create the procedure in TRADITIONAL mode. Check that error will be thrown on
# execution.
@@ -81,6 +86,7 @@ DROP FUNCTION sp_vars_check_ret1;
DROP FUNCTION sp_vars_check_ret2;
DROP FUNCTION sp_vars_check_ret3;
DROP FUNCTION sp_vars_check_ret4;
+DROP FUNCTION sp_vars_div_zero;
--source include/sp-vars.inc
@@ -110,6 +116,9 @@ SELECT sp_vars_check_ret3();
SELECT sp_vars_check_ret4();
+--error ER_DIVISION_BY_ZERO
+SELECT sp_vars_div_zero();
+
SET @@sql_mode = 'ansi';
#
@@ -122,6 +131,7 @@ DROP FUNCTION sp_vars_check_ret1;
DROP FUNCTION sp_vars_check_ret2;
DROP FUNCTION sp_vars_check_ret3;
DROP FUNCTION sp_vars_check_ret4;
+DROP FUNCTION sp_vars_div_zero;
###########################################################################
#
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 87d19baf888..fc6e8714a65 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -2940,11 +2940,11 @@ begin
show warnings;
end|
--disable_parsing
-show binlog events;
-show storage engines;
-show master status;
-show slave hosts;
-show slave status;
+show binlog events|
+show storage engines|
+show master status|
+show slave hosts|
+show slave status|
--enable_parsing
call bug4902()|
@@ -5630,7 +5630,10 @@ drop procedure bug16887|
# Bug#13575 SP funcs in select with distinct/group and order by can
# produce bad data
#
+# Disable warnings to allow test to run also without InnoDB
+--disable_warnings
create table t3 (f1 int, f2 varchar(3), primary key(f1)) engine=innodb|
+--enable_warnings
insert into t3 values (1,'aaa'),(2,'bbb'),(3,'ccc')|
CREATE FUNCTION bug13575 ( p1 integer )
returns varchar(3)
@@ -6420,6 +6423,170 @@ SELECT bug21493(Member_ID) FROM t3|
DROP FUNCTION bug21493|
DROP TABLE t3,t4|
+#
+# Bug#20028 Function with select return no data
+#
+
+--disable_warnings
+drop function if exists func_20028_a|
+drop function if exists func_20028_b|
+drop function if exists func_20028_c|
+drop procedure if exists proc_20028_a|
+drop procedure if exists proc_20028_b|
+drop procedure if exists proc_20028_c|
+drop table if exists table_20028|
+--enable_warnings
+
+create table table_20028 (i int)|
+
+SET @save_sql_mode=@@sql_mode|
+
+SET sql_mode=''|
+
+create function func_20028_a() returns integer
+begin
+ declare temp integer;
+ select i into temp from table_20028 limit 1;
+ return ifnull(temp, 0);
+end|
+
+create function func_20028_b() returns integer
+begin
+ return func_20028_a();
+end|
+
+create function func_20028_c() returns integer
+begin
+ declare div_zero integer;
+ set SQL_MODE='TRADITIONAL';
+ select 1/0 into div_zero;
+ return div_zero;
+end|
+
+create procedure proc_20028_a()
+begin
+ declare temp integer;
+ select i into temp from table_20028 limit 1;
+end|
+
+create procedure proc_20028_b()
+begin
+ call proc_20028_a();
+end|
+
+create procedure proc_20028_c()
+begin
+ declare div_zero integer;
+ set SQL_MODE='TRADITIONAL';
+ select 1/0 into div_zero;
+end|
+
+select func_20028_a()|
+select func_20028_b()|
+--error ER_DIVISION_BY_ZERO
+select func_20028_c()|
+call proc_20028_a()|
+call proc_20028_b()|
+--error ER_DIVISION_BY_ZERO
+call proc_20028_c()|
+
+SET sql_mode='TRADITIONAL'|
+
+drop function func_20028_a|
+drop function func_20028_b|
+drop function func_20028_c|
+drop procedure proc_20028_a|
+drop procedure proc_20028_b|
+drop procedure proc_20028_c|
+
+create function func_20028_a() returns integer
+begin
+ declare temp integer;
+ select i into temp from table_20028 limit 1;
+ return ifnull(temp, 0);
+end|
+
+create function func_20028_b() returns integer
+begin
+ return func_20028_a();
+end|
+
+create function func_20028_c() returns integer
+begin
+ declare div_zero integer;
+ set SQL_MODE='';
+ select 1/0 into div_zero;
+ return div_zero;
+end|
+
+create procedure proc_20028_a()
+begin
+ declare temp integer;
+ select i into temp from table_20028 limit 1;
+end|
+
+create procedure proc_20028_b()
+begin
+ call proc_20028_a();
+end|
+
+create procedure proc_20028_c()
+begin
+ declare div_zero integer;
+ set SQL_MODE='';
+ select 1/0 into div_zero;
+end|
+
+select func_20028_a()|
+select func_20028_b()|
+select func_20028_c()|
+call proc_20028_a()|
+call proc_20028_b()|
+call proc_20028_c()|
+
+SET @@sql_mode=@save_sql_mode|
+
+drop function func_20028_a|
+drop function func_20028_b|
+drop function func_20028_c|
+drop procedure proc_20028_a|
+drop procedure proc_20028_b|
+drop procedure proc_20028_c|
+drop table table_20028|
+
+#
+# Bug#21462 Stored procedures with no arguments require parenthesis
+#
+
+--disable_warnings
+drop procedure if exists proc_21462_a|
+drop procedure if exists proc_21462_b|
+--enable_warnings
+
+create procedure proc_21462_a()
+begin
+ select "Called A";
+end|
+
+create procedure proc_21462_b(x int)
+begin
+ select "Called B";
+end|
+
+call proc_21462_a|
+call proc_21462_a()|
+-- error ER_SP_WRONG_NO_OF_ARGS
+call proc_21462_a(1)|
+
+-- error ER_SP_WRONG_NO_OF_ARGS
+call proc_21462_b|
+-- error ER_SP_WRONG_NO_OF_ARGS
+call proc_21462_b()|
+call proc_21462_b(1)|
+
+drop procedure proc_21462_a|
+drop procedure proc_21462_b|
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/sp_notembedded.test b/mysql-test/t/sp_notembedded.test
index b087f699f86..4e18e69d3d2 100644
--- a/mysql-test/t/sp_notembedded.test
+++ b/mysql-test/t/sp_notembedded.test
@@ -19,11 +19,11 @@ begin
show grants for 'root'@'localhost';
end|
--disable_parsing
-show binlog events;
-show storage engines;
-show master status;
-show slave hosts;
-show slave status;
+show binlog events|
+show storage engines|
+show master status|
+show slave hosts|
+show slave status|
--enable_parsing
call bug4902()|
@@ -108,7 +108,7 @@ flush status|
flush query cache|
delete from t1|
drop procedure bug3583|
-drop table t1;
+drop table t1|
#
# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
diff --git a/mysql-test/t/ssl_des-master.opt b/mysql-test/t/ssl_des-master.opt
new file mode 100644
index 00000000000..0b2b8cb85ac
--- /dev/null
+++ b/mysql-test/t/ssl_des-master.opt
@@ -0,0 +1 @@
+--loose_ssl-cert=std_data/server-cert-des.pem --loose_ssl-key=std_data/server-key-des.pem
diff --git a/mysql-test/t/ssl_des.test b/mysql-test/t/ssl_des.test
new file mode 100644
index 00000000000..7cf2c920ab5
--- /dev/null
+++ b/mysql-test/t/ssl_des.test
@@ -0,0 +1,19 @@
+# Tell the server to use a DES-encrypted cert
+# then turn on ssl between the client and server
+# and run a number of standard tests
+
+-- source include/have_openssl.inc
+
+# Connect by ip to avoid turning on "ssl-verify-server-cert"
+connect (ssl_con,127.0.0.1,root,,,,$MASTER_MYPORT,SSL);
+
+# Check ssl turned on
+SHOW STATUS LIKE 'Ssl_cipher';
+
+# Source select test case
+-- source include/common-tests.inc
+
+# Check ssl turned on
+SHOW STATUS LIKE 'Ssl_cipher';
+
+
diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test
index 6ebbb53ed8e..224a7422de1 100644
--- a/mysql-test/t/strict.test
+++ b/mysql-test/t/strict.test
@@ -327,14 +327,14 @@ INSERT INTO t1 (col2) VALUES(CAST('0000-00-00' AS DATETIME));
# SQLSTATE 22007 <invalid datetime value>
--error 1292
INSERT INTO t1 (col3) VALUES(CAST('0000-10-31 15:30' AS DATETIME));
--- should return OK
--- We accept this to be a failure
+# should return OK
+# We accept this to be a failure
--error 1292
INSERT INTO t1 (col3) VALUES(CAST('2004-10-0 15:30' AS DATETIME));
--error 1292
INSERT INTO t1 (col3) VALUES(CAST('2004-0-10 15:30' AS DATETIME));
--- should return SQLSTATE 22007 <invalid datetime value>
+# should return SQLSTATE 22007 <invalid datetime value>
# deactivated because of Bug#8294
# Bug#8294 Traditional: Misleading error message for invalid CAST to DATE
@@ -422,8 +422,8 @@ INSERT INTO t1 (col2) VALUES(CONVERT('0000-00-00',DATETIME));
# SQLSTATE 22007 <invalid datetime value>
--error 1292
INSERT INTO t1 (col3) VALUES(CONVERT('0000-10-31 15:30',DATETIME));
--- should return OK
--- We accept this to be a failure
+# should return OK
+# We accept this to be a failure
--error 1292
INSERT INTO t1 (col3) VALUES(CONVERT('2004-10-0 15:30',DATETIME));
@@ -729,11 +729,11 @@ DROP TABLE t1;
CREATE TABLE t1 (col1 NUMERIC(4,2));
INSERT INTO t1 VALUES (10.55),(10.5555),(0),(-10.55),(-10.5555),(11),(1e+01);
--- Note that the +/-10.5555 is inserted as +/-10.55, not +/-10.56 !
+# Note that the +/-10.5555 is inserted as +/-10.55, not +/-10.56 !
INSERT INTO t1 VALUES ('10.55'),('10.5555'),('-10.55'),('-10.5555'),('11'),('1e+01');
--- The 2 following inserts should generate a warning, but doesn't yet
--- because NUMERIC works like DECIMAL
+# The 2 following inserts should generate a warning, but doesn't yet
+# because NUMERIC works like DECIMAL
--error 1264
INSERT INTO t1 VALUES (101.55);
--error 1264
@@ -744,8 +744,8 @@ INSERT INTO t1 VALUES (-101.55);
INSERT INTO t1 VALUES (1010.55);
--error 1264
INSERT INTO t1 VALUES (1010);
--- The 2 following inserts should generate a warning, but doesn't yet
--- because NUMERIC works like DECIMAL
+# The 2 following inserts should generate a warning, but doesn't yet
+# because NUMERIC works like DECIMAL
--error 1264
INSERT INTO t1 VALUES ('101.55');
--error 1264
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 75c1c0c0ffe..0bbbc5a793e 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -108,7 +108,7 @@ select * from t3 where a in (select a,b from t2);
-- error 1241
select * from t3 where a in (select * from t2);
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9),(1,10);
--- empty set
+# empty set
select b,max(a) as ma from t4 group by b having b < (select max(t2.a) from t2 where t2.b=t4.b);
insert into t2 values (2,10);
select b,max(a) as ma from t4 group by b having ma < (select max(t2.a) from t2 where t2.b=t4.b);
@@ -1728,7 +1728,7 @@ select (select a from t1) = (1,2);
select (1,2,3) = (select * from t1);
-- error 1241
select (select * from t1) = (1,2,3);
-drop table t1
+drop table t1;
#
# Item_int_with_ref check (BUG#10020)
@@ -2280,11 +2280,11 @@ drop table t1;
# Bug#19700: subselect returning BIGINT always returned it as SIGNED
#
CREATE TABLE t1 (i BIGINT UNSIGNED);
-INSERT INTO t1 VALUES (10000000000000000000); -- > MAX SIGNED BIGINT 9323372036854775807
+INSERT INTO t1 VALUES (10000000000000000000); # > MAX SIGNED BIGINT 9323372036854775807
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (i BIGINT UNSIGNED);
-INSERT INTO t2 VALUES (10000000000000000000); -- same as first table
+INSERT INTO t2 VALUES (10000000000000000000); # same as first table
INSERT INTO t2 VALUES (1);
/* simple test */
diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test
index fa44b454b4f..c50b641b7e2 100644
--- a/mysql-test/t/system_mysql_db_fix.test
+++ b/mysql-test/t/system_mysql_db_fix.test
@@ -38,7 +38,7 @@ CREATE TABLE db (
KEY User (User)
)
type=ISAM;
---enable-warnings
+--enable_warnings
INSERT INTO db VALUES ('%','test', '','Y','Y','Y','Y','Y','Y');
INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y');
@@ -56,7 +56,7 @@ CREATE TABLE host (
PRIMARY KEY Host (Host,Db)
)
type=ISAM;
---enable-warnings
+--enable_warnings
--disable_warnings
CREATE TABLE user (
@@ -75,7 +75,7 @@ CREATE TABLE user (
PRIMARY KEY Host (Host,User)
)
type=ISAM;
---enable-warnings
+--enable_warnings
INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y');
INSERT INTO user VALUES ('localhost','', '','N','N','N','N','N','N','N','N','N');
diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test
index 34bbb365c70..157b18f57fa 100644
--- a/mysql-test/t/timezone.test
+++ b/mysql-test/t/timezone.test
@@ -52,11 +52,12 @@ INSERT INTO t1 (ts) VALUES ('2003-03-30 01:59:59'),
DROP TABLE t1;
#
-# Test for fix for Bug#2523
+# Test for fix for Bug#2523 Check that boundary dates are processed
+# correctly.
#
select unix_timestamp('1970-01-01 01:00:00'),
unix_timestamp('1970-01-01 01:00:01'),
- unix_timestamp('2038-01-01 00:59:59'),
- unix_timestamp('2038-01-01 01:00:00');
+ unix_timestamp('2038-01-19 04:14:07'),
+ unix_timestamp('2038-01-19 04:14:08');
# End of 4.1 tests
diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test
index bfc909d6995..75e5d4bfe81 100644
--- a/mysql-test/t/timezone2.test
+++ b/mysql-test/t/timezone2.test
@@ -113,21 +113,21 @@ create table t1 (ts timestamp);
set time_zone='UTC';
insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'),
('1970-01-01 00:00:00'),('1970-01-01 00:00:01'),
- ('2037-12-31 23:59:59'),('2038-01-01 00:00:00');
+ ('2038-01-19 03:14:07'),('2038-01-19 03:14:08');
select * from t1;
delete from t1;
# MET time zone has range shifted by one hour
set time_zone='MET';
insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'),
('1970-01-01 01:00:00'),('1970-01-01 01:00:01'),
- ('2038-01-01 00:59:59'),('2038-01-01 01:00:00');
+ ('2038-01-19 04:14:07'),('2038-01-19 04:14:08');
select * from t1;
delete from t1;
# same for +01:30 time zone
set time_zone='+01:30';
insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'),
('1970-01-01 01:30:00'),('1970-01-01 01:30:01'),
- ('2038-01-01 01:29:59'),('2038-01-01 01:30:00');
+ ('2038-01-19 04:44:07'),('2038-01-19 04:44:08');
select * from t1;
drop table t1;
@@ -177,8 +177,8 @@ select convert_tz('2003-10-26 01:00:00', 'MET', 'UTC');
select convert_tz('2003-10-26 02:00:00', 'MET', 'UTC');
select convert_tz('2003-10-26 02:59:59', 'MET', 'UTC');
select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC');
-select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC');
-select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC');
+select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC');
+select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC');
select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC');
# Let us test variable time zone argument
diff --git a/mysql-test/t/timezone4-master.opt b/mysql-test/t/timezone4-master.opt
new file mode 100644
index 00000000000..d1ab6207933
--- /dev/null
+++ b/mysql-test/t/timezone4-master.opt
@@ -0,0 +1 @@
+--timezone=GMT+10
diff --git a/mysql-test/t/timezone4.test b/mysql-test/t/timezone4.test
new file mode 100644
index 00000000000..d7372c75d5a
--- /dev/null
+++ b/mysql-test/t/timezone4.test
@@ -0,0 +1,13 @@
+#
+# Tests for time functions. The difference from func_time test is the
+# timezone. In func_time it's GMT-3. In our case it's GMT+10
+#
+
+#
+# Test for bug bug #9191 "TIMESTAMP/from_unixtime() no longer accepts 2^31-1"
+#
+
+select from_unixtime(0);
+# check 0 boundary
+select unix_timestamp('1969-12-31 14:00:01');
+
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index 969047929b9..ae01a4b2c3d 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -1275,7 +1275,6 @@ INSERT INTO t1 VALUES (@x);
SELECT @x;
SET @x=2;
---error ER_DIVISION_BY_ZERO
UPDATE t1 SET i1 = @x;
SELECT @x;
@@ -1286,7 +1285,6 @@ INSERT INTO t1 VALUES (@x);
SELECT @x;
SET @x=4;
---error ER_DIVISION_BY_ZERO
UPDATE t1 SET i1 = @x;
SELECT @x;
@@ -1421,6 +1419,67 @@ CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890
DROP TABLE t1;
DROP TABLE t2;
+#
+# Bug#20028 Function with select return no data
+#
+
+--disable_warnings
+drop table if exists t1;
+drop table if exists t2;
+drop table if exists t3;
+drop table if exists t4;
+--enable_warnings
+
+SET @save_sql_mode=@@sql_mode;
+
+delimiter |;
+SET sql_mode='TRADITIONAL'|
+create table t1 (id int(10) not null primary key, v int(10) )|
+create table t2 (id int(10) not null primary key, v int(10) )|
+create table t3 (id int(10) not null primary key, v int(10) )|
+create table t4 (c int)|
+
+create trigger t4_bi before insert on t4 for each row set @t4_bi_called:=1|
+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|
+select 1/0 from t1|
+
+create trigger t1_bi before insert on t1 for each row set @a:=1/0|
+
+insert into t1 values(20, 20)|
+
+drop trigger t1_bi|
+create trigger t1_bi before insert on t1 for each row
+begin
+ insert into t2 values (new.id, new.v);
+ update t2 set v=v+1 where id= new.id;
+ replace t3 values (new.id, 0);
+ update t2, t3 set t2.v=new.v, t3.v=new.v where t2.id=t3.id;
+ create temporary table t5 select * from t1;
+ delete from t5;
+ insert into t5 select * from t1;
+ insert into t4 values (0);
+ set @check= (select count(*) from t5);
+ update t4 set c= @check;
+ drop temporary table t5;
+
+ set @a:=1/0;
+end|
+
+set @check=0, @t4_bi_called=0, @t4_bu_called=0|
+insert into t1 values(30, 30)|
+select @check, @t4_bi_called, @t4_bu_called|
+
+delimiter ;|
+
+SET @@sql_mode=@save_sql_mode;
+
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
#
# Bug#20670 "UPDATE using key and invoking trigger that modifies
@@ -1441,4 +1500,52 @@ select * from t1;
drop table t1;
+#
+# Bug #23651 "Server crashes when trigger which uses stored function
+# invoked from different connections".
+#
+--disable_warnings
+drop table if exists t1;
+drop function if exists f1;
+--enable_warnings
+create table t1 (i int);
+create function f1() returns int return 10;
+create trigger t1_bi before insert on t1 for each row set @a:= f1() + 10;
+insert into t1 values ();
+select @a;
+connection addconroot1;
+insert into t1 values ();
+select @a;
+connection default;
+drop table t1;
+drop function f1;
+
+#
+# Bug#23703: DROP TRIGGER needs an IF EXISTS
+#
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1(a int, b varchar(50));
+
+-- error ER_TRG_DOES_NOT_EXIST
+drop trigger not_a_trigger;
+
+drop trigger if exists not_a_trigger;
+
+create trigger t1_bi before insert on t1
+for each row set NEW.b := "In trigger t1_bi";
+
+insert into t1 values (1, "a");
+drop trigger if exists t1_bi;
+insert into t1 values (2, "b");
+drop trigger if exists t1_bi;
+insert into t1 values (3, "c");
+
+select * from t1;
+
+drop table t1;
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test
index d46ba667665..48ad24ff6b7 100644
--- a/mysql-test/t/type_bit.test
+++ b/mysql-test/t/type_bit.test
@@ -261,4 +261,15 @@ insert into t1 (b, a) values ('2', '1');
select hex(a), b from t1;
drop table t1;
+#
+# type was not properly initalized, which caused key_copy to fail
+#
+
+create table t1(bit_field bit(2), int_field int, key a(bit_field));
+insert into t1 values (1,2);
+handler t1 open as t1;
+handler t1 read a=(1);
+handler t1 close;
+drop table t1;
+
--echo End of 5.0 tests
diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test
index 12da41dcfd5..f315e88fd0e 100644
--- a/mysql-test/t/type_newdecimal.test
+++ b/mysql-test/t/type_newdecimal.test
@@ -613,7 +613,7 @@ select truncate(99.999999999999999999999999999999999999,31);
#-- should return 99.9999999999999999999999999999999
#
select truncate(99999999999999999999999999999999999999,-31);
--- should return 90000000000000000000000000000000
+# should return 90000000000000000000000000000000
#
#-- 6. Set functions (AVG, SUM, COUNT) should work.
#
@@ -810,7 +810,7 @@ select 1 / 0;
#BUG#6048 Stored procedure causes operating system reboot
#BUG#6053 DOUBLE PRECISION literal
--- Tests from 'traditional' mode tests
+# Tests from 'traditional' mode tests
#
set sql_mode='ansi,traditional';
#
@@ -1000,9 +1000,9 @@ drop table t1;
#
# Bug 12938 (arithmetic loop's zero)
#
---disable-warnings
+--disable_warnings
drop procedure if exists wg2;
---enable-warnings
+--enable_warnings
delimiter //;
create procedure wg2()
begin
@@ -1109,10 +1109,14 @@ select i, count(distinct j) from t1 group by i;
select i+0.0 as i2, count(distinct j) from t1 group by i2;
drop table t1;
-
create table t1(f1 decimal(20,6));
insert into t1 values (CAST('10:11:12' AS date) + interval 14 microsecond);
insert into t1 values (CAST('10:11:12' AS time));
select * from t1;
drop table t1;
+#
+# Bug #8663 (cant use bigint as input to CAST)
+#
+select cast(19999999999999999999 as unsigned);
+
diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test
index 439e98471b2..7b87a388c56 100644
--- a/mysql-test/t/type_varchar.test
+++ b/mysql-test/t/type_varchar.test
@@ -187,3 +187,13 @@ left join t3 on t1.id=t3.id order by t3.id;
--disable_metadata
--enable_ps_protocol
drop table t1, t2, t3;
+
+#
+# Bug #11927: Warnings shown for CAST( chr as signed) but not (chr + 0)
+#
+CREATE TABLE t1 (a CHAR(2));
+INSERT INTO t1 VALUES (10), (50), (30), ('1a'), (60), ('t');
+SELECT a,(a + 0) FROM t1 ORDER BY a;
+SELECT a,(a DIV 2) FROM t1 ORDER BY a;
+SELECT a,CAST(a AS SIGNED) FROM t1 ORDER BY a;
+DROP TABLE t1;
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 644ca506eba..65ca1b2c1b7 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -144,6 +144,8 @@ select @@version;
--replace_column 1 #
select @@global.version;
+--echo End of 4.1 tests
+
# Bug #6598: problem with cast(NULL as signed integer);
#
@@ -210,4 +212,10 @@ select @var:=f2 from t1 group by f1 order by f2 desc limit 1;
select @var;
drop table t1;
-# End of 4.1 tests
+#
+# Bug#19024 - SHOW COUNT(*) WARNINGS not return Errors
+#
+--error 1064
+insert into city 'blah';
+SHOW COUNT(*) WARNINGS;
+SHOW COUNT(*) ERRORS;
diff --git a/mysql-test/t/utils.sh b/mysql-test/t/utils.sh
new file mode 100644
index 00000000000..b3f4744947d
--- /dev/null
+++ b/mysql-test/t/utils.sh
@@ -0,0 +1,55 @@
+###########################################################################
+#
+# 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/t/view.test b/mysql-test/t/view.test
index 21080dd00cc..8473458ae15 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -23,8 +23,11 @@ create table t1 (a int, b int);
insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
# view with variable
--- error 1351
+-- error ER_VIEW_SELECT_VARIABLE
create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
+-- error ER_VIEW_SELECT_VARIABLE
+create view v1 (c,d) as select a,b from t1
+ where a = @@global.max_user_connections;
# simple view
create view v1 (c) as select b+1 from t1;
@@ -487,19 +490,6 @@ drop view v1;
create view v1 (a,a) as select 'a','a';
#
-# SP variables inside view test
-#
---disable_warnings
-drop procedure if exists p1;
---enable_warnings
-delimiter //;
-create procedure p1 () begin declare v int; create view v1 as select v; end;//
-delimiter ;//
--- error 1351
-call p1();
-drop procedure p1;
-
-#
# updatablity should be transitive
#
create table t1 (col1 int,col2 char(22));
@@ -820,6 +810,8 @@ create view v1 as select 5 into outfile 'ttt';
create table t1 (a int);
-- error 1350
create view v1 as select a from t1 procedure analyse();
+-- error ER_VIEW_SELECT_DERIVED
+create view v1 as select 1 from (select 1) as d1;
drop table t1;
#
@@ -1801,7 +1793,7 @@ drop table t1;
# underlying tables (BUG#6443)
#
set sql_mode='strict_all_tables';
-CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL) ENGINE = INNODB;
+CREATE TABLE t1 (col1 INT NOT NULL, col2 INT NOT NULL);
CREATE VIEW v1 (vcol1) AS SELECT col1 FROM t1;
CREATE VIEW v2 (vcol1) AS SELECT col1 FROM t1 WHERE col2 > 2;
-- error 1364
@@ -1857,7 +1849,7 @@ drop table t1;
#
# Test for bug #11771: wrong query_id in SELECT * FROM <view>
#
-CREATE TABLE t1 (f1 char) ENGINE = innodb;
+CREATE TABLE t1 (f1 char);
INSERT INTO t1 VALUES ('A');
CREATE VIEW v1 AS SELECT * FROM t1;
@@ -2597,6 +2589,7 @@ SELECT * FROM t2;
DROP VIEW v1;
DROP TABLE t1,t2;
+
#
# Bug#16110: insert permitted into view col w/o default value
#
@@ -2880,6 +2873,40 @@ SHOW CREATE VIEW v1;
DROP VIEW v1;
DROP TABLE t1, t2;
+
+#
+# Bug#19111: TRIGGERs selecting from a VIEW on the firing base table
+# fail
+#
+# Allow to select from a view on a table being modified in a trigger
+# and stored function, since plain select is allowed there.
+#
+--disable_warnings
+DROP FUNCTION IF EXISTS f1;
+DROP VIEW IF EXISTS v1;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT);
+INSERT INTO t1 VALUES (1);
+
+CREATE VIEW v1 AS SELECT MAX(i) FROM t1;
+
+# Plain 'SET NEW.i = (SELECT MAX(i) FROM t1) + 1' works, so select
+# from a view should work too.
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ SET NEW.i = (SELECT * FROM v1) + 1;
+INSERT INTO t1 VALUES (1);
+
+# Plain 'RETURN (SELECT MAX(i) FROM t1)' works in INSERT, so select
+# from a view should work too.
+CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1);
+UPDATE t1 SET i= f1();
+
+DROP FUNCTION f1;
+DROP VIEW v1;
+DROP TABLE t1;
+
#
# Bug #16813 (WITH CHECK OPTION doesn't work with UPDATE)
#
@@ -2894,4 +2921,43 @@ UPDATE v1 SET val=6 WHERE id=2;
DROP VIEW v1;
DROP TABLE t1;
+
+#
+# BUG#22584: last_insert_id not updated after inserting a record
+# through a updatable view
+#
+# We still do not update LAST_INSERT_ID if AUTO_INCREMENT column is
+# not accessible through a view. However, we do not reset the value
+# of LAST_INSERT_ID, but keep it unchanged.
+#
+--disable_warnings
+DROP VIEW IF EXISTS v1, v2;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT);
+CREATE VIEW v1 AS SELECT j FROM t1;
+CREATE VIEW v2 AS SELECT * FROM t1;
+
+INSERT INTO t1 (j) VALUES (1);
+SELECT LAST_INSERT_ID();
+
+INSERT INTO v1 (j) VALUES (2);
+--echo # LAST_INSERT_ID() should not change.
+SELECT LAST_INSERT_ID();
+
+INSERT INTO v2 (j) VALUES (3);
+--echo # LAST_INSERT_ID() should be updated.
+SELECT LAST_INSERT_ID();
+
+INSERT INTO v1 (j) SELECT j FROM t1;
+--echo # LAST_INSERT_ID() should not change.
+SELECT LAST_INSERT_ID();
+
+SELECT * FROM t1;
+
+DROP VIEW v1, v2;
+DROP TABLE t1;
+
+
--echo End of 5.0 tests.
diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test
index c75e5422de7..6bb34a9fcef 100644
--- a/mysql-test/t/view_grant.test
+++ b/mysql-test/t/view_grant.test
@@ -26,7 +26,7 @@ grant create view,select on test.* to mysqltest_1@localhost;
connect (user1,localhost,mysqltest_1,,test);
connection user1;
--- error ER_SPECIFIC_ACCESS_DENIED
+-- error ER_SPECIFIC_ACCESS_DENIED_ERROR
create definer=root@localhost view v1 as select * from mysqltest.t1;
create view v1 as select * from mysqltest.t1;
# try to modify view without DROP privilege on it
@@ -800,7 +800,7 @@ DROP DATABASE mysqltest1;
CREATE TABLE t1 (a INT PRIMARY KEY);
INSERT INTO t1 VALUES (1), (2), (3);
CREATE DEFINER = 'no-such-user'@localhost VIEW v AS SELECT a from t1;
---warning 1448
+#--warning 1448
SHOW CREATE VIEW v;
--error 1449
SELECT * FROM v;
@@ -927,4 +927,41 @@ DROP VIEW v2;
DROP VIEW v1;
DROP USER mysqltest_u1@localhost;
+#
+# Bug#17254: Error for DEFINER security on VIEW provides too much info
+#
+connect (root,localhost,root,,);
+connection root;
+CREATE DATABASE db17254;
+USE db17254;
+CREATE TABLE t1 (f1 INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE USER def_17254@localhost;
+GRANT SELECT ON db17254.* TO def_17254@localhost;
+CREATE USER inv_17254@localhost;
+GRANT SELECT ON db17254.t1 TO inv_17254@localhost;
+GRANT CREATE VIEW ON db17254.* TO def_17254@localhost;
+
+connect (def,localhost,def_17254,,db17254);
+connection def;
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+connection root;
+DROP USER def_17254@localhost;
+
+connect (inv,localhost,inv_17254,,db17254);
+connection inv;
+--echo for a user
+--error 1142
+SELECT * FROM v1;
+
+connection root;
+--echo for a superuser
+--error 1449
+SELECT * FROM v1;
+DROP USER inv_17254@localhost;
+DROP DATABASE db17254;
+disconnect def;
+disconnect inv;
+
# End of 5.0 tests.
diff --git a/mysql-test/t/wait_for_process.sh b/mysql-test/t/wait_for_process.sh
index df0f4a17e3a..4c2d89cfea6 100755
--- a/mysql-test/t/wait_for_process.sh
+++ b/mysql-test/t/wait_for_process.sh
@@ -2,34 +2,40 @@
###########################################################################
-pid_path="$1"
-total_attempts="$2"
-event="$3"
+# 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.
-case "$3" in
- started)
- check_fn='check_started';
- ;;
+###########################################################################
- stopped)
- check_fn='check_stopped';
- ;;
+basename=`basename "$0"`
+dirname=`dirname "$0"`
- *)
- echo "Error: invalid third argument ('started' or 'stopped' expected)."
- exit 0
-esac
+###########################################################################
+
+. "$dirname/utils.sh"
###########################################################################
check_started()
{
- [ ! -r "$pid_path" ] && return 1
+ 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."
- [ $? -eq 0 -a "$original_pid" = "$new_pid" ] && return 1
+ 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
}
@@ -37,30 +43,72 @@ check_started()
check_stopped()
{
- [ -r "$pid_path" ] && return 1
+ 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.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
- echo "Success: the process has been $event."
- exit 0
+ 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
-echo "Error: the process has not been $event in $total_attempts secs."
-exit 0
-
+log_error "The process has not been $event in $total_attempts secs."
+quit 0
diff --git a/mysql-test/t/wait_for_socket.sh b/mysql-test/t/wait_for_socket.sh
new file mode 100755
index 00000000000..1bce74dfd3a
--- /dev/null
+++ b/mysql-test/t/wait_for_socket.sh
@@ -0,0 +1,94 @@
+#!/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.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="--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/t/wait_timeout.test b/mysql-test/t/wait_timeout.test
index 195d1a5d3f2..67ed8fedfeb 100644
--- a/mysql-test/t/wait_timeout.test
+++ b/mysql-test/t/wait_timeout.test
@@ -52,7 +52,7 @@ select 2;
select 3;
# Disconnect so that we will not be confused by a future abort from this
# connection.
-disconnect default
+disconnect default;
#
# Do the same test as above on a TCP connection
diff --git a/mysys/base64.c b/mysys/base64.c
index b29c8ff8360..2d1b7f2aeba 100644
--- a/mysys/base64.c
+++ b/mysys/base64.c
@@ -40,7 +40,7 @@ base64_needed_encoded_length(int length_of_data)
int
base64_needed_decoded_length(int length_of_encoded_data)
{
- return ceil(length_of_encoded_data * 3 / 4);
+ return (int) ceil(length_of_encoded_data * 3 / 4);
}
diff --git a/mysys/charset.c b/mysys/charset.c
index 64b15fab0c2..d10a580ae4e 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -312,7 +312,7 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
{
char *buf;
int fd;
- uint len;
+ uint len, tmp_len;
MY_STAT stat_info;
if (!my_stat(filename, &stat_info, MYF(myflags)) ||
@@ -321,12 +321,11 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
return TRUE;
if ((fd=my_open(filename,O_RDONLY,myflags)) < 0)
- {
- my_free(buf,myflags);
- return TRUE;
- }
- len=read(fd,buf,len);
+ goto error;
+ tmp_len=my_read(fd, buf, len, myflags);
my_close(fd,myflags);
+ if (tmp_len != len)
+ goto error;
if (my_parse_charset_xml(buf,len,add_collation))
{
@@ -340,6 +339,10 @@ static my_bool my_read_charset_file(const char *filename, myf myflags)
my_free(buf, myflags);
return FALSE;
+
+error:
+ my_free(buf, myflags);
+ return TRUE;
}
diff --git a/mysys/default.c b/mysys/default.c
index 540968d4ba0..d93f4135e73 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -484,7 +484,7 @@ static int search_default_file(Process_option_func opt_handler,
my_bool have_ext= fn_ext(config_file)[0] != 0;
const char **exts_to_use= have_ext ? empty_list : f_extensions;
- for (ext= (char**) exts_to_use; *ext; *ext++)
+ for (ext= (char**) exts_to_use; *ext; ext++)
{
int error;
if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
@@ -672,7 +672,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
ext= fn_ext(search_file->name);
/* check extension */
- for (tmp_ext= (char**) f_extensions; *tmp_ext; *tmp_ext++)
+ for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
{
if (!strcmp(ext, *tmp_ext))
break;
@@ -861,7 +861,7 @@ void my_print_default_files(const char *conf_file)
{
for (dirs=default_directories ; *dirs; dirs++)
{
- for (ext= (char**) exts_to_use; *ext; *ext++)
+ for (ext= (char**) exts_to_use; *ext; ext++)
{
const char *pos;
char *end;
diff --git a/mysys/hash.c b/mysys/hash.c
index 99479ef6769..9a268a7e218 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -53,7 +53,7 @@ _hash_init(HASH *hash,CHARSET_INFO *charset,
void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
{
DBUG_ENTER("hash_init");
- DBUG_PRINT("enter",("hash: 0x%lx size: %d",hash,size));
+ DBUG_PRINT("enter",("hash: 0x%lx size: %d", (long) hash, size));
hash->records=0;
if (my_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0))
@@ -109,7 +109,7 @@ static inline void hash_free_elements(HASH *hash)
void hash_free(HASH *hash)
{
DBUG_ENTER("hash_free");
- DBUG_PRINT("enter",("hash: 0x%lxd",hash));
+ DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash));
hash_free_elements(hash);
hash->free= 0;
@@ -129,7 +129,7 @@ void hash_free(HASH *hash)
void my_hash_reset(HASH *hash)
{
DBUG_ENTER("my_hash_reset");
- DBUG_PRINT("enter",("hash: 0x%lxd",hash));
+ DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash));
hash_free_elements(hash);
reset_dynamic(&hash->array);
@@ -644,7 +644,8 @@ my_bool hash_check(HASH *hash)
if ((rec_link=hash_rec_mask(hash,hash_info,blength,records)) != i)
{
DBUG_PRINT("error",
- ("Record in wrong link at %d: Start %d Record: 0x%lx Record-link %d", idx,i,hash_info->data,rec_link));
+ ("Record in wrong link at %d: Start %d Record: 0x%lx Record-link %d",
+ idx, i, (long) hash_info->data, rec_link));
error=1;
}
else
@@ -655,12 +656,12 @@ my_bool hash_check(HASH *hash)
}
if (found != records)
{
- DBUG_PRINT("error",("Found %ld of %ld records"));
+ DBUG_PRINT("error",("Found %u of %u records", found, records));
error=1;
}
if (records)
DBUG_PRINT("info",
- ("records: %ld seeks: %d max links: %d hitrate: %.2f",
+ ("records: %u seeks: %d max links: %d hitrate: %.2f",
records,seek,max_links,(float) seek / (float) records));
return error;
}
diff --git a/mysys/list.c b/mysys/list.c
index 0e55c9399f5..c4ce5b5e36f 100644
--- a/mysys/list.c
+++ b/mysys/list.c
@@ -28,7 +28,7 @@
LIST *list_add(LIST *root, LIST *element)
{
DBUG_ENTER("list_add");
- DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", root, element));
+ DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", (long) root, (long) element));
if (root)
{
if (root->prev) /* If add in mid of list */
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index b1cf940d70d..e0962999015 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -332,7 +332,11 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
{
info->read_end=info->write_pos;
info->end_of_file=my_b_tell(info);
- info->seek_not_done=1;
+ /*
+ Trigger a new seek only if we have a valid
+ file handle.
+ */
+ info->seek_not_done= (info->file != -1);
}
else if (type == WRITE_CACHE)
{
@@ -441,11 +445,24 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
/* pos_in_file always point on where info->buffer was read */
pos_in_file=info->pos_in_file+(uint) (info->read_end - info->buffer);
+
+ /*
+ Whenever a function which operates on IO_CACHE flushes/writes
+ some part of the IO_CACHE to disk it will set the property
+ "seek_not_done" to indicate this to other functions operating
+ on the IO_CACHE.
+ */
if (info->seek_not_done)
- { /* File touched, do seek */
- VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
+ {
+ if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))
+ == MY_FILEPOS_ERROR)
+ {
+ info->error= -1;
+ DBUG_RETURN(1);
+ }
info->seek_not_done=0;
}
+
diff_length=(uint) (pos_in_file & (IO_SIZE-1));
if (Count >= (uint) (IO_SIZE+(IO_SIZE-diff_length)))
{ /* Fill first intern buffer */
@@ -577,7 +594,8 @@ void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare,
DBUG_ENTER("init_io_cache_share");
DBUG_PRINT("io_cache_share", ("read_cache: 0x%lx share: 0x%lx "
"write_cache: 0x%lx threads: %u",
- read_cache, cshare, write_cache, num_threads));
+ (long) read_cache, (long) cshare,
+ (long) write_cache, num_threads));
DBUG_ASSERT(num_threads > 1);
DBUG_ASSERT(read_cache->type == READ_CACHE);
@@ -639,7 +657,7 @@ void remove_io_thread(IO_CACHE *cache)
pthread_mutex_lock(&cshare->mutex);
DBUG_PRINT("io_cache_share", ("%s: 0x%lx",
(cache == cshare->source_cache) ?
- "writer" : "reader", cache));
+ "writer" : "reader", (long) cache));
/* Remove from share. */
total= --cshare->total_threads;
@@ -715,7 +733,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos)
cshare->running_threads--;
DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u",
(cache == cshare->source_cache) ?
- "writer" : "reader", cache, (ulong) pos,
+ "writer" : "reader", (long) cache, (ulong) pos,
cshare->running_threads));
if (cshare->source_cache)
@@ -854,7 +872,7 @@ static void unlock_io_cache(IO_CACHE *cache)
DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u",
(cache == cshare->source_cache) ?
"writer" : "reader",
- cache, (ulong) cshare->pos_in_file,
+ (long) cache, (ulong) cshare->pos_in_file,
cshare->total_threads));
cshare->running_threads= cshare->total_threads;
@@ -946,8 +964,22 @@ int _my_b_read_r(register IO_CACHE *cache, byte *Buffer, uint Count)
len= 0;
else
{
- if (cache->seek_not_done) /* File touched, do seek */
- VOID(my_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0)));
+ /*
+ Whenever a function which operates on IO_CACHE flushes/writes
+ some part of the IO_CACHE to disk it will set the property
+ "seek_not_done" to indicate this to other functions operating
+ on the IO_CACHE.
+ */
+ if (cache->seek_not_done)
+ {
+ if (my_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0))
+ == MY_FILEPOS_ERROR)
+ {
+ cache->error= -1;
+ unlock_io_cache(cache);
+ DBUG_RETURN(1);
+ }
+ }
len= (int) my_read(cache->file, cache->buffer, length, cache->myflags);
}
DBUG_PRINT("io_cache_share", ("read %d bytes", len));
@@ -1049,11 +1081,16 @@ static void copy_to_read_buffer(IO_CACHE *write_cache,
/*
- Do sequential read from the SEQ_READ_APPEND cache
- we do this in three stages:
+ Do sequential read from the SEQ_READ_APPEND cache.
+
+ We do this in three stages:
- first read from info->buffer
- then if there are still data to read, try the file descriptor
- afterwards, if there are still data to read, try append buffer
+
+ RETURNS
+ 0 Success
+ 1 Failed to read
*/
int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
@@ -1081,7 +1118,13 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count)
With read-append cache we must always do a seek before we read,
because the write could have moved the file pointer astray
*/
- VOID(my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)));
+ if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))
+ == MY_FILEPOS_ERROR)
+ {
+ info->error= -1;
+ unlock_append_buffer(info);
+ return (1);
+ }
info->seek_not_done=0;
diff_length=(uint) (pos_in_file & (IO_SIZE-1));
@@ -1197,6 +1240,21 @@ read_append_buffer:
#ifdef HAVE_AIOWAIT
+/*
+ Read from the IO_CACHE into a buffer and feed asynchronously
+ from disk when needed.
+
+ SYNOPSIS
+ _my_b_async_read()
+ info IO_CACHE pointer
+ Buffer Buffer to retrieve count bytes from file
+ Count Number of bytes to read into Buffer
+
+ RETURN VALUE
+ -1 An error has occurred; my_errno is set.
+ 0 Success
+ 1 An error has occurred; IO_CACHE to error state.
+*/
int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
{
uint length,read_length,diff_length,left_length,use_length,org_Count;
@@ -1287,13 +1345,20 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count)
info->error=(int) (read_length+left_length);
return 1;
}
- VOID(my_seek(info->file,next_pos_in_file,MY_SEEK_SET,MYF(0)));
+
+ if (my_seek(info->file,next_pos_in_file,MY_SEEK_SET,MYF(0))
+ == MY_FILEPOS_ERROR)
+ {
+ info->error= -1;
+ return (1);
+ }
+
read_length=IO_SIZE*2- (uint) (next_pos_in_file & (IO_SIZE-1));
if (Count < read_length)
{ /* Small block, read to cache */
if ((read_length=my_read(info->file,info->request_pos,
read_length, info->myflags)) == (uint) -1)
- return info->error= -1;
+ return info->error= -1;
use_length=min(Count,read_length);
memcpy(Buffer,info->request_pos,(size_t) use_length);
info->read_pos=info->request_pos+Count;
@@ -1380,7 +1445,15 @@ int _my_b_get(IO_CACHE *info)
return (int) (uchar) buff;
}
- /* Returns != 0 if error on write */
+/*
+ Write a byte buffer to IO_CACHE and flush to disk
+ if IO_CACHE is full.
+
+ RETURN VALUE
+ 1 On error on write
+ 0 On success
+ -1 On error; my_errno contains error code.
+*/
int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
{
@@ -1404,8 +1477,18 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
{ /* Fill first intern buffer */
length=Count & (uint) ~(IO_SIZE-1);
if (info->seek_not_done)
- { /* File touched, do seek */
- VOID(my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)));
+ {
+ /*
+ Whenever a function which operates on IO_CACHE flushes/writes
+ some part of the IO_CACHE to disk it will set the property
+ "seek_not_done" to indicate this to other functions operating
+ on the IO_CACHE.
+ */
+ if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)))
+ {
+ info->error= -1;
+ return (1);
+ }
info->seek_not_done=0;
}
if (my_write(info->file,Buffer,(uint) length,info->myflags | MY_NABP))
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 11e27bb19ad..d658e6fe055 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -418,9 +418,9 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
DBUG_PRINT("exit",
("disk_blocks: %d block_root: 0x%lx hash_entries: %d\
hash_root: 0x%lx hash_links: %d hash_link_root: 0x%lx",
- keycache->disk_blocks, keycache->block_root,
- keycache->hash_entries, keycache->hash_root,
- keycache->hash_links, keycache->hash_link_root));
+ keycache->disk_blocks, (long) keycache->block_root,
+ keycache->hash_entries, (long) keycache->hash_root,
+ keycache->hash_links, (long) keycache->hash_link_root));
bzero((gptr) keycache->changed_blocks,
sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH);
bzero((gptr) keycache->file_blocks,
@@ -633,7 +633,7 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
{
DBUG_ENTER("end_key_cache");
- DBUG_PRINT("enter", ("key_cache: 0x%lx", keycache));
+ DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
if (!keycache->key_cache_inited)
DBUG_VOID_RETURN;
@@ -652,7 +652,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
keycache->blocks_changed= 0;
}
- DBUG_PRINT("status", ("used: %d changed: %d w_requests: %lu "
+ DBUG_PRINT("status", ("used: %lu changed: %lu w_requests: %lu "
"writes: %lu r_requests: %lu reads: %lu",
keycache->blocks_used, keycache->global_blocks_changed,
(ulong) keycache->global_cache_w_requests,
@@ -1085,7 +1085,7 @@ static void unreg_request(KEY_CACHE *keycache,
if (block->temperature == BLOCK_WARM)
keycache->warm_blocks--;
block->temperature= BLOCK_HOT;
- KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks=%u",
+ KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu",
keycache->warm_blocks));
}
link_block(keycache, block, hot, (my_bool)at_end);
@@ -1104,7 +1104,7 @@ static void unreg_request(KEY_CACHE *keycache,
keycache->warm_blocks++;
block->temperature= BLOCK_WARM;
}
- KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks=%u",
+ KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu",
keycache->warm_blocks));
}
}
@@ -1352,11 +1352,11 @@ static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
DBUG_ENTER("find_key_block");
KEYCACHE_THREAD_TRACE("find_key_block:begin");
- DBUG_PRINT("enter", ("fd: %u pos %lu wrmode: %lu",
- (uint) file, (ulong) filepos, (uint) wrmode));
- KEYCACHE_DBUG_PRINT("find_key_block", ("fd: %u pos: %lu wrmode: %lu",
- (uint) file, (ulong) filepos,
- (uint) wrmode));
+ DBUG_PRINT("enter", ("fd: %d pos: %lu wrmode: %d",
+ file, (ulong) filepos, wrmode));
+ KEYCACHE_DBUG_PRINT("find_key_block", ("fd: %d pos: %lu wrmode: %d",
+ file, (ulong) filepos,
+ wrmode));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache2",
test_key_cache(keycache, "start of find_key_block", 0););
@@ -1646,8 +1646,8 @@ restart:
KEYCACHE_DBUG_ASSERT(page_status != -1);
*page_st=page_status;
KEYCACHE_DBUG_PRINT("find_key_block",
- ("fd: %u pos %lu block->status %u page_status %lu",
- (uint) file, (ulong) filepos, block->status,
+ ("fd: %d pos: %lu block->status: %u page_status: %u",
+ file, (ulong) filepos, block->status,
(uint) page_status));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
@@ -2338,7 +2338,7 @@ static int flush_key_blocks_int(KEY_CACHE *keycache,
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
int last_errno= 0;
DBUG_ENTER("flush_key_blocks_int");
- DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d",
+ DBUG_PRINT("enter",("file: %d blocks_used: %lu blocks_changed: %lu",
file, keycache->blocks_used, keycache->blocks_changed));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
@@ -2543,7 +2543,7 @@ int flush_key_blocks(KEY_CACHE *keycache,
{
int res;
DBUG_ENTER("flush_key_blocks");
- DBUG_PRINT("enter", ("keycache: 0x%lx", keycache));
+ DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
if (keycache->disk_blocks <= 0)
DBUG_RETURN(0);
diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c
index 38fef31fdd4..e5086014a27 100644
--- a/mysys/mf_keycaches.c
+++ b/mysys/mf_keycaches.c
@@ -159,7 +159,7 @@ static byte *safe_hash_search(SAFE_HASH *hash, const byte *key, uint length)
result= hash->default_value;
else
result= ((SAFE_HASH_ENTRY*) result)->data;
- DBUG_PRINT("exit",("data: 0x%lx", result));
+ DBUG_PRINT("exit",("data: 0x%lx", (long) result));
DBUG_RETURN(result);
}
@@ -190,7 +190,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const byte *key, uint length,
SAFE_HASH_ENTRY *entry;
my_bool error= 0;
DBUG_ENTER("safe_hash_set");
- DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, data));
+ DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, (long) data));
rw_wrlock(&hash->mutex);
entry= (SAFE_HASH_ENTRY*) hash_search(&hash->hash, key, length);
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index d5346d530c3..c97ae83f6bc 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -48,7 +48,8 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused)))
{
DBUG_ENTER("init_alloc_root");
- DBUG_PRINT("enter",("root: 0x%lx", mem_root));
+ DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root));
+
mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
mem_root->min_malloc= 32;
mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
@@ -146,7 +147,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
#if defined(HAVE_purify) && defined(EXTRA_DEBUG)
reg1 USED_MEM *next;
DBUG_ENTER("alloc_root");
- DBUG_PRINT("enter",("root: 0x%lx", mem_root));
+ DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root));
DBUG_ASSERT(alloc_root_inited(mem_root));
@@ -160,8 +161,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
next->next= mem_root->used;
next->size= Size;
mem_root->used= next;
- DBUG_PRINT("exit",("ptr: 0x%lx", (((char*) next)+
- ALIGN_SIZE(sizeof(USED_MEM)))));
+ DBUG_PRINT("exit",("ptr: 0x%lx", (long) (((char*) next)+
+ ALIGN_SIZE(sizeof(USED_MEM)))));
DBUG_RETURN((gptr) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))));
#else
uint get_size, block_size;
@@ -169,7 +170,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
reg1 USED_MEM *next= 0;
reg2 USED_MEM **prev;
DBUG_ENTER("alloc_root");
- DBUG_PRINT("enter",("root: 0x%lx", mem_root));
+ DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root));
DBUG_ASSERT(alloc_root_inited(mem_root));
Size= ALIGN_SIZE(Size);
@@ -328,7 +329,7 @@ void free_root(MEM_ROOT *root, myf MyFlags)
{
reg1 USED_MEM *next,*old;
DBUG_ENTER("free_root");
- DBUG_PRINT("enter",("root: 0x%lx flags: %u", root, (uint) MyFlags));
+ DBUG_PRINT("enter",("root: 0x%lx flags: %u", (long) root, (uint) MyFlags));
if (!root) /* QQ: Should be deleted */
DBUG_VOID_RETURN; /* purecov: inspected */
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index fe0d0ffa607..4b26085c870 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -86,7 +86,11 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
Fill space between requested length and true length with 'filler'
We should never come here on any modern machine
*/
- VOID(my_seek(fd, newlength, MY_SEEK_SET, MYF(MY_WME+MY_FAE)));
+ if (my_seek(fd, newlength, MY_SEEK_SET, MYF(MY_WME+MY_FAE))
+ == MY_FILEPOS_ERROR)
+ {
+ goto err;
+ }
swap_variables(my_off_t, newlength, oldsize);
#endif
}
diff --git a/mysys/my_dup.c b/mysys/my_dup.c
index 4b7434e29ea..cdc15b3ebce 100644
--- a/mysys/my_dup.c
+++ b/mysys/my_dup.c
@@ -30,7 +30,7 @@ File my_dup(File file, myf MyFlags)
File fd;
const char *filename;
DBUG_ENTER("my_dup");
- DBUG_PRINT("my",("file: %d MyFlags: %d", MyFlags));
+ DBUG_PRINT("my",("file: %d MyFlags: %d", file, MyFlags));
fd = dup(file);
filename= (((uint) file < my_file_limit) ?
my_file_info[(int) file].name : "Unknown");
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index f07beec9f39..6e81d40a2d6 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -79,7 +79,7 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags)
my_stream_opened++;
my_file_info[fileno(fd)].type = STREAM_BY_FOPEN;
pthread_mutex_unlock(&THR_LOCK_open);
- DBUG_PRINT("exit",("stream: 0x%lx",fd));
+ DBUG_PRINT("exit",("stream: 0x%lx", (long) fd));
DBUG_RETURN(fd);
}
pthread_mutex_unlock(&THR_LOCK_open);
@@ -103,7 +103,7 @@ int my_fclose(FILE *fd, myf MyFlags)
{
int err,file;
DBUG_ENTER("my_fclose");
- DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d",fd, MyFlags));
+ DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
file=fileno(fd);
@@ -163,7 +163,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
pthread_mutex_unlock(&THR_LOCK_open);
}
- DBUG_PRINT("exit",("stream: 0x%lx",fd));
+ DBUG_PRINT("exit",("stream: 0x%lx", (long) fd));
DBUG_RETURN(fd);
} /* my_fdopen */
diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c
index 5b17e3ff51c..0f7f4cc888f 100644
--- a/mysys/my_fstream.c
+++ b/mysys/my_fstream.c
@@ -40,7 +40,7 @@ uint my_fread(FILE *stream, byte *Buffer, uint Count, myf MyFlags)
uint readbytes;
DBUG_ENTER("my_fread");
DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d",
- stream, Buffer, Count, MyFlags));
+ (long) stream, (long) Buffer, Count, MyFlags));
if ((readbytes = (uint) fread(Buffer,sizeof(char),(size_t) Count,stream))
!= Count)
@@ -81,7 +81,7 @@ uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags)
#endif
DBUG_ENTER("my_fwrite");
DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d",
- stream, Buffer, Count, MyFlags));
+ (long) stream, (long) Buffer, Count, MyFlags));
#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
errors=0;
@@ -153,7 +153,7 @@ my_off_t my_fseek(FILE *stream, my_off_t pos, int whence,
{
DBUG_ENTER("my_fseek");
DBUG_PRINT("my",("stream: 0x%lx pos: %lu whence: %d MyFlags: %d",
- stream, pos, whence, MyFlags));
+ (long) stream, (long) pos, whence, MyFlags));
DBUG_RETURN(fseek(stream, (off_t) pos, whence) ?
MY_FILEPOS_ERROR : (my_off_t) ftell(stream));
} /* my_seek */
@@ -166,7 +166,7 @@ my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused)))
{
off_t pos;
DBUG_ENTER("my_ftell");
- DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d",stream, MyFlags));
+ DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) stream, MyFlags));
pos=ftell(stream);
DBUG_PRINT("exit",("ftell: %lu",(ulong) pos));
DBUG_RETURN((my_off_t) pos);
diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c
index 5663ceaa60e..b6b6ee610a5 100644
--- a/mysys/my_getwd.c
+++ b/mysys/my_getwd.c
@@ -45,7 +45,7 @@ int my_getwd(my_string buf, uint size, myf MyFlags)
{
my_string pos;
DBUG_ENTER("my_getwd");
- DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", buf,size,MyFlags));
+ DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", (long) buf,size,MyFlags));
#if ! defined(MSDOS)
if (curr_dir[0]) /* Current pos is saved here */
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 23d28956808..46144c0dff2 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -505,6 +505,7 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
switch ((enum ha_base_keytype) keyseg->type) {
case HA_KEYTYPE_TEXT:
case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_BIT:
if (keyseg->flag & HA_SPACE_PACK)
{
int a_length;
@@ -516,7 +517,9 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
a= end;
break;
case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
case HA_KEYTYPE_VARBINARY1:
+ case HA_KEYTYPE_VARBINARY2:
{
int a_length;
get_key_length(a_length, a);
@@ -546,6 +549,10 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
case HA_KEYTYPE_DOUBLE:
a= end;
break;
+ case HA_KEYTYPE_END: /* purecov: inspected */
+ /* keep compiler happy */
+ DBUG_ASSERT(0);
+ break;
}
}
return keyseg;
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index 1c5630ad14e..ae7b0baafbd 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -638,7 +638,7 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
int m_used;
DBUG_ENTER("my_stat");
DBUG_PRINT("my", ("path: '%s', stat_area: 0x%lx, MyFlags: %d", path,
- (byte *) stat_area, 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)))
diff --git a/mysys/my_lock.c b/mysys/my_lock.c
index 8f915d6003a..b8307f366c0 100644
--- a/mysys/my_lock.c
+++ b/mysys/my_lock.c
@@ -35,7 +35,14 @@
#include <nks/fsio.h>
#endif
- /* Lock a part of a file */
+/*
+ Lock a part of a file
+
+ RETURN VALUE
+ 0 Success
+ -1 An error has occured and 'my_errno' is set
+ to indicate the actual error code.
+*/
int my_lock(File fd, int locktype, my_off_t start, my_off_t length,
myf MyFlags)
@@ -104,10 +111,22 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length,
#elif defined(HAVE_LOCKING)
/* Windows */
{
- my_bool error;
+ my_bool error= FALSE;
pthread_mutex_lock(&my_file_info[fd].mutex);
- if (MyFlags & MY_SEEK_NOT_DONE)
- VOID(my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE)));
+ 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)
@@ -145,7 +164,17 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length,
}
#else
if (MyFlags & MY_SEEK_NOT_DONE)
- VOID(my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE)));
+ {
+ if (my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE))
+ == MY_FILEPOS_ERROR)
+ {
+ /*
+ If an error has occured in my_seek then we will already
+ have an error code in my_errno; Just return error code.
+ */
+ DBUG_RETURN(-1);
+ }
+ }
if (lockf(fd,locktype,length) != -1)
DBUG_RETURN(0);
#endif /* HAVE_FCNTL */
diff --git a/mysys/my_lread.c b/mysys/my_lread.c
index 601d772b844..ccf795631b8 100644
--- a/mysys/my_lread.c
+++ b/mysys/my_lread.c
@@ -27,8 +27,10 @@ uint32 my_lread(int Filedes, byte *Buffer, uint32 Count, myf MyFlags)
{
uint32 readbytes;
DBUG_ENTER("my_lread");
- DBUG_PRINT("my",("Fd: %d Buffer: %ld Count: %ld MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
+ DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d",
+ Filedes, (long) Buffer, (ulong) Count, MyFlags));
+
+ DBUG_PRINT("error", ("Deprecated my_lread() function should not be used."));
/* Temp hack to get count to int32 while read wants int */
if ((readbytes = (uint32) read(Filedes, Buffer, (uint) Count)) != Count)
diff --git a/mysys/my_lwrite.c b/mysys/my_lwrite.c
index 3b9afdbd71f..85f4677932e 100644
--- a/mysys/my_lwrite.c
+++ b/mysys/my_lwrite.c
@@ -23,8 +23,10 @@ uint32 my_lwrite(int Filedes, const byte *Buffer, uint32 Count, myf MyFlags)
{
uint32 writenbytes;
DBUG_ENTER("my_lwrite");
- DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %ld MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
+ DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d",
+ Filedes, (long) Buffer, (ulong) Count, MyFlags));
+
+ DBUG_PRINT("error", ("Deprecated my_lwrite() function should not be used."));
/* Temp hack to get count to int32 while write wants int */
if ((writenbytes = (uint32) write(Filedes, Buffer, (uint) Count)) != Count)
diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c
index f33db2655c4..c6d51e29f18 100644
--- a/mysys/my_malloc.c
+++ b/mysys/my_malloc.c
@@ -44,7 +44,7 @@ gptr my_malloc(unsigned int size, myf my_flags)
}
else if (my_flags & MY_ZEROFILL)
bzero(point,size);
- DBUG_PRINT("exit",("ptr: 0x%lx",point));
+ DBUG_PRINT("exit",("ptr: 0x%lx", (long) point));
DBUG_RETURN(point);
} /* my_malloc */
@@ -55,7 +55,7 @@ gptr my_malloc(unsigned int size, myf my_flags)
void my_no_flags_free(gptr ptr)
{
DBUG_ENTER("my_free");
- DBUG_PRINT("my",("ptr: 0x%lx",ptr));
+ DBUG_PRINT("my",("ptr: 0x%lx", (long) ptr));
if (ptr)
free(ptr);
DBUG_VOID_RETURN;
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index 3d02e368720..b1b9d9da950 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -30,7 +30,7 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
int error;
DBUG_ENTER("my_pread");
DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d",
- Filedes, (ulong) offset, Buffer, Count, MyFlags));
+ Filedes, (ulong) offset, (long) Buffer, Count, MyFlags));
for (;;)
{
@@ -49,11 +49,15 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
if (error)
{
my_errno=errno;
- DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d",
- readbytes,Count,Filedes,my_errno));
+ DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
+ (int) readbytes, Count,Filedes,my_errno));
#ifdef THREAD
- if (readbytes == 0 && errno == EINTR)
- continue; /* Interrupted */
+ if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
+ {
+ DBUG_PRINT("debug", ("my_pread() was interrupted and returned %d",
+ (int) readbytes));
+ continue; /* Interrupted */
+ }
#endif
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
@@ -83,7 +87,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
ulong written;
DBUG_ENTER("my_pwrite");
DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %d MyFlags: %d",
- Filedes, (ulong) offset,Buffer, Count, MyFlags));
+ Filedes, (ulong) offset, (long) Buffer, Count, MyFlags));
errors=0; written=0L;
for (;;)
@@ -124,8 +128,8 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC));
continue;
}
- if ((writenbytes == 0 && my_errno == EINTR) ||
- (writenbytes > 0 && (uint) writenbytes != (uint) -1))
+ if ((writenbytes > 0 && (uint) writenbytes != (uint) -1) ||
+ my_errno == EINTR)
continue; /* Retry */
#endif
if (MyFlags & (MY_NABP | MY_FNABP))
diff --git a/mysys/my_quick.c b/mysys/my_quick.c
index 44ed3fc0b2c..ffc8160c371 100644
--- a/mysys/my_quick.c
+++ b/mysys/my_quick.c
@@ -26,6 +26,14 @@ uint my_quick_read(File Filedes,byte *Buffer,uint Count,myf MyFlags)
if ((readbytes = (uint) read(Filedes, Buffer, Count)) != Count)
{
+#ifndef DBUG_OFF
+ if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
+ {
+ DBUG_PRINT("error", ("my_quick_read() was interrupted and returned %d"
+ ". This function does not retry the read!",
+ (int) readbytes));
+ }
+#endif
my_errno=errno;
return readbytes;
}
@@ -35,8 +43,24 @@ uint my_quick_read(File Filedes,byte *Buffer,uint Count,myf MyFlags)
uint my_quick_write(File Filedes,const byte *Buffer,uint Count)
{
- if ((uint) write(Filedes,Buffer,Count) != Count)
+#ifndef DBUG_OFF
+ uint writtenbytes;
+#endif
+
+ if ((
+#ifndef DBUG_OFF
+ writtenbytes =
+#endif
+ (uint) write(Filedes,Buffer,Count)) != Count)
{
+#ifndef DBUG_OFF
+ if ((writtenbytes == 0 || (int) writtenbytes == -1) && errno == EINTR)
+ {
+ DBUG_PRINT("error", ("my_quick_write() was interrupted and returned %d"
+ ". This function does not retry the write!",
+ (int) writtenbytes));
+ }
+#endif
my_errno=errno;
return (uint) -1;
}
diff --git a/mysys/my_read.c b/mysys/my_read.c
index 2e23f2175f8..33eb3ddf334 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -39,7 +39,7 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags)
uint readbytes, save_count;
DBUG_ENTER("my_read");
DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
+ Filedes, (long) Buffer, Count, MyFlags));
save_count= Count;
for (;;)
@@ -48,13 +48,14 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags)
if ((readbytes= (uint) read(Filedes, Buffer, Count)) != Count)
{
my_errno= errno ? errno : -1;
- DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d",
- readbytes, Count, Filedes, my_errno));
+ DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
+ (int) readbytes, Count, Filedes, my_errno));
#ifdef THREAD
- if ((int) readbytes <= 0 && errno == EINTR)
- {
- DBUG_PRINT("debug", ("my_read() was interrupted and returned %d", (int) readbytes));
- continue; /* Interrupted */
+ if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
+ {
+ DBUG_PRINT("debug", ("my_read() was interrupted and returned %d",
+ (int) readbytes));
+ continue; /* Interrupted */
}
#endif
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c
index a385bf1e530..b521ae36b94 100644
--- a/mysys/my_realloc.c
+++ b/mysys/my_realloc.c
@@ -27,7 +27,7 @@ gptr my_realloc(gptr oldpoint, uint size, myf my_flags)
{
gptr point;
DBUG_ENTER("my_realloc");
- DBUG_PRINT("my",("ptr: 0x%lx size: %u my_flags: %d",oldpoint, size,
+ DBUG_PRINT("my",("ptr: 0x%lx size: %u my_flags: %d", (long) oldpoint, size,
my_flags));
if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR))
@@ -60,6 +60,6 @@ gptr my_realloc(gptr oldpoint, uint size, myf my_flags)
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), size);
}
#endif
- DBUG_PRINT("exit",("ptr: 0x%lx",point));
+ DBUG_PRINT("exit",("ptr: 0x%lx", (long) point));
DBUG_RETURN(point);
} /* my_realloc */
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index 8035312496d..e8c109acacd 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -16,8 +16,30 @@
#include "mysys_priv.h"
- /* Seek to position in file */
- /*ARGSUSED*/
+/*
+ Seek to a position in a file.
+
+ ARGUMENTS
+ File fd The file descriptor
+ my_off_t pos The expected position (absolute or relative)
+ int whence A direction parameter and one of
+ {SEEK_SET, SEEK_CUR, SEEK_END}
+ myf MyFlags Not used.
+
+ DESCRIPTION
+ The my_seek function is a wrapper around the system call lseek and
+ repositions the offset of the file descriptor fd to the argument
+ offset according to the directive whence as follows:
+ SEEK_SET The offset is set to offset bytes.
+ SEEK_CUR The offset is set to its current location plus offset bytes
+ SEEK_END The offset is set to the size of the file plus offset bytes
+
+ RETURN VALUE
+ my_off_t newpos The new position in the file.
+ MY_FILEPOS_ERROR An error was encountered while performing
+ the seek. my_errno is set to indicate the
+ actual error.
+*/
my_off_t my_seek(File fd, my_off_t pos, int whence,
myf MyFlags __attribute__((unused)))
@@ -29,12 +51,17 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
whence, MyFlags));
DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */
- if (-1 != fd)
- newpos=lseek(fd, pos, whence);
+ /*
+ Make sure we are using a valid file descriptor!
+ */
+ DBUG_ASSERT(fd != -1);
+
+ newpos= lseek(fd, pos, whence);
+
if (newpos == (os_off_t) -1)
{
my_errno=errno;
- DBUG_PRINT("error",("lseek: %lu, errno: %d",newpos,errno));
+ DBUG_PRINT("error",("lseek: %lu, errno: %d", (ulong) newpos,errno));
DBUG_RETURN(MY_FILEPOS_ERROR);
}
if ((my_off_t) newpos != pos)
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 4d23d01cd82..fcae18d4686 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -30,7 +30,10 @@ 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_net, THR_LOCK_charset, THR_LOCK_threads;
+pthread_cond_t THR_COND_threads;
+uint THR_thread_count= 0;
+uint my_thread_end_wait_time= 5;
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
pthread_mutex_t LOCK_localtime_r;
#endif
@@ -79,7 +82,7 @@ my_bool my_thread_global_init(void)
#endif
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
/*
- Set mutex type to "errorcheck" a.k.a "adaptive"
+ Set mutex type to "errorcheck"
*/
pthread_mutexattr_init(&my_errorcheck_mutexattr);
pthread_mutexattr_settype(&my_errorcheck_mutexattr,
@@ -94,6 +97,8 @@ my_bool my_thread_global_init(void)
pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&THR_COND_threads, NULL);
#if defined( __WIN__) || defined(OS2)
win_pthread_init();
#endif
@@ -114,6 +119,27 @@ my_bool my_thread_global_init(void)
void my_thread_global_end(void)
{
+ struct timespec abstime;
+ my_bool all_threads_killed= 1;
+
+ set_timespec(abstime, my_thread_end_wait_time);
+ pthread_mutex_lock(&THR_LOCK_threads);
+ while (THR_thread_count > 0)
+ {
+ int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
+ &abstime);
+ if (error == ETIMEDOUT || error == ETIME)
+ {
+ if (THR_thread_count)
+ fprintf(stderr,
+ "Error in my_thread_global_end(): %d threads didn't exit\n",
+ THR_thread_count);
+ all_threads_killed= 0;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&THR_LOCK_threads);
+
pthread_key_delete(THR_KEY_mysys);
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
pthread_mutexattr_destroy(&my_fast_mutexattr);
@@ -129,6 +155,11 @@ void my_thread_global_end(void)
pthread_mutex_destroy(&THR_LOCK_heap);
pthread_mutex_destroy(&THR_LOCK_net);
pthread_mutex_destroy(&THR_LOCK_charset);
+ if (all_threads_killed)
+ {
+ pthread_mutex_destroy(&THR_LOCK_threads);
+ pthread_cond_destroy (&THR_COND_threads);
+ }
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
pthread_mutex_destroy(&LOCK_localtime_r);
#endif
@@ -140,10 +171,23 @@ void my_thread_global_end(void)
static long thread_id=0;
/*
- We can't use mutex_locks here if we are using windows as
- we may have compiled the program with SAFE_MUTEX, in which
- case the checking of mutex_locks will not work until
- the pthread_self thread specific variable is initialized.
+ Allocate thread specific memory for the thread, used by mysys and dbug
+
+ SYNOPSIS
+ my_thread_init()
+
+ NOTES
+ We can't use mutex_locks here if we are using windows as
+ we may have compiled the program with SAFE_MUTEX, in which
+ case the checking of mutex_locks will not work until
+ the pthread_self thread specific variable is initialized.
+
+ This function may called multiple times for a thread, for example
+ if one uses my_init() followed by mysql_server_init().
+
+ RETURN
+ 0 ok
+ 1 Fatal error; mysys/dbug functions can't be used
*/
my_bool my_thread_init(void)
@@ -154,9 +198,6 @@ my_bool my_thread_init(void)
#ifdef EXTRA_DEBUG_THREADS
fprintf(stderr,"my_thread_init(): thread_id=%ld\n",pthread_self());
#endif
-#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
- pthread_mutex_lock(&THR_LOCK_lock);
-#endif
#if !defined(__WIN__) || defined(USE_TLS)
if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys))
@@ -174,7 +215,7 @@ my_bool my_thread_init(void)
}
pthread_setspecific(THR_KEY_mysys,tmp);
-#else
+#else /* defined(__WIN__) && !(defined(USE_TLS) */
/*
Skip initialization if the thread specific variable is already initialized
*/
@@ -182,7 +223,6 @@ my_bool my_thread_init(void)
goto end;
tmp= &THR_KEY_mysys;
#endif
- tmp->id= ++thread_id;
#if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
tmp->thread_self= (pthread_t)getpid();
#endif
@@ -190,22 +230,35 @@ my_bool my_thread_init(void)
pthread_cond_init(&tmp->suspend, NULL);
tmp->init= 1;
+ pthread_mutex_lock(&THR_LOCK_threads);
+ tmp->id= ++thread_id;
+ ++THR_thread_count;
+ pthread_mutex_unlock(&THR_LOCK_threads);
end:
-#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
- pthread_mutex_unlock(&THR_LOCK_lock);
-#endif
return error;
}
+/*
+ Deallocate memory used by the thread for book-keeping
+
+ SYNOPSIS
+ my_thread_end()
+
+ NOTE
+ This may be called multiple times for a thread.
+ This happens for example when one calls 'mysql_server_init()'
+ mysql_server_end() and then ends with a mysql_end().
+*/
+
void my_thread_end(void)
{
struct st_my_thread_var *tmp;
tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
#ifdef EXTRA_DEBUG_THREADS
- fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n",
- tmp,pthread_self());
+ fprintf(stderr,"my_thread_end(): tmp: 0x%lx thread_id=%ld\n",
+ (long) tmp, pthread_self());
#endif
if (tmp && tmp->init)
{
@@ -227,6 +280,18 @@ void my_thread_end(void)
#else
tmp->init= 0;
#endif
+
+ /*
+ Decrement counter for number of running threads. We are using this
+ in my_thread_global_end() to wait until all threads have called
+ my_thread_end and thus freed all memory they have allocated in
+ my_thread_init() and DBUG_xxxx
+ */
+ pthread_mutex_lock(&THR_LOCK_threads);
+ DBUG_ASSERT(THR_thread_count != 0);
+ if (--THR_thread_count == 0)
+ 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(OS2)) || defined(USE_TLS)
diff --git a/mysys/my_write.c b/mysys/my_write.c
index 4e8369480b3..26b9a4f2444 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -27,7 +27,7 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags)
ulong written;
DBUG_ENTER("my_write");
DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %d MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
+ Filedes, (long) Buffer, Count, MyFlags));
errors=0; written=0L;
for (;;)
@@ -57,18 +57,24 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags)
VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC));
continue;
}
- if (!writenbytes)
+
+ if ((writenbytes == 0 || (int) writenbytes == -1))
{
- /* We may come here on an interrupt or if the file quote is exeeded */
if (my_errno == EINTR)
- continue;
- if (!errors++) /* Retry once */
{
- errno=EFBIG; /* Assume this is the error */
- continue;
+ DBUG_PRINT("debug", ("my_write() was interrupted and returned %d",
+ (int) writenbytes));
+ continue; /* Interrupted */
+ }
+
+ if (!writenbytes && !errors++) /* Retry once */
+ {
+ /* We may come here if the file quota is exeeded */
+ errno=EFBIG; /* Assume this is the error */
+ continue;
}
}
- else if ((uint) writenbytes != (uint) -1)
+ else
continue; /* Retry */
#endif
if (MyFlags & (MY_NABP | MY_FNABP))
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index f6d6644859e..b3466e36197 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -194,7 +194,7 @@ gptr _mymalloc(uint size, const char *filename, uint lineno, myf MyFlags)
if ((MyFlags & MY_ZEROFILL) || !sf_malloc_quick)
bfill(data, size, (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL));
/* Return a pointer to the real data */
- DBUG_PRINT("exit",("ptr: 0x%lx", data));
+ DBUG_PRINT("exit",("ptr: 0x%lx", (long) data));
if (sf_min_adress > data)
sf_min_adress= data;
if (sf_max_adress < data)
@@ -259,7 +259,7 @@ void _myfree(gptr ptr, const char *filename, uint lineno, myf myflags)
{
struct st_irem *irem;
DBUG_ENTER("_myfree");
- DBUG_PRINT("enter",("ptr: 0x%lx", ptr));
+ DBUG_PRINT("enter",("ptr: 0x%lx", (long) ptr));
if (!sf_malloc_quick)
(void) _sanity (filename, lineno);
@@ -410,7 +410,7 @@ void TERMINATE(FILE *file)
}
DBUG_PRINT("safe",
("%6u bytes at 0x%09lx, allocated at line %4d in '%s'",
- irem->datasize, data, irem->linenum, irem->filename));
+ irem->datasize, (long) data, irem->linenum, irem->filename));
irem= irem->next;
}
}
@@ -447,7 +447,7 @@ static int _checkchunk(register struct st_irem *irem, const char *filename,
fprintf(stderr, " discovered at %s:%d\n", filename, lineno);
(void) fflush(stderr);
DBUG_PRINT("safe",("Underrun at 0x%lx, allocated at %s:%d",
- data, irem->filename, irem->linenum));
+ (long) data, irem->filename, irem->linenum));
flag=1;
}
@@ -463,7 +463,7 @@ static int _checkchunk(register struct st_irem *irem, const char *filename,
fprintf(stderr, " discovered at '%s:%d'\n", filename, lineno);
(void) fflush(stderr);
DBUG_PRINT("safe",("Overrun at 0x%lx, allocated at %s:%d",
- data,
+ (long) data,
irem->filename,
irem->linenum));
flag=1;
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index 51df50a4926..66848b94651 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -483,8 +483,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
data->owner= owner; /* Must be reset ! */
VOID(pthread_mutex_lock(&lock->mutex));
DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx type: %d",
- data, data->owner->info->thread_id,
- lock, (int) lock_type));
+ (long) data, data->owner->info->thread_id,
+ (long) lock, (int) lock_type));
check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ?
"enter read_lock" : "enter write_lock",0);
if ((int) lock_type <= (int) TL_READ_NO_INSERT)
@@ -659,7 +659,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
goto end;
}
}
- DBUG_PRINT("lock",("write locked by thread: %ld, type: %ld",
+ DBUG_PRINT("lock",("write locked by thread: %ld, type: %d",
lock->read.data->owner->info->thread_id, data->type));
}
wait_queue= &lock->write_wait;
@@ -740,7 +740,7 @@ void thr_unlock(THR_LOCK_DATA *data)
enum thr_lock_type lock_type=data->type;
DBUG_ENTER("thr_unlock");
DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx",
- data, data->owner->info->thread_id, lock));
+ (long) data, data->owner->info->thread_id, (long) lock));
pthread_mutex_lock(&lock->mutex);
check_locks(lock,"start of release lock",0);
@@ -913,7 +913,7 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner)
{
THR_LOCK_DATA **pos,**end;
DBUG_ENTER("thr_multi_lock");
- DBUG_PRINT("lock",("data: 0x%lx count: %d",data,count));
+ DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count));
if (count > 1)
sort_locks(data,count);
/* lock everything */
@@ -986,7 +986,7 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
{
THR_LOCK_DATA **pos,**end;
DBUG_ENTER("thr_multi_unlock");
- DBUG_PRINT("lock",("data: 0x%lx count: %d",data,count));
+ DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count));
for (pos=data,end=data+count; pos < end ; pos++)
{
@@ -1000,7 +1000,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
else
{
DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: %ld lock: 0x%lx",
- *pos, (*pos)->owner->info->thread_id, (*pos)->lock));
+ (long) *pos, (*pos)->owner->info->thread_id,
+ (long) (*pos)->lock));
}
}
DBUG_VOID_RETURN;
diff --git a/mysys/tree.c b/mysys/tree.c
index 0c9c04919b0..f295fa15575 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -84,12 +84,12 @@ static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent);
static int test_rb_tree(TREE_ELEMENT *element);
#endif
-void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
+void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit,
int size, qsort_cmp2 compare, my_bool with_delete,
tree_element_free free_element, void *custom_arg)
{
DBUG_ENTER("init_tree");
- DBUG_PRINT("enter",("tree: 0x%lx size: %d",tree,size));
+ DBUG_PRINT("enter",("tree: 0x%lx size: %d", (long) tree, size));
if (default_alloc_size < DEFAULT_ALLOC_SIZE)
default_alloc_size= DEFAULT_ALLOC_SIZE;
@@ -128,7 +128,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
}
if (!(tree->with_delete=with_delete))
{
- init_alloc_root(&tree->mem_root, default_alloc_size,0);
+ init_alloc_root(&tree->mem_root, (uint) default_alloc_size, 0);
tree->mem_root.min_malloc=(sizeof(TREE_ELEMENT)+tree->size_of_element);
}
DBUG_VOID_RETURN;
@@ -137,7 +137,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
static void free_tree(TREE *tree, myf free_flags)
{
DBUG_ENTER("free_tree");
- DBUG_PRINT("enter",("tree: 0x%lx",tree));
+ DBUG_PRINT("enter",("tree: 0x%lx", (long) tree));
if (tree->root) /* If initialized */
{
diff --git a/mysys/typelib.c b/mysys/typelib.c
index 90a093b0b32..d329b687668 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.c
@@ -49,7 +49,7 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name)
reg1 my_string i;
reg2 const char *j;
DBUG_ENTER("find_type");
- DBUG_PRINT("enter",("x: '%s' lib: 0x%lx",x,typelib));
+ DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) typelib));
if (!typelib->count)
{
diff --git a/ndb/config/type_kernel.mk.am b/ndb/config/type_kernel.mk.am
index 703876ee2e9..ccb01709dfb 100644
--- a/ndb/config/type_kernel.mk.am
+++ b/ndb/config/type_kernel.mk.am
@@ -1,6 +1,9 @@
INCLUDES += \
- -I$(srcdir) -I$(top_srcdir)/include \
+ -I$(srcdir) \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/ndb/include \
+ -I$(top_srcdir)/include \
-I$(top_srcdir)/ndb/include \
-I$(top_srcdir)/ndb/src/kernel/vm \
-I$(top_srcdir)/ndb/src/kernel/error \
diff --git a/ndb/config/type_ndbapi.mk.am b/ndb/config/type_ndbapi.mk.am
index ab84c683e86..18bc536fdee 100644
--- a/ndb/config/type_ndbapi.mk.am
+++ b/ndb/config/type_ndbapi.mk.am
@@ -1,6 +1,9 @@
INCLUDES += \
- -I$(srcdir) -I$(top_srcdir)/include \
+ -I$(srcdir) \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/ndb/include \
+ -I$(top_srcdir)/include \
-I$(top_srcdir)/mysys \
-I$(top_srcdir)/ndb/include \
-I$(top_srcdir)/ndb/include/kernel \
diff --git a/ndb/config/type_ndbapitest.mk.am b/ndb/config/type_ndbapitest.mk.am
index 392c4e9fc70..e9a383eaad7 100644
--- a/ndb/config/type_ndbapitest.mk.am
+++ b/ndb/config/type_ndbapitest.mk.am
@@ -5,7 +5,10 @@ LDADD += $(top_builddir)/ndb/test/src/libNDBT.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@
-INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/include \
+INCLUDES += -I$(top_srcdir) \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/ndb/include \
+ -I$(top_srcdir)/include \
-I$(top_srcdir)/ndb/include \
-I$(top_srcdir)/ndb/include/ndbapi \
-I$(top_srcdir)/ndb/include/util \
diff --git a/ndb/config/type_ndbapitools.mk.am b/ndb/config/type_ndbapitools.mk.am
index d4eb090112d..3c5510880d4 100644
--- a/ndb/config/type_ndbapitools.mk.am
+++ b/ndb/config/type_ndbapitools.mk.am
@@ -5,7 +5,10 @@ LDADD += \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@
-INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \
+INCLUDES += -I$(srcdir) \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/ndb/include \
+ -I$(top_srcdir)/include \
-I$(top_srcdir)/ndb/include \
-I$(top_srcdir)/ndb/include/ndbapi \
-I$(top_srcdir)/ndb/include/util \
diff --git a/ndb/config/type_util.mk.am b/ndb/config/type_util.mk.am
index 4f2d605dc91..de250ae1f43 100644
--- a/ndb/config/type_util.mk.am
+++ b/ndb/config/type_util.mk.am
@@ -1,5 +1,7 @@
INCLUDES += -I$(srcdir) \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/ndb/include \
-I$(top_srcdir)/include \
-I$(top_srcdir)/mysys \
-I$(top_srcdir)/ndb/include \
diff --git a/ndb/include/kernel/GlobalSignalNumbers.h b/ndb/include/kernel/GlobalSignalNumbers.h
index a645a56a64b..76b7d30059e 100644
--- a/ndb/include/kernel/GlobalSignalNumbers.h
+++ b/ndb/include/kernel/GlobalSignalNumbers.h
@@ -127,6 +127,7 @@ extern const GlobalSignalNumber NO_OF_SIGNAL_NAMES;
/* 68 unused */
/* 69 unused */
/* 70 unused */
+#define GSN_UPDATE_FRAG_DIST_KEY_ORD 70
#define GSN_ACC_ABORTREQ 71
#define GSN_ACC_CHECK_SCAN 72
#define GSN_ACC_COMMITCONF 73
diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h
index e60153e60ec..8822cb8976e 100644
--- a/ndb/include/kernel/ndb_limits.h
+++ b/ndb/include/kernel/ndb_limits.h
@@ -64,6 +64,8 @@
#define MAX_NULL_BITS 4096
#define MAX_FRAGMENT_DATA_BYTES (4+(2 * 8 * MAX_REPLICAS * MAX_NDB_NODES))
+#define MAX_WORDS_META_FILE 24576
+
#define MIN_ATTRBUF ((MAX_ATTRIBUTES_IN_TABLE/24) + 1)
/*
* Max Number of Records to fetch per SCAN_NEXTREQ in a scan in LQH. The
diff --git a/ndb/include/kernel/signaldata/CmRegSignalData.hpp b/ndb/include/kernel/signaldata/CmRegSignalData.hpp
index ab51ed17bc3..e076534da9e 100644
--- a/ndb/include/kernel/signaldata/CmRegSignalData.hpp
+++ b/ndb/include/kernel/signaldata/CmRegSignalData.hpp
@@ -90,7 +90,11 @@ public:
ZNOT_PRESIDENT = 5, /* We are not president */
ZNOT_DEAD = 6, /* We are not dead when we are starting */
ZINCOMPATIBLE_VERSION = 7,
- ZINCOMPATIBLE_START_TYPE = 8
+ ZINCOMPATIBLE_START_TYPE = 8,
+ ZSINGLE_USER_MODE = 9, /* The cluster is in single user mode,
+ * data node is not allowed to get added
+ * in the cluster while in single user mode */
+ ZGENERIC = 100 /* The generic error code */
};
private:
diff --git a/ndb/include/kernel/signaldata/CopyFrag.hpp b/ndb/include/kernel/signaldata/CopyFrag.hpp
index 67b935dda64..3fd5d704727 100644
--- a/ndb/include/kernel/signaldata/CopyFrag.hpp
+++ b/ndb/include/kernel/signaldata/CopyFrag.hpp
@@ -30,7 +30,8 @@ class CopyFragReq {
*/
friend class Dblqh;
public:
- STATIC_CONST( SignalLength = 7 );
+ STATIC_CONST( SignalLength = 8
+ );
private:
Uint32 userPtr;
@@ -40,6 +41,8 @@ private:
Uint32 nodeId;
Uint32 schemaVersion;
Uint32 distributionKey;
+ Uint32 nodeCount;
+ Uint32 nodeList[1];
};
class CopyFragConf {
@@ -84,4 +87,13 @@ private:
Uint32 errorCode;
};
+struct UpdateFragDistKeyOrd
+{
+ Uint32 tableId;
+ Uint32 fragId;
+ Uint32 fragDistributionKey;
+
+ STATIC_CONST( SignalLength = 3 );
+};
+
#endif
diff --git a/ndb/include/logger/LogHandler.hpp b/ndb/include/logger/LogHandler.hpp
index 8b9aa43d7a9..efb87bb3104 100644
--- a/ndb/include/logger/LogHandler.hpp
+++ b/ndb/include/logger/LogHandler.hpp
@@ -135,7 +135,7 @@ public:
*
* @param str the error string.
*/
- void setErrorStr(char* str);
+ void setErrorStr(const char* str);
/**
* Parse logstring parameters
diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h
index 4e015cc3d7e..d80e923a16e 100644
--- a/ndb/include/mgmapi/mgmapi.h
+++ b/ndb/include/mgmapi/mgmapi.h
@@ -231,7 +231,9 @@ extern "C" {
NDB_MGM_SERVER_NOT_CONNECTED = 1010,
/** Could not connect to socker */
NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011,
-
+ /** Could not bind local address */
+ NDB_MGM_BIND_ADDRESS = 1012,
+
/* Alloc node id failures */
/** Generic error, retry may succeed */
NDB_MGM_ALLOCID_ERROR = 1101,
@@ -516,6 +518,15 @@ extern "C" {
const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
/**
+ * Set local bindaddress
+ * @param arg - Srting of form "host[:port]"
+ * @note must be called before connect
+ * @note Error on binding local address will not be reported until connect
+ * @return 0 on success
+ */
+ int ndb_mgm_set_bindaddress(NdbMgmHandle, const char * arg);
+
+ /**
* Gets the connectstring used for a connection
*
* @note This function returns the default connectstring if no call to
@@ -862,6 +873,15 @@ extern "C" {
enum ndb_mgm_event_category category,
int level,
struct ndb_mgm_reply* reply);
+ /**
+ * get log category and levels
+ *
+ * @param handle NDB management handle.
+ * @return A vector of twelve elements,
+ * where each element contains
+ * loglevel of corresponding category
+ */
+ const unsigned int *ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle);
/** @} *********************************************************************/
/**
@@ -1072,6 +1092,19 @@ extern "C" {
int ndb_mgm_end_session(NdbMgmHandle handle);
/**
+ * ndb_mgm_get_fd
+ *
+ * get the file descriptor of the handle.
+ * INTERNAL ONLY.
+ * USE FOR TESTING. OTHER USES ARE NOT A GOOD IDEA.
+ *
+ * @param handle NDB management handle
+ * @return handle->socket
+ *
+ */
+ int ndb_mgm_get_fd(NdbMgmHandle handle);
+
+ /**
* Get the node id of the mgm server we're connected to
*/
Uint32 ndb_mgm_get_mgmd_nodeid(NdbMgmHandle handle);
@@ -1141,6 +1174,11 @@ extern "C" {
enum ndb_mgm_event_category c,
int l, struct ndb_mgm_reply* r)
{ return ndb_mgm_set_clusterlog_loglevel(h,n,c,l,r); }
+
+ inline
+ const unsigned int *ndb_mgm_get_loglevel_clusterlog(NdbMgmHandle h)
+ { return ndb_mgm_get_clusterlog_loglevel(h); }
+
#endif
#ifdef __cplusplus
diff --git a/ndb/include/mgmapi/ndbd_exit_codes.h b/ndb/include/mgmapi/ndbd_exit_codes.h
index 1016234c513..66c736181f0 100644
--- a/ndb/include/mgmapi/ndbd_exit_codes.h
+++ b/ndb/include/mgmapi/ndbd_exit_codes.h
@@ -65,6 +65,7 @@ typedef ndbd_exit_status_enum ndbd_exit_status;
typedef ndbd_exit_classification_enum ndbd_exit_classification;
/* Errorcodes before block division was used */
+#define NDBD_EXIT_GENERIC 2300
#define NDBD_EXIT_PRGERR 2301
#define NDBD_EXIT_NODE_NOT_IN_CONFIG 2302
#define NDBD_EXIT_SYSTEM_ERROR 2303
@@ -78,6 +79,7 @@ typedef ndbd_exit_classification_enum ndbd_exit_classification;
#define NDBD_EXIT_SR_RESTARTCONFLICT 2311
#define NDBD_EXIT_NO_MORE_UNDOLOG 2312
#define NDBD_EXIT_SR_UNDOLOG 2313
+#define NDBD_EXIT_SINGLE_USER_MODE 2314
#define NDBD_EXIT_MEMALLOC 2327
#define NDBD_EXIT_BLOCK_JBUFCONGESTION 2334
#define NDBD_EXIT_TIME_QUEUE_SHORT 2335
diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp
index 1b4ecd56f80..89a1eb976c8 100644
--- a/ndb/include/mgmcommon/ConfigRetriever.hpp
+++ b/ndb/include/mgmcommon/ConfigRetriever.hpp
@@ -28,7 +28,8 @@
class ConfigRetriever {
public:
ConfigRetriever(const char * _connect_string,
- Uint32 version, Uint32 nodeType);
+ Uint32 version, Uint32 nodeType,
+ const char * _bind_address = 0);
~ConfigRetriever();
int do_connect(int no_retries, int retry_delay_in_seconds, int verbose);
diff --git a/ndb/include/ndb_global.h.in b/ndb/include/ndb_global.h.in
index 122b0edc400..f1eed73f71a 100644
--- a/ndb/include/ndb_global.h.in
+++ b/ndb/include/ndb_global.h.in
@@ -132,4 +132,10 @@ extern "C" {
#define PATH_MAX 1024
#endif
+#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
+#define LINT_SET_PTR = {0,0}
+#else
+#define LINT_SET_PTR
+#endif
+
#endif
diff --git a/ndb/include/ndb_version.h.in b/ndb/include/ndb_version.h.in
index 7e878803f46..b60ea3bba68 100644
--- a/ndb/include/ndb_version.h.in
+++ b/ndb/include/ndb_version.h.in
@@ -62,5 +62,10 @@ char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ];
#define NDBD_DICT_LOCK_VERSION_5 MAKE_VERSION(5,0,23)
+#define NDBD_UPDATE_FRAG_DIST_KEY_50 MAKE_VERSION(5,0,26)
+#define NDBD_UPDATE_FRAG_DIST_KEY_51 MAKE_VERSION(5,1,12)
+
+#define NDBD_QMGR_SINGLEUSER_VERSION_5 MAKE_VERSION(5,0,25)
+
#endif
diff --git a/ndb/include/ndbapi/NdbTransaction.hpp b/ndb/include/ndbapi/NdbTransaction.hpp
index 6a80d6bf22c..de4db785fb3 100644
--- a/ndb/include/ndbapi/NdbTransaction.hpp
+++ b/ndb/include/ndbapi/NdbTransaction.hpp
@@ -658,8 +658,11 @@ private:
// Release all cursor operations in connection
void releaseOps(NdbOperation*);
void releaseScanOperations(NdbIndexScanOperation*);
+ bool releaseScanOperation(NdbIndexScanOperation** listhead,
+ NdbIndexScanOperation** listtail,
+ NdbIndexScanOperation* op);
void releaseExecutedScanOperation(NdbIndexScanOperation*);
-
+
// Set the transaction identity of the transaction
void setTransactionId(Uint64 aTransactionId);
diff --git a/ndb/include/util/File.hpp b/ndb/include/util/File.hpp
index 53ea88e0f52..fc71394c8c5 100644
--- a/ndb/include/util/File.hpp
+++ b/ndb/include/util/File.hpp
@@ -29,6 +29,14 @@ class File_class
{
public:
/**
+ * Returns time for last contents modification of a file.
+ *
+ * @param aFileName a filename to check.
+ * @return the time for last contents modificaton of the file.
+ */
+ static time_t mtime(const char* aFileName);
+
+ /**
* Returns true if the file exist.
*
* @param aFileName a filename to check.
diff --git a/ndb/include/util/InputStream.hpp b/ndb/include/util/InputStream.hpp
index b2a56b1e433..56c43686df1 100644
--- a/ndb/include/util/InputStream.hpp
+++ b/ndb/include/util/InputStream.hpp
@@ -25,6 +25,7 @@
*/
class InputStream {
public:
+ virtual ~InputStream() {}
virtual char* gets(char * buf, int bufLen) = 0;
};
@@ -40,6 +41,7 @@ extern FileInputStream Stdin;
class SocketInputStream : public InputStream {
NDB_SOCKET_TYPE m_socket;
unsigned m_timeout;
+ bool m_startover;
public:
SocketInputStream(NDB_SOCKET_TYPE socket, unsigned readTimeout = 1000);
char* gets(char * buf, int bufLen);
diff --git a/ndb/include/util/OutputStream.hpp b/ndb/include/util/OutputStream.hpp
index c7e009d4537..a834b577bb3 100644
--- a/ndb/include/util/OutputStream.hpp
+++ b/ndb/include/util/OutputStream.hpp
@@ -25,6 +25,7 @@
*/
class OutputStream {
public:
+ virtual ~OutputStream() {}
virtual int print(const char * fmt, ...) = 0;
virtual int println(const char * fmt, ...) = 0;
virtual void flush() {};
diff --git a/ndb/include/util/SimpleProperties.hpp b/ndb/include/util/SimpleProperties.hpp
index 438426fb62b..b29e65e21da 100644
--- a/ndb/include/util/SimpleProperties.hpp
+++ b/ndb/include/util/SimpleProperties.hpp
@@ -151,6 +151,7 @@ public:
ValueType m_type;
protected:
Reader();
+ virtual ~Reader() {}
virtual void reset() = 0;
virtual bool step(Uint32 len) = 0;
@@ -169,6 +170,7 @@ public:
bool add(Uint16 key, const char * value);
bool add(Uint16 key, const void* value, int len);
protected:
+ virtual ~Writer() {}
virtual bool reset() = 0;
virtual bool putWord(Uint32 val) = 0;
virtual bool putWords(const Uint32 * src, Uint32 len) = 0;
@@ -184,6 +186,7 @@ class SimplePropertiesLinearReader : public SimpleProperties::Reader {
public:
SimplePropertiesLinearReader(const Uint32 * src, Uint32 len);
+ virtual ~SimplePropertiesLinearReader() {}
virtual void reset();
virtual bool step(Uint32 len);
virtual bool getWord(Uint32 * dst);
@@ -202,6 +205,7 @@ class LinearWriter : public SimpleProperties::Writer {
public:
LinearWriter(Uint32 * src, Uint32 len);
+ virtual ~LinearWriter() {}
virtual bool reset();
virtual bool putWord(Uint32 val);
virtual bool putWords(const Uint32 * src, Uint32 len);
@@ -219,6 +223,7 @@ class UtilBufferWriter : public SimpleProperties::Writer {
public:
UtilBufferWriter(class UtilBuffer & buf);
+ virtual ~UtilBufferWriter() {}
virtual bool reset();
virtual bool putWord(Uint32 val);
virtual bool putWords(const Uint32 * src, Uint32 len);
@@ -238,6 +243,7 @@ public:
SimplePropertiesSectionReader(struct SegmentedSectionPtr &,
class SectionSegmentPool &);
+ virtual ~SimplePropertiesSectionReader() {}
virtual void reset();
virtual bool step(Uint32 len);
virtual bool getWord(Uint32 * dst);
@@ -270,6 +276,7 @@ class SimplePropertiesSectionWriter : public SimpleProperties::Writer {
public:
SimplePropertiesSectionWriter(class SectionSegmentPool &);
+ virtual ~SimplePropertiesSectionWriter() {}
virtual bool reset();
virtual bool putWord(Uint32 val);
virtual bool putWords(const Uint32 * src, Uint32 len);
diff --git a/ndb/include/util/SocketClient.hpp b/ndb/include/util/SocketClient.hpp
index bf1ad7d45d6..422560c8a78 100644
--- a/ndb/include/util/SocketClient.hpp
+++ b/ndb/include/util/SocketClient.hpp
@@ -37,7 +37,8 @@ public:
};
unsigned short get_port() { return m_port; };
char *get_server_name() { return m_server_name; };
- NDB_SOCKET_TYPE connect();
+ int bind(const char* toaddress, unsigned short toport);
+ NDB_SOCKET_TYPE connect(const char* toaddress = 0, unsigned short port = 0);
bool close();
};
diff --git a/ndb/include/util/UtilBuffer.hpp b/ndb/include/util/UtilBuffer.hpp
index f43fc960a16..ba1f47b93d8 100644
--- a/ndb/include/util/UtilBuffer.hpp
+++ b/ndb/include/util/UtilBuffer.hpp
@@ -73,11 +73,15 @@ public:
}
int assign(const void * d, size_t l) {
- if (data) free(data);
+ /* Free the old data only after copying, in case d==data. */
+ void *old_data= data;
data = NULL;
len = 0;
alloc_size = 0;
- return append(d, l);
+ int ret= append(d, l);
+ if (old_data)
+ free(old_data);
+ return ret;
}
void clear() {
diff --git a/ndb/include/util/ndb_opts.h b/ndb/include/util/ndb_opts.h
index 08ab4a2e9df..053cc8613f7 100644
--- a/ndb/include/util/ndb_opts.h
+++ b/ndb/include/util/ndb_opts.h
@@ -58,7 +58,7 @@ const char *opt_debug= 0;
{ "ndb-connectstring", OPT_NDB_CONNECTSTRING, \
"Set connect string for connecting to ndb_mgmd. " \
"Syntax: \"[nodeid=<id>;][host=]<hostname>[:<port>]\". " \
- "Overides specifying entries in NDB_CONNECTSTRING and Ndb.cfg", \
+ "Overrides specifying entries in NDB_CONNECTSTRING and my.cnf", \
(gptr*) &opt_ndb_connectstring, (gptr*) &opt_ndb_connectstring, \
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
{ "ndb-mgmd-host", OPT_NDB_MGMD, \
diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp
index e1a477b8ea4..8027a6bd347 100644
--- a/ndb/src/common/debugger/EventLogger.cpp
+++ b/ndb/src/common/debugger/EventLogger.cpp
@@ -116,8 +116,7 @@ void getTextNDBStopForced(QQQQ) {
int sphase = theData[4];
int extra = theData[5];
getRestartAction(theData[1],action_str);
- if (signal)
- reason_str.appfmt(" Initiated by signal %d.", signum);
+ reason_str.appfmt(" Initiated by signal %d.", signum);
if (error)
{
ndbd_exit_classification cl;
@@ -647,8 +646,8 @@ void getTextMemoryUsage(QQQQ) {
const int used = theData[3];
const int total = theData[4];
const int block = theData[5];
- const int percent = (used*100)/total;
-
+ const int percent = total ? (used*100)/total : 0;
+
BaseString::snprintf(m_text, m_text_len,
"%s usage %s %d%s(%d %dK pages of total %d)",
(block==DBACC ? "Index" : (block == DBTUP ?"Data":"<unknown>")),
diff --git a/ndb/src/common/debugger/signaldata/BackupSignalData.cpp b/ndb/src/common/debugger/signaldata/BackupSignalData.cpp
index 27fed22ac72..7410db44aa3 100644
--- a/ndb/src/common/debugger/signaldata/BackupSignalData.cpp
+++ b/ndb/src/common/debugger/signaldata/BackupSignalData.cpp
@@ -124,6 +124,9 @@ printABORT_BACKUP_ORD(FILE * out, const Uint32 * data, Uint32 len, Uint16 b){
sig->backupPtr, sig->backupId);
return true;
break;
+ case AbortBackupOrd::AbortScan:
+ case AbortBackupOrd::IncompatibleVersions:
+ return false;
}
return false;
}
diff --git a/ndb/src/common/debugger/signaldata/SignalNames.cpp b/ndb/src/common/debugger/signaldata/SignalNames.cpp
index 49e3f505b11..ecc9fc83153 100644
--- a/ndb/src/common/debugger/signaldata/SignalNames.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalNames.cpp
@@ -636,6 +636,7 @@ const GsnName SignalNames [] = {
,{ GSN_DICT_LOCK_CONF, "DICT_LOCK_CONF" }
,{ GSN_DICT_LOCK_REF, "DICT_LOCK_REF" }
,{ GSN_DICT_UNLOCK_ORD, "DICT_UNLOCK_ORD" }
-
+
+ ,{ GSN_UPDATE_FRAG_DIST_KEY_ORD, "UPDATE_FRAG_DIST_KEY_ORD" }
};
const unsigned short NO_OF_SIGNAL_NAMES = sizeof(SignalNames)/sizeof(GsnName);
diff --git a/ndb/src/common/logger/FileLogHandler.cpp b/ndb/src/common/logger/FileLogHandler.cpp
index 3d29e63ac1f..b8859630406 100644
--- a/ndb/src/common/logger/FileLogHandler.cpp
+++ b/ndb/src/common/logger/FileLogHandler.cpp
@@ -147,6 +147,7 @@ FileLogHandler::createNewFile()
bool rc = true;
int fileNo = 1;
char newName[PATH_MAX];
+ time_t newMtime, preMtime = 0;
do
{
@@ -159,7 +160,15 @@ FileLogHandler::createNewFile()
}
BaseString::snprintf(newName, sizeof(newName),
"%s.%d", m_pLogFile->getName(), fileNo++);
-
+ newMtime = File_class::mtime(newName);
+ if (newMtime < preMtime)
+ {
+ break;
+ }
+ else
+ {
+ preMtime = newMtime;
+ }
} while (File_class::exists(newName));
m_pLogFile->close();
diff --git a/ndb/src/common/logger/LogHandler.cpp b/ndb/src/common/logger/LogHandler.cpp
index c11f962d4fb..47333f81812 100644
--- a/ndb/src/common/logger/LogHandler.cpp
+++ b/ndb/src/common/logger/LogHandler.cpp
@@ -164,9 +164,9 @@ LogHandler::getErrorStr()
}
void
-LogHandler::setErrorStr(char* str)
+LogHandler::setErrorStr(const char* str)
{
- m_errorStr= str;
+ m_errorStr= (char*) str;
}
bool
diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index c2b3e8235eb..a0e3a4b74f3 100644
--- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -45,7 +45,8 @@
//****************************************************************************
ConfigRetriever::ConfigRetriever(const char * _connect_string,
- Uint32 version, Uint32 node_type)
+ Uint32 version, Uint32 node_type,
+ const char * _bindaddress)
{
DBUG_ENTER("ConfigRetriever::ConfigRetriever");
@@ -66,6 +67,15 @@ ConfigRetriever::ConfigRetriever(const char * _connect_string,
setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
DBUG_VOID_RETURN;
}
+
+ if (_bindaddress)
+ {
+ if (ndb_mgm_set_bindaddress(m_handle, _bindaddress))
+ {
+ setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
+ DBUG_VOID_RETURN;
+ }
+ }
resetError();
DBUG_VOID_RETURN;
}
diff --git a/ndb/src/common/portlib/NdbMutex.c b/ndb/src/common/portlib/NdbMutex.c
index 4a170d87e5c..f0a1614ba8e 100644
--- a/ndb/src/common/portlib/NdbMutex.c
+++ b/ndb/src/common/portlib/NdbMutex.c
@@ -28,7 +28,7 @@ NdbMutex* NdbMutex_Create(void)
DBUG_ENTER("NdbMutex_Create");
pNdbMutex = (NdbMutex*)NdbMem_Allocate(sizeof(NdbMutex));
- DBUG_PRINT("info",("NdbMem_Allocate 0x%lx",pNdbMutex));
+ DBUG_PRINT("info",("NdbMem_Allocate 0x%lx", (long) pNdbMutex));
if (pNdbMutex == NULL)
DBUG_RETURN(NULL);
@@ -50,7 +50,7 @@ int NdbMutex_Destroy(NdbMutex* p_mutex)
result = pthread_mutex_destroy(p_mutex);
- DBUG_PRINT("info",("NdbMem_Free 0x%lx",p_mutex));
+ DBUG_PRINT("info",("NdbMem_Free 0x%lx", (long) p_mutex));
NdbMem_Free(p_mutex);
DBUG_RETURN(result);
diff --git a/ndb/src/common/portlib/NdbThread.c b/ndb/src/common/portlib/NdbThread.c
index 48d00956ec2..67c8f6faf50 100644
--- a/ndb/src/common/portlib/NdbThread.c
+++ b/ndb/src/common/portlib/NdbThread.c
@@ -122,7 +122,7 @@ struct NdbThread* NdbThread_Create(NDB_THREAD_FUNC *p_thread_func,
assert(result==0);
pthread_attr_destroy(&thread_attr);
- DBUG_PRINT("exit",("ret: %lx", tmpThread));
+ DBUG_PRINT("exit",("ret: 0x%lx", (long) tmpThread));
DBUG_RETURN(tmpThread);
}
@@ -131,7 +131,7 @@ void NdbThread_Destroy(struct NdbThread** p_thread)
{
DBUG_ENTER("NdbThread_Destroy");
if (*p_thread != NULL){
- DBUG_PRINT("enter",("*p_thread: %lx", * p_thread));
+ DBUG_PRINT("enter",("*p_thread: 0x%lx", (long) *p_thread));
free(* p_thread);
* p_thread = 0;
}
diff --git a/ndb/src/common/transporter/Transporter.cpp b/ndb/src/common/transporter/Transporter.cpp
index 820aa4cfc18..b2ee75e4754 100644
--- a/ndb/src/common/transporter/Transporter.cpp
+++ b/ndb/src/common/transporter/Transporter.cpp
@@ -39,8 +39,8 @@ Transporter::Transporter(TransporterRegistry &t_reg,
int _byteorder,
bool _compression, bool _checksum, bool _signalId)
: m_s_port(s_port), remoteNodeId(rNodeId), localNodeId(lNodeId),
- isServer(lNodeId==serverNodeId), isMgmConnection(_isMgmConnection),
- m_packer(_signalId, _checksum),
+ isServer(lNodeId==serverNodeId),
+ m_packer(_signalId, _checksum), isMgmConnection(_isMgmConnection),
m_type(_type),
m_transporter_registry(t_reg)
{
@@ -60,9 +60,6 @@ Transporter::Transporter(TransporterRegistry &t_reg,
}
strncpy(localHostName, lHostName, sizeof(localHostName));
- if (strlen(lHostName) > 0)
- Ndb_getInAddr(&localHostAddress, lHostName);
-
DBUG_PRINT("info",("rId=%d lId=%d isServer=%d rHost=%s lHost=%s s_port=%d",
remoteNodeId, localNodeId, isServer,
remoteHostName, localHostName,
@@ -128,10 +125,23 @@ Transporter::connect_client() {
return true;
if(isMgmConnection)
+ {
sockfd= m_transporter_registry.connect_ndb_mgmd(m_socket_client);
+ }
else
+ {
+ if (!m_socket_client->init())
+ {
+ return false;
+ }
+ if (strlen(localHostName) > 0)
+ {
+ if (m_socket_client->bind(localHostName, 0) != 0)
+ return false;
+ }
sockfd= m_socket_client->connect();
-
+ }
+
return connect_client(sockfd);
}
diff --git a/ndb/src/common/util/File.cpp b/ndb/src/common/util/File.cpp
index 52ad3a4a51e..056b7ff199b 100644
--- a/ndb/src/common/util/File.cpp
+++ b/ndb/src/common/util/File.cpp
@@ -24,6 +24,18 @@
//
// PUBLIC
//
+time_t
+File_class::mtime(const char* aFileName)
+{
+ MY_STAT stmp;
+ time_t rc = 0;
+
+ if (my_stat(aFileName, &stmp, MYF(0)) != NULL) {
+ rc = stmp.st_mtime;
+ }
+
+ return rc;
+}
bool
File_class::exists(const char* aFileName)
diff --git a/ndb/src/common/util/InputStream.cpp b/ndb/src/common/util/InputStream.cpp
index 410e9a70e9c..1b0e809a047 100644
--- a/ndb/src/common/util/InputStream.cpp
+++ b/ndb/src/common/util/InputStream.cpp
@@ -36,26 +36,35 @@ FileInputStream::gets(char * buf, int bufLen){
SocketInputStream::SocketInputStream(NDB_SOCKET_TYPE socket,
unsigned readTimeout)
- : m_socket(socket) {
- m_timeout = readTimeout;
+ : m_socket(socket) {
+ m_startover= true;
+ m_timeout = readTimeout;
}
-char*
+char*
SocketInputStream::gets(char * buf, int bufLen) {
- buf[0] = 77;
assert(bufLen >= 2);
- int res = readln_socket(m_socket, m_timeout, buf, bufLen - 1);
+ int offset= 0;
+ if(m_startover)
+ {
+ buf[0]= '\0';
+ m_startover= false;
+ }
+ else
+ offset= strlen(buf);
+
+ int res = readln_socket(m_socket, m_timeout, buf+offset, bufLen-offset);
+
+ if(res == 0)
+ {
+ buf[0]=0;
+ return buf;
+ }
+
+ m_startover= true;
+
if(res == -1)
return 0;
- if(res == 0 && buf[0] == 77){ // select return 0
- buf[0] = 0;
- } else if(res == 0 && buf[0] == 0){ // only newline
- buf[0] = '\n';
- buf[1] = 0;
- } else {
- int len = strlen(buf);
- buf[len + 1] = '\0';
- buf[len] = '\n';
- }
+
return buf;
}
diff --git a/ndb/src/common/util/Parser.cpp b/ndb/src/common/util/Parser.cpp
index 3a86ae8f318..392c3e83825 100644
--- a/ndb/src/common/util/Parser.cpp
+++ b/ndb/src/common/util/Parser.cpp
@@ -148,21 +148,26 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst,
bool ownStop = false;
if(stop == 0)
stop = &ownStop;
-
+
ctx->m_aliasUsed.clear();
-
+
const unsigned sz = sizeof(ctx->m_tokenBuffer);
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
if(Eof(ctx->m_currentToken)){
ctx->m_status = Parser<Dummy>::Eof;
DBUG_RETURN(false);
}
-
- if(ctx->m_currentToken[0] == 0){
+
+ int last= strlen(ctx->m_currentToken);
+ if(last>0)
+ last--;
+
+ if(ctx->m_currentToken[last] !='\n'){
ctx->m_status = Parser<Dummy>::NoLine;
+ ctx->m_tokenBuffer[0]= '\0';
DBUG_RETURN(false);
}
-
+
if(Empty(ctx->m_currentToken)){
ctx->m_status = Parser<Dummy>::EmptyLine;
DBUG_RETURN(false);
@@ -174,14 +179,14 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst,
ctx->m_status = Parser<Dummy>::UnknownCommand;
DBUG_RETURN(false);
}
-
+
Properties * p = new Properties();
-
+
bool invalidArgument = false;
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
-
- while((! * stop) &&
- !Eof(ctx->m_currentToken) &&
+
+ while((! * stop) &&
+ !Eof(ctx->m_currentToken) &&
!Empty(ctx->m_currentToken)){
if(ctx->m_currentToken[0] != 0){
trim(ctx->m_currentToken);
@@ -193,7 +198,7 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst,
}
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
}
-
+
if(invalidArgument){
char buf[sz];
char * tmp;
@@ -204,13 +209,13 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst,
}
DBUG_RETURN(false);
}
-
+
if(* stop){
delete p;
ctx->m_status = Parser<Dummy>::ExternalStop;
DBUG_RETURN(false);
}
-
+
if(!checkMandatory(ctx, p)){
ctx->m_status = Parser<Dummy>::MissingMandatoryArgument;
delete p;
@@ -226,9 +231,9 @@ ParserImpl::run(Context * ctx, const class Properties ** pDst,
tmp.put("name", alias->name);
tmp.put("realName", alias->realName);
p->put("$ALIAS", i, &tmp);
- }
+ }
p->put("$ALIAS", ctx->m_aliasUsed.size());
-
+
ctx->m_status = Parser<Dummy>::Ok;
* pDst = p;
DBUG_RETURN(true);
diff --git a/ndb/src/common/util/SimpleProperties.cpp b/ndb/src/common/util/SimpleProperties.cpp
index c9251c6a854..a32762caad7 100644
--- a/ndb/src/common/util/SimpleProperties.cpp
+++ b/ndb/src/common/util/SimpleProperties.cpp
@@ -267,7 +267,7 @@ SimpleProperties::pack(Writer & it, const void * __src,
const char * src_len = _src + _map[i].Length_Offset;
Uint32 len = *((Uint32*)src_len);
if(!ignoreMinMax){
- if(len == _map[i].maxValue)
+ if(len > _map[i].maxValue)
return ValueTooHigh;
}
ok = it.add(_map[i].Key, src, len);
@@ -276,7 +276,7 @@ SimpleProperties::pack(Writer & it, const void * __src,
case SimpleProperties::StringValue:
if(!ignoreMinMax){
size_t len = strlen(src);
- if(len == _map[i].maxValue)
+ if(len > _map[i].maxValue)
return ValueTooHigh;
}
ok = it.add(_map[i].Key, src);
diff --git a/ndb/src/common/util/SocketClient.cpp b/ndb/src/common/util/SocketClient.cpp
index 821624eb5c4..f4f2babf312 100644
--- a/ndb/src/common/util/SocketClient.cpp
+++ b/ndb/src/common/util/SocketClient.cpp
@@ -25,7 +25,7 @@ SocketClient::SocketClient(const char *server_name, unsigned short port, SocketA
{
m_auth= sa;
m_port= port;
- m_server_name= strdup(server_name);
+ m_server_name= server_name ? strdup(server_name) : 0;
m_sockfd= NDB_INVALID_SOCKET;
}
@@ -45,13 +45,16 @@ SocketClient::init()
if (m_sockfd != NDB_INVALID_SOCKET)
NDB_CLOSE_SOCKET(m_sockfd);
- memset(&m_servaddr, 0, sizeof(m_servaddr));
- m_servaddr.sin_family = AF_INET;
- m_servaddr.sin_port = htons(m_port);
- // Convert ip address presentation format to numeric format
- if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
- return false;
-
+ if (m_server_name)
+ {
+ memset(&m_servaddr, 0, sizeof(m_servaddr));
+ m_servaddr.sin_family = AF_INET;
+ m_servaddr.sin_port = htons(m_port);
+ // Convert ip address presentation format to numeric format
+ if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
+ return false;
+ }
+
m_sockfd= socket(AF_INET, SOCK_STREAM, 0);
if (m_sockfd == NDB_INVALID_SOCKET) {
return false;
@@ -62,8 +65,45 @@ SocketClient::init()
return true;
}
+int
+SocketClient::bind(const char* bindaddress, unsigned short localport)
+{
+ if (m_sockfd == NDB_INVALID_SOCKET)
+ return -1;
+
+ struct sockaddr_in local;
+ memset(&local, 0, sizeof(local));
+ local.sin_family = AF_INET;
+ local.sin_port = htons(localport);
+ // Convert ip address presentation format to numeric format
+ if (Ndb_getInAddr(&local.sin_addr, bindaddress))
+ {
+ return errno ? errno : EINVAL;
+ }
+
+ const int on = 1;
+ if (setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR,
+ (const char*)&on, sizeof(on)) == -1) {
+
+ int ret = errno;
+ NDB_CLOSE_SOCKET(m_sockfd);
+ m_sockfd= NDB_INVALID_SOCKET;
+ return errno;
+ }
+
+ if (::bind(m_sockfd, (struct sockaddr*)&local, sizeof(local)) == -1)
+ {
+ int ret = errno;
+ NDB_CLOSE_SOCKET(m_sockfd);
+ m_sockfd= NDB_INVALID_SOCKET;
+ return ret;
+ }
+
+ return 0;
+}
+
NDB_SOCKET_TYPE
-SocketClient::connect()
+SocketClient::connect(const char *toaddress, unsigned short toport)
{
if (m_sockfd == NDB_INVALID_SOCKET)
{
@@ -74,6 +114,21 @@ SocketClient::connect()
return NDB_INVALID_SOCKET;
}
}
+
+ if (toaddress)
+ {
+ if (m_server_name)
+ free(m_server_name);
+ m_server_name = strdup(toaddress);
+ m_port = toport;
+ memset(&m_servaddr, 0, sizeof(m_servaddr));
+ m_servaddr.sin_family = AF_INET;
+ m_servaddr.sin_port = htons(toport);
+ // Convert ip address presentation format to numeric format
+ if (Ndb_getInAddr(&m_servaddr.sin_addr, m_server_name))
+ return NDB_INVALID_SOCKET;
+ }
+
const int r = ::connect(m_sockfd, (struct sockaddr*) &m_servaddr, sizeof(m_servaddr));
if (r == -1) {
NDB_CLOSE_SOCKET(m_sockfd);
diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp
index 58636e6663d..ba2794e4374 100644
--- a/ndb/src/common/util/socket_io.cpp
+++ b/ndb/src/common/util/socket_io.cpp
@@ -75,7 +75,6 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
return -1;
}
- buf[0] = 0;
const int t = recv(socket, buf, buflen, MSG_PEEK);
if(t < 1)
@@ -87,27 +86,28 @@ readln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
for(int i=0; i< t;i++)
{
if(buf[i] == '\n'){
- recv(socket, buf, i+1, 0);
- buf[i] = 0;
+ int r= recv(socket, buf, i+1, 0);
+ buf[i+1]= 0;
+ if(r < 1) {
+ fcntl(socket, F_SETFL, sock_flags);
+ return -1;
+ }
if(i > 0 && buf[i-1] == '\r'){
- i--;
- buf[i] = 0;
+ buf[i-1] = '\n';
+ buf[i]= '\0';
}
fcntl(socket, F_SETFL, sock_flags);
- return t;
+ return r;
}
}
- if(t == (buflen - 1)){
- recv(socket, buf, t, 0);
- buf[t] = 0;
- fcntl(socket, F_SETFL, sock_flags);
- return buflen;
- }
-
- return 0;
+ int r= recv(socket, buf, t, 0);
+ if(r>=0)
+ buf[r] = 0;
+ fcntl(socket, F_SETFL, sock_flags);
+ return r;
}
extern "C"
diff --git a/ndb/src/cw/cpcd/CPCD.hpp b/ndb/src/cw/cpcd/CPCD.hpp
index aecc43150c4..3a69a03aa3f 100644
--- a/ndb/src/cw/cpcd/CPCD.hpp
+++ b/ndb/src/cw/cpcd/CPCD.hpp
@@ -63,6 +63,7 @@ struct CPCEvent {
struct EventSubscriber {
virtual void report(const CPCEvent &) = 0;
+ virtual ~EventSubscriber() {}
};
/**
diff --git a/ndb/src/cw/cpcd/main.cpp b/ndb/src/cw/cpcd/main.cpp
index c320f07ef04..137735c9e76 100644
--- a/ndb/src/cw/cpcd/main.cpp
+++ b/ndb/src/cw/cpcd/main.cpp
@@ -82,6 +82,8 @@ int main(int argc, char** argv){
load_defaults("ndb_cpcd",load_default_groups,&argc,&argv);
if (handle_options(&argc, &argv, my_long_options, get_one_option)) {
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
exit(1);
diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am
index 389cb85c1d8..6e075f0f248 100644
--- a/ndb/src/kernel/Makefile.am
+++ b/ndb/src/kernel/Makefile.am
@@ -9,21 +9,21 @@ ndbd_SOURCES = main.cpp SimBlockList.cpp
include $(top_srcdir)/ndb/config/type_kernel.mk.am
INCLUDES += \
- -Iblocks/cmvmi \
- -Iblocks/dbacc \
- -Iblocks/dbdict \
- -Iblocks/dbdih \
- -Iblocks/dblqh \
- -Iblocks/dbtc \
- -Iblocks/dbtup \
- -Iblocks/ndbfs \
- -Iblocks/ndbcntr \
- -Iblocks/qmgr \
- -Iblocks/trix \
- -Iblocks/backup \
- -Iblocks/dbutil \
- -Iblocks/suma \
- -Iblocks/dbtux
+ -I$(srcdir)/blocks/cmvmi \
+ -I$(srcdir)/blocks/dbacc \
+ -I$(srcdir)/blocks/dbdict \
+ -I$(srcdir)/blocks/dbdih \
+ -I$(srcdir)/blocks/dblqh \
+ -I$(srcdir)/blocks/dbtc \
+ -I$(srcdir)/blocks/dbtup \
+ -I$(srcdir)/blocks/ndbfs \
+ -I$(srcdir)/blocks/ndbcntr \
+ -I$(srcdir)/blocks/qmgr \
+ -I$(srcdir)/blocks/trix \
+ -I$(srcdir)/blocks/backup \
+ -I$(srcdir)/blocks/dbutil \
+ -I$(srcdir)/blocks/suma \
+ -I$(srcdir)/blocks/dbtux
LDADD += \
blocks/cmvmi/libcmvmi.a \
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index c8c9e82efc2..74d5df2c1e6 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -5,7 +5,7 @@ Next DBACC 3002
Next DBTUP 4014
Next DBLQH 5043
Next DBDICT 6007
-Next DBDIH 7177
+Next DBDIH 7178
Next DBTC 8038
Next CMVMI 9000
Next BACKUP 10022
@@ -66,6 +66,8 @@ Delay GCP_SAVEREQ by 10 secs
7030: Delay in GCP_PREPARE until node has completed a node failure
7031: Delay in GCP_PREPARE and die 3s later
+7177: Delay copying of sysfileData in execCOPY_GCIREQ
+
ERROR CODES FOR TESTING NODE FAILURE, LOCAL CHECKPOINT HANDLING:
-----------------------------------------------------------------
diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp
index 10318e5f52d..8f3f6ffe55c 100644
--- a/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -272,7 +272,7 @@ Backup::execCONTINUEB(Signal* signal)
Uint32 tabPtr_I = Tdata2;
Uint32 fragPtr_I = signal->theData[3];
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptr_I);
if (tabPtr_I == RNIL)
@@ -309,7 +309,7 @@ Backup::execCONTINUEB(Signal* signal)
fragInfo->NoOfRecordsLow = htonl(fragPtr.p->noOfRecords & 0xFFFFFFFF);
fragInfo->NoOfRecordsHigh = htonl(fragPtr.p->noOfRecords >> 32);
fragInfo->FilePosLow = htonl(0 & 0xFFFFFFFF);
- fragInfo->FilePosHigh = htonl(0 >> 32);
+ fragInfo->FilePosHigh = htonl(0);
filePtr.p->operation.dataBuffer.updateWritePtr(sz);
@@ -341,7 +341,7 @@ Backup::execCONTINUEB(Signal* signal)
case BackupContinueB::BUFFER_UNDERFLOW:
{
jam();
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, Tdata1);
checkFile(signal, filePtr);
return;
@@ -350,7 +350,7 @@ Backup::execCONTINUEB(Signal* signal)
case BackupContinueB::BUFFER_FULL_SCAN:
{
jam();
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, Tdata1);
checkScan(signal, filePtr);
return;
@@ -359,7 +359,7 @@ Backup::execCONTINUEB(Signal* signal)
case BackupContinueB::BUFFER_FULL_FRAG_COMPLETE:
{
jam();
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, Tdata1);
fragmentCompleted(signal, filePtr);
return;
@@ -368,7 +368,7 @@ Backup::execCONTINUEB(Signal* signal)
case BackupContinueB::BUFFER_FULL_META:
{
jam();
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, Tdata1);
BackupFilePtr filePtr;
@@ -377,7 +377,7 @@ Backup::execCONTINUEB(Signal* signal)
if(buf.getFreeSize() + buf.getMinRead() < buf.getUsableSize()) {
jam();
- TablePtr tabPtr;
+ TablePtr tabPtr LINT_SET_PTR;
c_tablePool.getPtr(tabPtr, Tdata2);
DEBUG_OUT("Backup - Buffer full - " << buf.getFreeSize()
@@ -392,7 +392,7 @@ Backup::execCONTINUEB(Signal* signal)
return;
}//if
- TablePtr tabPtr;
+ TablePtr tabPtr LINT_SET_PTR;
c_tablePool.getPtr(tabPtr, Tdata2);
GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
req->senderRef = reference();
@@ -912,6 +912,9 @@ Backup::checkNodeFail(Signal* signal,
#endif
Uint32 gsn, len, pos;
+ LINT_INIT(gsn);
+ LINT_INIT(len);
+ LINT_INIT(pos);
ptr.p->nodes.bitANDC(mask);
switch(ptr.p->masterData.gsn){
case GSN_DEFINE_BACKUP_REQ:
@@ -1099,7 +1102,7 @@ Backup::execBACKUP_REQ(Signal* signal)
void
Backup::execUTIL_SEQUENCE_REF(Signal* signal)
{
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
jamEntry();
UtilSequenceRef * utilRef = (UtilSequenceRef*)signal->getDataPtr();
ptr.i = utilRef->senderData;
@@ -1153,7 +1156,7 @@ Backup::execUTIL_SEQUENCE_CONF(Signal* signal)
return;
}
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
ptr.i = conf->senderData;
c_backupPool.getPtr(ptr);
@@ -1194,7 +1197,7 @@ Backup::defineBackupMutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){
jamEntry();
ndbrequire(retVal == 0);
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
ptr.i = ptrI;
c_backupPool.getPtr(ptr);
@@ -1215,7 +1218,7 @@ Backup::dictCommitTableMutex_locked(Signal* signal, Uint32 ptrI,Uint32 retVal)
/**
* We now have both the mutexes
*/
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
ptr.i = ptrI;
c_backupPool.getPtr(ptr);
@@ -1320,7 +1323,7 @@ Backup::execDEFINE_BACKUP_REF(Signal* signal)
//const Uint32 backupId = ref->backupId;
const Uint32 nodeId = ref->nodeId;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
ptr.p->setErrorCode(ref->errorCode);
@@ -1337,7 +1340,7 @@ Backup::execDEFINE_BACKUP_CONF(Signal* signal)
//const Uint32 backupId = conf->backupId;
const Uint32 nodeId = refToNode(signal->senderBlockRef());
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
if (ERROR_INSERTED(10024))
@@ -1508,7 +1511,7 @@ Backup::execCREATE_TRIG_REF(Signal* signal)
const Uint32 ptrI = ref->getConnectionPtr();
const Uint32 tableId = ref->getTableId();
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
/**
@@ -1623,7 +1626,7 @@ Backup::execSTART_BACKUP_REF(Signal* signal)
const Uint32 signalNo = ref->signalNo;
const Uint32 nodeId = ref->nodeId;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
ptr.p->setErrorCode(ref->errorCode);
@@ -1641,7 +1644,7 @@ Backup::execSTART_BACKUP_CONF(Signal* signal)
const Uint32 signalNo = conf->signalNo;
const Uint32 nodeId = refToNode(signal->senderBlockRef());
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
startBackupReply(signal, ptr, nodeId, signalNo);
@@ -1671,7 +1674,7 @@ Backup::startBackupReply(Signal* signal, BackupRecordPtr ptr,
return;
}
- TablePtr tabPtr;
+ TablePtr tabPtr LINT_SET_PTR;
c_tablePool.getPtr(tabPtr, ptr.p->masterData.startBackup.tablePtr);
for(Uint32 i = 0; i<StartBackupReq::MaxTableTriggers; i++) {
jam();
@@ -1765,7 +1768,7 @@ Backup::execALTER_TRIG_CONF(Signal* signal)
AlterTrigConf* conf = (AlterTrigConf*)signal->getDataPtr();
const Uint32 ptrI = conf->getConnectionPtr();
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
alterTrigReply(signal, ptr);
@@ -1779,7 +1782,7 @@ Backup::execALTER_TRIG_REF(Signal* signal)
AlterTrigRef* ref = (AlterTrigRef*)signal->getDataPtr();
const Uint32 ptrI = ref->getConnectionPtr();
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
ptr.p->setErrorCode(ref->getErrorCode());
@@ -1823,7 +1826,7 @@ Backup::execWAIT_GCP_REF(Signal* signal)
WaitGCPRef * ref = (WaitGCPRef*)signal->getDataPtr();
const Uint32 ptrI = ref->senderData;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
ndbrequire(ptr.p->masterRef == reference());
@@ -1847,7 +1850,7 @@ Backup::execWAIT_GCP_CONF(Signal* signal){
const Uint32 ptrI = conf->senderData;
const Uint32 gcp = conf->gcp;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
ndbrequire(ptr.p->masterRef == reference());
@@ -2057,7 +2060,7 @@ Backup::execBACKUP_FRAGMENT_REF(Signal* signal)
//const Uint32 backupId = ref->backupId;
const Uint32 nodeId = ref->nodeId;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
TablePtr tabPtr;
@@ -2206,7 +2209,7 @@ Backup::execDROP_TRIG_REF(Signal* signal)
DropTrigRef* ref = (DropTrigRef*)signal->getDataPtr();
const Uint32 ptrI = ref->getConnectionPtr();
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
//ndbrequire(ref->getErrorCode() == DropTrigRef::NoSuchTrigger);
@@ -2221,7 +2224,7 @@ Backup::execDROP_TRIG_CONF(Signal* signal)
DropTrigConf* conf = (DropTrigConf*)signal->getDataPtr();
const Uint32 ptrI = conf->getConnectionPtr();
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
dropTrigReply(signal, ptr);
@@ -2261,7 +2264,7 @@ Backup::execSTOP_BACKUP_REF(Signal* signal)
//const Uint32 backupId = ref->backupId;
const Uint32 nodeId = ref->nodeId;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
ptr.p->setErrorCode(ref->errorCode);
@@ -2296,7 +2299,7 @@ Backup::execSTOP_BACKUP_CONF(Signal* signal)
//const Uint32 backupId = conf->backupId;
const Uint32 nodeId = refToNode(signal->senderBlockRef());
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
ptr.p->noOfLogBytes += conf->noOfLogBytes;
@@ -2485,7 +2488,7 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
DefineBackupReq* req = (DefineBackupReq*)signal->getDataPtr();
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
const Uint32 ptrI = req->backupPtr;
const Uint32 backupId = req->backupId;
const BlockReference senderRef = req->senderRef;
@@ -2547,8 +2550,8 @@ Backup::execDEFINE_BACKUP_REQ(Signal* signal)
0 // 3M
};
const Uint32 maxInsert[] = {
- 2048, // Temporarily to solve TR515
- 4096, // 4k
+ MAX_WORDS_META_FILE,
+ 4096, // 16k
16*3000, // Max 16 tuples
};
Uint32 minWrite[] = {
@@ -2663,7 +2666,7 @@ Backup::execLIST_TABLES_CONF(Signal* signal)
ListTablesConf* conf = (ListTablesConf*)signal->getDataPtr();
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, conf->senderData);
const Uint32 len = signal->length() - ListTablesConf::HeaderLength;
@@ -2711,7 +2714,7 @@ Backup::openFiles(Signal* signal, BackupRecordPtr ptr)
{
jam();
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
FsOpenReq * req = (FsOpenReq *)signal->getDataPtrSend();
req->userReference = reference();
@@ -2776,10 +2779,10 @@ Backup::execFSOPENREF(Signal* signal)
const Uint32 userPtr = ref->userPointer;
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, userPtr);
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
ptr.p->setErrorCode(ref->errorCode);
openFilesReply(signal, ptr, filePtr);
@@ -2795,11 +2798,11 @@ Backup::execFSOPENCONF(Signal* signal)
const Uint32 userPtr = conf->userPointer;
const Uint32 filePointer = conf->filePointer;
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, userPtr);
filePtr.p->filePointer = filePointer;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
ndbrequire(filePtr.p->fileOpened == 0);
@@ -2957,7 +2960,7 @@ Backup::execGET_TABINFOREF(Signal* signal)
GetTabInfoRef * ref = (GetTabInfoRef*)signal->getDataPtr();
const Uint32 senderData = ref->senderData;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, senderData);
defineBackupRef(signal, ptr, ref->errorCode);
@@ -2978,7 +2981,7 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
const Uint32 len = conf->totalLen;
const Uint32 senderData = conf->senderData;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, senderData);
SegmentedSectionPtr dictTabInfoPtr;
@@ -3212,7 +3215,7 @@ Backup::execDI_FCOUNTCONF(Signal* signal)
fragPtr.p->scanned = 0;
fragPtr.p->scanning = 0;
fragPtr.p->tableId = tableId;
- fragPtr.p->node = RNIL;
+ fragPtr.p->node = 0;
}//for
/**
@@ -3421,7 +3424,7 @@ Backup::execBACKUP_FRAGMENT_REQ(Signal* signal)
/**
* Get file
*/
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, ptr.p->dataFilePtr);
ndbrequire(filePtr.p->backupPtr == ptrI);
@@ -3553,12 +3556,12 @@ Backup::execTRANSID_AI(Signal* signal)
//const Uint32 transId2 = signal->theData[2];
const Uint32 dataLen = signal->length() - 3;
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, filePtrI);
OperationRecord & op = filePtr.p->operation;
- TablePtr tabPtr;
+ TablePtr tabPtr LINT_SET_PTR;
c_tablePool.getPtr(tabPtr, op.tablePtr);
Table & table = * tabPtr.p;
@@ -3752,7 +3755,7 @@ Backup::execSCAN_FRAGREF(Signal* signal)
ScanFragRef * ref = (ScanFragRef*)signal->getDataPtr();
const Uint32 filePtrI = ref->senderData;
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, filePtrI);
filePtr.p->errorCode = ref->errorCode;
@@ -3771,7 +3774,7 @@ Backup::execSCAN_FRAGCONF(Signal* signal)
ScanFragConf * conf = (ScanFragConf*)signal->getDataPtr();
const Uint32 filePtrI = conf->senderData;
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, filePtrI);
OperationRecord & op = filePtr.p->operation;
@@ -3812,7 +3815,7 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr)
filePtr.p->scanRunning = 0;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
BackupFragmentConf * conf = (BackupFragmentConf*)signal->getDataPtrSend();
@@ -3835,7 +3838,7 @@ Backup::fragmentCompleted(Signal* signal, BackupFilePtr filePtr)
void
Backup::backupFragmentRef(Signal * signal, BackupFilePtr filePtr)
{
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
ptr.p->m_gsn = GSN_BACKUP_FRAGMENT_REF;
@@ -3891,7 +3894,7 @@ Backup::checkScan(Signal* signal, BackupFilePtr filePtr)
sendSignalWithDelay(DBLQH_REF, GSN_SCAN_NEXTREQ, signal,
10000, ScanFragNextReq::SignalLength);
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
ord->backupId = ptr.p->backupId;
@@ -3922,7 +3925,8 @@ Backup::execFSAPPENDREF(Signal* signal)
const Uint32 filePtrI = ref->userPointer;
const Uint32 errCode = ref->errorCode;
- BackupFilePtr filePtr;
+
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, filePtrI);
filePtr.p->fileRunning = 0;
@@ -3942,7 +3946,7 @@ Backup::execFSAPPENDCONF(Signal* signal)
const Uint32 filePtrI = signal->theData[0]; //conf->userPointer;
const Uint32 bytes = signal->theData[1]; //conf->bytes;
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, filePtrI);
OperationRecord & op = filePtr.p->operation;
@@ -4030,8 +4034,8 @@ Backup::execBACKUP_TRIG_REQ(Signal* signal)
/*
TUP asks if this trigger is to be fired on this node.
*/
- TriggerPtr trigPtr;
- TablePtr tabPtr;
+ TriggerPtr trigPtr LINT_SET_PTR;
+ TablePtr tabPtr LINT_SET_PTR;
FragmentPtr fragPtr;
Uint32 trigger_id = signal->theData[0];
Uint32 frag_id = signal->theData[1];
@@ -4059,7 +4063,7 @@ Backup::execTRIG_ATTRINFO(Signal* signal) {
TrigAttrInfo * trg = (TrigAttrInfo*)signal->getDataPtr();
- TriggerPtr trigPtr;
+ TriggerPtr trigPtr LINT_SET_PTR;
c_triggerPool.getPtr(trigPtr, trg->getTriggerId());
ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID); // Online...
@@ -4090,7 +4094,7 @@ Backup::execTRIG_ATTRINFO(Signal* signal) {
jam();
Uint32 save[TrigAttrInfo::StaticLength];
memcpy(save, signal->getDataPtr(), 4*TrigAttrInfo::StaticLength);
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
trigPtr.p->errorCode = AbortBackupOrd::LogBufferFull;
AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend();
@@ -4131,7 +4135,7 @@ Backup::execFIRE_TRIG_ORD(Signal* signal)
const Uint32 gci = trg->getGCI();
const Uint32 trI = trg->getTriggerId();
- TriggerPtr trigPtr;
+ TriggerPtr trigPtr LINT_SET_PTR;
c_triggerPool.getPtr(trigPtr, trI);
ndbrequire(trigPtr.p->event != ILLEGAL_TRIGGER_ID);
@@ -4144,7 +4148,7 @@ Backup::execFIRE_TRIG_ORD(Signal* signal)
ndbrequire(trigPtr.p->logEntry != 0);
Uint32 len = trigPtr.p->logEntry->Length;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, trigPtr.p->backupPtr);
if(gci != ptr.p->currGCP)
{
@@ -4215,7 +4219,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal)
/**
* Get backup record
*/
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
ptr.p->slaveState.setState(STOPPING);
@@ -4228,6 +4232,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal)
BackupFilePtr filePtr;
ptr.p->files.getPtr(filePtr, ptr.p->logFilePtr);
Uint32 * dst;
+ LINT_INIT(dst);
ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, 1));
* dst = 0;
filePtr.p->operation.dataBuffer.updateWritePtr(1);
@@ -4240,6 +4245,7 @@ Backup::execSTOP_BACKUP_REQ(Signal* signal)
const Uint32 gcpSz = sizeof(BackupFormat::CtlFile::GCPEntry) >> 2;
Uint32 * dst;
+ LINT_INIT(dst);
ndbrequire(filePtr.p->operation.dataBuffer.getWritePtr(&dst, gcpSz));
BackupFormat::CtlFile::GCPEntry * gcp =
@@ -4331,7 +4337,7 @@ Backup::execFSCLOSEREF(Signal* signal)
FsRef * ref = (FsRef*)signal->getDataPtr();
const Uint32 filePtrI = ref->userPointer;
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, filePtrI);
BackupRecordPtr ptr;
@@ -4352,7 +4358,7 @@ Backup::execFSCLOSECONF(Signal* signal)
FsConf * conf = (FsConf*)signal->getDataPtr();
const Uint32 filePtrI = conf->userPointer;
- BackupFilePtr filePtr;
+ BackupFilePtr filePtr LINT_SET_PTR;
c_backupFilePool.getPtr(filePtr, filePtrI);
#ifdef DEBUG_ABORT
@@ -4366,7 +4372,7 @@ Backup::execFSCLOSECONF(Signal* signal)
filePtr.p->fileOpened = 0;
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, filePtr.p->backupPtr);
for(ptr.p->files.first(filePtr); filePtr.i!=RNIL;ptr.p->files.next(filePtr))
{
@@ -4432,7 +4438,7 @@ Backup::execABORT_BACKUP_ORD(Signal* signal)
dumpUsedResources();
#endif
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
if(requestType == AbortBackupOrd::ClientAbort) {
if (getOwnNodeId() != getMasterNodeId()) {
jam();
@@ -4561,7 +4567,7 @@ Backup::dumpUsedResources()
jam();
for(Uint32 j = 0; j<3; j++) {
jam();
- TriggerPtr trigPtr;
+ TriggerPtr trigPtr LINT_SET_PTR;
if(tabPtr.p->triggerAllocated[j]) {
jam();
c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
@@ -4600,7 +4606,7 @@ Backup::cleanup(Signal* signal, BackupRecordPtr ptr)
tabPtr.p->fragments.release();
for(Uint32 j = 0; j<3; j++) {
jam();
- TriggerPtr trigPtr;
+ TriggerPtr trigPtr LINT_SET_PTR;
if(tabPtr.p->triggerAllocated[j]) {
jam();
c_triggerPool.getPtr(trigPtr, tabPtr.p->triggerIds[j]);
@@ -4680,7 +4686,7 @@ Backup::execFSREMOVECONF(Signal* signal){
/**
* Get backup record
*/
- BackupRecordPtr ptr;
+ BackupRecordPtr ptr LINT_SET_PTR;
c_backupPool.getPtr(ptr, ptrI);
c_backups.release(ptr);
}
diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp
index e37923da749..e869cbf9544 100644
--- a/ndb/src/kernel/blocks/backup/Backup.hpp
+++ b/ndb/src/kernel/blocks/backup/Backup.hpp
@@ -518,8 +518,10 @@ public:
Config c_defaults;
Uint32 m_diskless;
- STATIC_CONST(NO_OF_PAGES_META_FILE = 2);
-
+ STATIC_CONST(NO_OF_PAGES_META_FILE =
+ (MAX_WORDS_META_FILE + BACKUP_WORDS_PER_PAGE - 1) /
+ BACKUP_WORDS_PER_PAGE);
+
/**
* Pools
*/
diff --git a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
index d2f9150ade0..44f9917438f 100644
--- a/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
+++ b/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
@@ -1234,7 +1234,7 @@ Cmvmi::execTESTSIG(Signal* signal){
fprintf(stdout, "\n");
for(i = 0; i<signal->header.m_noOfSections; i++){
- SegmentedSectionPtr ptr;
+ SegmentedSectionPtr ptr = {0,0,0};
ndbout_c("-- Section %d --", i);
signal->getSection(ptr, i);
ndbrequire(ptr.p != 0);
@@ -1292,7 +1292,7 @@ Cmvmi::execTESTSIG(Signal* signal){
LinearSectionPtr ptr[3];
const Uint32 secs = signal->getNoOfSections();
for(i = 0; i<secs; i++){
- SegmentedSectionPtr sptr;
+ SegmentedSectionPtr sptr = {0,0,0};
signal->getSection(sptr, i);
ptr[i].sz = sptr.sz;
ptr[i].p = new Uint32[sptr.sz];
@@ -1341,7 +1341,7 @@ Cmvmi::execTESTSIG(Signal* signal){
LinearSectionPtr ptr[3];
const Uint32 secs = signal->getNoOfSections();
for(i = 0; i<secs; i++){
- SegmentedSectionPtr sptr;
+ SegmentedSectionPtr sptr = {0,0,0};
signal->getSection(sptr, i);
ptr[i].sz = sptr.sz;
ptr[i].p = new Uint32[sptr.sz];
@@ -1407,7 +1407,7 @@ Cmvmi::execTESTSIG(Signal* signal){
const Uint32 secs = signal->getNoOfSections();
memset(g_test, 0, sizeof(g_test));
for(i = 0; i<secs; i++){
- SegmentedSectionPtr sptr;
+ SegmentedSectionPtr sptr = {0,0,0};
signal->getSection(sptr, i);
g_test[i].sz = sptr.sz;
g_test[i].p = new Uint32[sptr.sz];
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
index 59a622b60e6..e560d924e5a 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
@@ -53,6 +53,7 @@ void Dbacc::initData()
tabrec = 0;
undopage = 0;
+ cnoOfAllocatedPages = cpagesize = 0;
// Records with constant sizes
}//Dbacc::initData()
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index 261a0acfa81..2652da97aea 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -177,7 +177,7 @@ void Dbacc::execCONTINUEB(Signal* signal)
case ZREPORT_MEMORY_USAGE:{
jam();
static int c_currentMemUsed = 0;
- int now = (cnoOfAllocatedPages * 100)/cpagesize;
+ int now = cpagesize ? (cnoOfAllocatedPages * 100)/cpagesize : 0;
const int thresholds[] = { 99, 90, 80, 0};
Uint32 i = 0;
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index a79ddd05fae..2eca2a76c45 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -2464,7 +2464,8 @@ void Dbdict::checkSchemaStatus(Signal* signal)
tablePtr.p->tableType = (DictTabInfo::TableType)oldEntry->m_tableType;
// On NR get index from master because index state is not on file
- const bool file = c_systemRestart || tablePtr.p->isTable();
+ const bool file = (* newEntry == * oldEntry) &&
+ (c_systemRestart || tablePtr.p->isTable());
restartCreateTab(signal, tableId, oldEntry, file);
return;
@@ -10053,8 +10054,8 @@ Dbdict::getDictLockType(Uint32 lockType)
static const DictLockType lt[] = {
{ DictLockReq::NodeRestartLock, BS_NODE_RESTART, "NodeRestart" }
};
- for (int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
- if (lt[i].lockType == lockType)
+ for (unsigned int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
+ if ((Uint32) lt[i].lockType == lockType)
return &lt[i];
}
return NULL;
@@ -10206,7 +10207,7 @@ Dbdict::execDICT_UNLOCK_ORD(Signal* signal)
DictLockPtr lockPtr;
c_dictLockQueue.getPtr(lockPtr, ord->lockPtr);
- ndbrequire(lockPtr.p->lt->lockType == ord->lockType);
+ ndbrequire((Uint32) lockPtr.p->lt->lockType == ord->lockType);
if (lockPtr.p->locked) {
jam();
diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
index 5c2cfac5eb1..53e54e96d2b 100644
--- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
+++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
@@ -1048,6 +1048,8 @@ private:
void removeStoredReplica(FragmentstorePtr regFragptr,
ReplicaRecordPtr replicaPtr);
void searchStoredReplicas(FragmentstorePtr regFragptr);
+ bool setup_create_replica(FragmentstorePtr, CreateReplicaRecord*,
+ ConstPtr<ReplicaRecord>);
void updateNodeInfo(FragmentstorePtr regFragptr);
//------------------------------------
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index 1c1fdb41d51..4aeb8136650 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -627,22 +627,48 @@ void Dbdih::execCOPY_GCIREQ(Signal* signal)
ndbrequire(c_copyGCISlave.m_copyReason == CopyGCIReq::IDLE);
ndbrequire(c_copyGCISlave.m_expectedNextWord == tstart);
ndbrequire(reason != CopyGCIReq::IDLE);
-
+ bool isdone = (tstart + CopyGCIReq::DATA_SIZE) >= Sysfile::SYSFILE_SIZE32;
+
+ if (ERROR_INSERTED(7177))
+ {
+ jam();
+
+ if (signal->getLength() == 3)
+ {
+ jam();
+ goto done;
+ }
+ }
+
arrGuard(tstart + CopyGCIReq::DATA_SIZE, sizeof(sysfileData)/4);
for(Uint32 i = 0; i<CopyGCIReq::DATA_SIZE; i++)
cdata[tstart+i] = copyGCI->data[i];
- if ((tstart + CopyGCIReq::DATA_SIZE) >= Sysfile::SYSFILE_SIZE32) {
+ if (ERROR_INSERTED(7177) && isMaster() && isdone)
+ {
+ sendSignalWithDelay(reference(), GSN_COPY_GCIREQ, signal, 1000, 3);
+ return;
+ }
+
+done:
+ if (isdone)
+ {
jam();
c_copyGCISlave.m_expectedNextWord = 0;
- } else {
+ }
+ else
+ {
jam();
c_copyGCISlave.m_expectedNextWord += CopyGCIReq::DATA_SIZE;
return;
- }//if
-
- memcpy(sysfileData, cdata, sizeof(sysfileData));
+ }
+ if (cmasterdihref != reference())
+ {
+ jam();
+ memcpy(sysfileData, cdata, sizeof(sysfileData));
+ }
+
c_copyGCISlave.m_copyReason = reason;
c_copyGCISlave.m_senderRef = signal->senderBlockRef();
c_copyGCISlave.m_senderData = copyGCI->anyData;
@@ -1274,9 +1300,9 @@ void Dbdih::execNDB_STTOR(Signal* signal)
if (isMaster()) {
jam();
systemRestartTakeOverLab(signal);
- if (anyActiveTakeOver() && false) {
+ if (anyActiveTakeOver())
+ {
jam();
- ndbout_c("1 - anyActiveTakeOver == true");
return;
}
}
@@ -2315,6 +2341,8 @@ Dbdih::systemRestartTakeOverLab(Signal* signal)
// NOT ACTIVE NODES THAT HAVE NOT YET BEEN TAKEN OVER NEEDS TAKE OVER
// IMMEDIATELY. IF WE ARE ALIVE WE TAKE OVER OUR OWN NODE.
/*-------------------------------------------------------------------*/
+ infoEvent("Take over of node %d started",
+ nodePtr.i);
startTakeOver(signal, RNIL, nodePtr.i, nodePtr.i);
}//if
break;
@@ -2427,6 +2455,12 @@ void Dbdih::nodeRestartTakeOver(Signal* signal, Uint32 startNodeId)
*--------------------------------------------------------------------*/
Uint32 takeOverNode = Sysfile::getTakeOverNode(startNodeId,
SYSFILE->takeOver);
+ if(takeOverNode == 0){
+ jam();
+ warningEvent("Bug in take-over code restarting");
+ takeOverNode = startNodeId;
+ }
+
startTakeOver(signal, RNIL, startNodeId, takeOverNode);
break;
}
@@ -2580,7 +2614,14 @@ void Dbdih::startTakeOver(Signal* signal,
Sysfile::setTakeOverNode(takeOverPtr.p->toFailedNode, SYSFILE->takeOver,
startNode);
takeOverPtr.p->toMasterStatus = TakeOverRecord::TO_START_COPY;
-
+
+ if (getNodeState().getSystemRestartInProgress())
+ {
+ jam();
+ checkToCopy();
+ checkToCopyCompleted(signal);
+ return;
+ }
cstartGcpNow = true;
}//Dbdih::startTakeOver()
@@ -3078,7 +3119,10 @@ void Dbdih::execCREATE_FRAGCONF(Signal* signal)
copyFragReq->nodeId = takeOverPtr.p->toStartingNode;
copyFragReq->schemaVersion = tabPtr.p->schemaVersion;
copyFragReq->distributionKey = fragPtr.p->distributionKey;
- sendSignal(ref, GSN_COPY_FRAGREQ, signal, CopyFragReq::SignalLength, JBB);
+ copyFragReq->nodeCount = extractNodeInfo(fragPtr.p,
+ copyFragReq->nodeList);
+ sendSignal(ref, GSN_COPY_FRAGREQ, signal,
+ CopyFragReq::SignalLength + copyFragReq->nodeCount, JBB);
} else {
ndbrequire(takeOverPtr.p->toMasterStatus == TakeOverRecord::COMMIT_CREATE);
jam();
@@ -3328,6 +3372,18 @@ void Dbdih::toCopyCompletedLab(Signal * signal, TakeOverRecordPtr takeOverPtr)
signal->theData[1] = takeOverPtr.p->toStartingNode;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
+ if (getNodeState().getSystemRestartInProgress())
+ {
+ jam();
+ infoEvent("Take over of node %d complete", takeOverPtr.p->toStartingNode);
+ setNodeActiveStatus(takeOverPtr.p->toStartingNode, Sysfile::NS_Active);
+ takeOverPtr.p->toMasterStatus = TakeOverRecord::WAIT_LCP;
+ takeOverCompleted(takeOverPtr.p->toStartingNode);
+ checkToCopy();
+ checkToCopyCompleted(signal);
+ return;
+ }
+
c_lcpState.immediateLcpStart = true;
takeOverPtr.p->toMasterStatus = TakeOverRecord::WAIT_LCP;
@@ -3434,16 +3490,12 @@ void Dbdih::execEND_TOCONF(Signal* signal)
}//if
endTakeOver(takeOverPtr.i);
- ndbout_c("2 - endTakeOver");
if (cstartPhase == ZNDB_SPH4) {
jam();
- ndbrequire(false);
if (anyActiveTakeOver()) {
jam();
- ndbout_c("4 - anyActiveTakeOver == true");
return;
}//if
- ndbout_c("5 - anyActiveTakeOver == false -> ndbsttorry10Lab");
ndbsttorry10Lab(signal, __LINE__);
return;
}//if
@@ -6488,7 +6540,13 @@ void Dbdih::execCREATE_FRAGMENTATION_REQ(Signal * signal){
}//for
}
}
- ndbrequire(count == (2 + noOfReplicas * noOfFragments));
+ if(count != (2 + noOfReplicas * noOfFragments)){
+ char buf[255];
+ BaseString::snprintf(buf, sizeof(buf),
+ "Illegal configuration change: NoOfReplicas."
+ " Can't be applied online ");
+ progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, buf);
+ }
CreateFragmentationConf * const conf =
(CreateFragmentationConf*)signal->getDataPtrSend();
@@ -8415,14 +8473,33 @@ Dbdih::resetReplicaSr(TabRecordPtr tabPtr){
resetReplicaLcp(replicaPtr.p, newestRestorableGCI);
- /* -----------------------------------------------------------------
- * LINK THE REPLICA INTO THE STORED REPLICA LIST. WE WILL USE THIS
- * NODE AS A STORED REPLICA.
- * WE MUST FIRST LINK IT OUT OF THE LIST OF OLD STORED REPLICAS.
- * --------------------------------------------------------------- */
- removeOldStoredReplica(fragPtr, replicaPtr);
- linkStoredReplica(fragPtr, replicaPtr);
-
+ /**
+ * Make sure we can also find REDO for restoring replica...
+ */
+ {
+ CreateReplicaRecord createReplica;
+ ConstPtr<ReplicaRecord> constReplicaPtr;
+ constReplicaPtr.i = replicaPtr.i;
+ constReplicaPtr.p = replicaPtr.p;
+ if (tabPtr.p->storedTable == 0 ||
+ setup_create_replica(fragPtr,
+ &createReplica, constReplicaPtr))
+ {
+ jam();
+ removeOldStoredReplica(fragPtr, replicaPtr);
+ linkStoredReplica(fragPtr, replicaPtr);
+ }
+ else
+ {
+ jam();
+ infoEvent("Forcing take-over of node %d due to unsufficient REDO"
+ " for table %d fragment: %d",
+ nodePtr.i, tabPtr.i, i);
+
+ setNodeActiveStatus(nodePtr.i,
+ Sysfile::NS_NotActive_NotTakenOver);
+ }
+ }
}
default:
jam();
@@ -9466,6 +9543,7 @@ void Dbdih::calculateKeepGciLab(Signal* signal, Uint32 tableId, Uint32 fragId)
FragmentstorePtr fragPtr;
getFragstore(tabPtr.p, fragId, fragPtr);
checkKeepGci(tabPtr, fragId, fragPtr.p, fragPtr.p->storedReplicas);
+ checkKeepGci(tabPtr, fragId, fragPtr.p, fragPtr.p->oldStoredReplicas);
fragId++;
if (fragId >= tabPtr.p->totalfragments) {
jam();
@@ -9651,73 +9729,84 @@ void Dbdih::startNextChkpt(Signal* signal)
nodePtr.i = replicaPtr.p->procNode;
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
- if (replicaPtr.p->lcpOngoingFlag &&
- replicaPtr.p->lcpIdStarted < lcpId) {
- jam();
- //-------------------------------------------------------------------
- // We have found a replica on a node that performs local checkpoint
- // that is alive and that have not yet been started.
- //-------------------------------------------------------------------
-
- if (nodePtr.p->noOfStartedChkpt < 2) {
- jam();
- /**
- * Send LCP_FRAG_ORD to LQH
- */
-
- /**
- * Mark the replica so with lcpIdStarted == true
- */
- replicaPtr.p->lcpIdStarted = lcpId;
-
- Uint32 i = nodePtr.p->noOfStartedChkpt;
- nodePtr.p->startedChkpt[i].tableId = tabPtr.i;
- nodePtr.p->startedChkpt[i].fragId = curr.fragmentId;
- nodePtr.p->startedChkpt[i].replicaPtr = replicaPtr.i;
- nodePtr.p->noOfStartedChkpt = i + 1;
-
- sendLCP_FRAG_ORD(signal, nodePtr.p->startedChkpt[i]);
- } else if (nodePtr.p->noOfQueuedChkpt < 2) {
- jam();
- /**
- * Put LCP_FRAG_ORD "in queue"
- */
-
- /**
- * Mark the replica so with lcpIdStarted == true
- */
- replicaPtr.p->lcpIdStarted = lcpId;
+ if (c_lcpState.m_participatingLQH.get(nodePtr.i))
+ {
+ if (replicaPtr.p->lcpOngoingFlag &&
+ replicaPtr.p->lcpIdStarted < lcpId)
+ {
+ jam();
+ //-------------------------------------------------------------------
+ // We have found a replica on a node that performs local checkpoint
+ // that is alive and that have not yet been started.
+ //-------------------------------------------------------------------
- Uint32 i = nodePtr.p->noOfQueuedChkpt;
- nodePtr.p->queuedChkpt[i].tableId = tabPtr.i;
- nodePtr.p->queuedChkpt[i].fragId = curr.fragmentId;
- nodePtr.p->queuedChkpt[i].replicaPtr = replicaPtr.i;
- nodePtr.p->noOfQueuedChkpt = i + 1;
- } else {
- jam();
+ if (nodePtr.p->noOfStartedChkpt < 2)
+ {
+ jam();
+ /**
+ * Send LCP_FRAG_ORD to LQH
+ */
+
+ /**
+ * Mark the replica so with lcpIdStarted == true
+ */
+ replicaPtr.p->lcpIdStarted = lcpId;
- if(save){
+ Uint32 i = nodePtr.p->noOfStartedChkpt;
+ nodePtr.p->startedChkpt[i].tableId = tabPtr.i;
+ nodePtr.p->startedChkpt[i].fragId = curr.fragmentId;
+ nodePtr.p->startedChkpt[i].replicaPtr = replicaPtr.i;
+ nodePtr.p->noOfStartedChkpt = i + 1;
+
+ sendLCP_FRAG_ORD(signal, nodePtr.p->startedChkpt[i]);
+ }
+ else if (nodePtr.p->noOfQueuedChkpt < 2)
+ {
+ jam();
/**
- * Stop increasing value on first that was "full"
+ * Put LCP_FRAG_ORD "in queue"
*/
- c_lcpState.currentFragment = curr;
- save = false;
- }
-
- busyNodes.set(nodePtr.i);
- if(busyNodes.count() == lcpNodes){
+
/**
- * There were no possibility to start the local checkpoint
- * and it was not possible to queue it up. In this case we
- * stop the start of local checkpoints until the nodes with a
- * backlog have performed more checkpoints. We will return and
- * will not continue the process of starting any more checkpoints.
+ * Mark the replica so with lcpIdStarted == true
*/
- return;
+ replicaPtr.p->lcpIdStarted = lcpId;
+
+ Uint32 i = nodePtr.p->noOfQueuedChkpt;
+ nodePtr.p->queuedChkpt[i].tableId = tabPtr.i;
+ nodePtr.p->queuedChkpt[i].fragId = curr.fragmentId;
+ nodePtr.p->queuedChkpt[i].replicaPtr = replicaPtr.i;
+ nodePtr.p->noOfQueuedChkpt = i + 1;
+ }
+ else
+ {
+ jam();
+
+ if(save)
+ {
+ /**
+ * Stop increasing value on first that was "full"
+ */
+ c_lcpState.currentFragment = curr;
+ save = false;
+ }
+
+ busyNodes.set(nodePtr.i);
+ if(busyNodes.count() == lcpNodes)
+ {
+ /**
+ * There were no possibility to start the local checkpoint
+ * and it was not possible to queue it up. In this case we
+ * stop the start of local checkpoints until the nodes with a
+ * backlog have performed more checkpoints. We will return and
+ * will not continue the process of starting any more checkpoints.
+ */
+ return;
+ }//if
}//if
- }//if
- }
- }//while
+ }
+ }//while
+ }
curr.fragmentId++;
if (curr.fragmentId >= tabPtr.p->totalfragments) {
jam();
@@ -12450,16 +12539,75 @@ void Dbdih::removeTooNewCrashedReplicas(ReplicaRecordPtr rtnReplicaPtr)
/* CHECKPOINT WITHOUT NEEDING ANY EXTRA LOGGING FACILITIES.*/
/* A MAXIMUM OF FOUR NODES IS RETRIEVED. */
/*************************************************************************/
+bool
+Dbdih::setup_create_replica(FragmentstorePtr fragPtr,
+ CreateReplicaRecord* createReplicaPtrP,
+ ConstPtr<ReplicaRecord> replicaPtr)
+{
+ createReplicaPtrP->dataNodeId = replicaPtr.p->procNode;
+ createReplicaPtrP->replicaRec = replicaPtr.i;
+
+ /* ----------------------------------------------------------------- */
+ /* WE NEED TO SEARCH FOR A PROPER LOCAL CHECKPOINT TO USE FOR THE */
+ /* SYSTEM RESTART. */
+ /* ----------------------------------------------------------------- */
+ Uint32 startGci;
+ Uint32 startLcpNo;
+ Uint32 stopGci = SYSFILE->newestRestorableGCI;
+ bool result = findStartGci(replicaPtr,
+ stopGci,
+ startGci,
+ startLcpNo);
+ if (!result)
+ {
+ jam();
+ /* --------------------------------------------------------------- */
+ /* WE COULD NOT FIND ANY LOCAL CHECKPOINT. THE FRAGMENT THUS DO NOT*/
+ /* CONTAIN ANY VALID LOCAL CHECKPOINT. IT DOES HOWEVER CONTAIN A */
+ /* VALID FRAGMENT LOG. THUS BY FIRST CREATING THE FRAGMENT AND THEN*/
+ /* EXECUTING THE FRAGMENT LOG WE CAN CREATE THE FRAGMENT AS */
+ /* DESIRED. THIS SHOULD ONLY OCCUR AFTER CREATING A FRAGMENT. */
+ /* */
+ /* TO INDICATE THAT NO LOCAL CHECKPOINT IS TO BE USED WE SET THE */
+ /* LOCAL CHECKPOINT TO ZNIL. */
+ /* --------------------------------------------------------------- */
+ createReplicaPtrP->lcpNo = ZNIL;
+ }
+ else
+ {
+ jam();
+ /* --------------------------------------------------------------- */
+ /* WE FOUND A PROPER LOCAL CHECKPOINT TO RESTART FROM. */
+ /* SET LOCAL CHECKPOINT ID AND LOCAL CHECKPOINT NUMBER. */
+ /* --------------------------------------------------------------- */
+ createReplicaPtrP->lcpNo = startLcpNo;
+ arrGuard(startLcpNo, MAX_LCP_STORED);
+ createReplicaPtrP->createLcpId = replicaPtr.p->lcpId[startLcpNo];
+ }//if
+
+
+ /* ----------------------------------------------------------------- */
+ /* WE HAVE EITHER FOUND A LOCAL CHECKPOINT OR WE ARE PLANNING TO */
+ /* EXECUTE THE LOG FROM THE INITIAL CREATION OF THE TABLE. IN BOTH */
+ /* CASES WE NEED TO FIND A SET OF LOGS THAT CAN EXECUTE SUCH THAT */
+ /* WE RECOVER TO THE SYSTEM RESTART GLOBAL CHECKPOINT. */
+ /* -_--------------------------------------------------------------- */
+ return findLogNodes(createReplicaPtrP, fragPtr, startGci, stopGci);
+}
+
void Dbdih::searchStoredReplicas(FragmentstorePtr fragPtr)
{
Uint32 nextReplicaPtrI;
- ConstPtr<ReplicaRecord> replicaPtr;
+ Ptr<ReplicaRecord> replicaPtr;
replicaPtr.i = fragPtr.p->storedReplicas;
while (replicaPtr.i != RNIL) {
jam();
ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord);
nextReplicaPtrI = replicaPtr.p->nextReplica;
+ ConstPtr<ReplicaRecord> constReplicaPtr;
+ constReplicaPtr.i = replicaPtr.i;
+ constReplicaPtr.p = replicaPtr.p;
NodeRecordPtr nodePtr;
nodePtr.i = replicaPtr.p->procNode;
ptrCheckGuard(nodePtr, MAX_NDB_NODES, nodeRecord);
@@ -12479,69 +12627,13 @@ void Dbdih::searchStoredReplicas(FragmentstorePtr fragPtr)
createReplicaPtr.i = cnoOfCreateReplicas;
ptrCheckGuard(createReplicaPtr, 4, createReplicaRecord);
cnoOfCreateReplicas++;
- createReplicaPtr.p->dataNodeId = replicaPtr.p->procNode;
- createReplicaPtr.p->replicaRec = replicaPtr.i;
- /* ----------------------------------------------------------------- */
- /* WE NEED TO SEARCH FOR A PROPER LOCAL CHECKPOINT TO USE FOR THE */
- /* SYSTEM RESTART. */
- /* ----------------------------------------------------------------- */
- Uint32 startGci;
- Uint32 startLcpNo;
- Uint32 stopGci = SYSFILE->newestRestorableGCI;
- bool result = findStartGci(replicaPtr,
- stopGci,
- startGci,
- startLcpNo);
- if (!result) {
- jam();
- /* --------------------------------------------------------------- */
- /* WE COULD NOT FIND ANY LOCAL CHECKPOINT. THE FRAGMENT THUS DO NOT*/
- /* CONTAIN ANY VALID LOCAL CHECKPOINT. IT DOES HOWEVER CONTAIN A */
- /* VALID FRAGMENT LOG. THUS BY FIRST CREATING THE FRAGMENT AND THEN*/
- /* EXECUTING THE FRAGMENT LOG WE CAN CREATE THE FRAGMENT AS */
- /* DESIRED. THIS SHOULD ONLY OCCUR AFTER CREATING A FRAGMENT. */
- /* */
- /* TO INDICATE THAT NO LOCAL CHECKPOINT IS TO BE USED WE SET THE */
- /* LOCAL CHECKPOINT TO ZNIL. */
- /* --------------------------------------------------------------- */
- createReplicaPtr.p->lcpNo = ZNIL;
- } else {
- jam();
- /* --------------------------------------------------------------- */
- /* WE FOUND A PROPER LOCAL CHECKPOINT TO RESTART FROM. */
- /* SET LOCAL CHECKPOINT ID AND LOCAL CHECKPOINT NUMBER. */
- /* --------------------------------------------------------------- */
- createReplicaPtr.p->lcpNo = startLcpNo;
- arrGuard(startLcpNo, MAX_LCP_STORED);
- createReplicaPtr.p->createLcpId = replicaPtr.p->lcpId[startLcpNo];
- }//if
-
- if(ERROR_INSERTED(7073) || ERROR_INSERTED(7074)){
- jam();
- nodePtr.p->nodeStatus = NodeRecord::DEAD;
- }
-
- /* ----------------------------------------------------------------- */
- /* WE HAVE EITHER FOUND A LOCAL CHECKPOINT OR WE ARE PLANNING TO */
- /* EXECUTE THE LOG FROM THE INITIAL CREATION OF THE TABLE. IN BOTH */
- /* CASES WE NEED TO FIND A SET OF LOGS THAT CAN EXECUTE SUCH THAT */
- /* WE RECOVER TO THE SYSTEM RESTART GLOBAL CHECKPOINT. */
- /* -_--------------------------------------------------------------- */
- if (!findLogNodes(createReplicaPtr.p, fragPtr, startGci, stopGci)) {
- jam();
- /* --------------------------------------------------------------- */
- /* WE WERE NOT ABLE TO FIND ANY WAY OF RESTORING THIS REPLICA. */
- /* THIS IS A POTENTIAL SYSTEM ERROR. */
- /* --------------------------------------------------------------- */
- cnoOfCreateReplicas--;
- return;
- }//if
-
- if(ERROR_INSERTED(7073) || ERROR_INSERTED(7074)){
- jam();
- nodePtr.p->nodeStatus = NodeRecord::ALIVE;
- }
+ /**
+ * Should have been checked in resetReplicaSr
+ */
+ ndbrequire(setup_create_replica(fragPtr,
+ createReplicaPtr.p,
+ constReplicaPtr));
break;
}
default:
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index d3ba8521226..299cad16ec1 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -2161,6 +2161,7 @@ private:
void execSTORED_PROCCONF(Signal* signal);
void execSTORED_PROCREF(Signal* signal);
void execCOPY_FRAGREQ(Signal* signal);
+ void execUPDATE_FRAG_DIST_KEY_ORD(Signal*);
void execCOPY_ACTIVEREQ(Signal* signal);
void execCOPY_STATEREQ(Signal* signal);
void execLQH_TRANSREQ(Signal* signal);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
index 04400f75255..ba18e20f4fb 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
@@ -335,7 +335,9 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_TUX_ADD_ATTRREF, &Dblqh::execTUX_ADD_ATTRREF);
addRecSignal(GSN_READ_PSUEDO_REQ, &Dblqh::execREAD_PSUEDO_REQ);
-
+ addRecSignal(GSN_UPDATE_FRAG_DIST_KEY_ORD,
+ &Dblqh::execUPDATE_FRAG_DIST_KEY_ORD);
+
initData();
#ifdef VM_TRACE
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index 7286481002f..4739450884c 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -9098,6 +9098,7 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
const CopyFragReq * const copyFragReq = (CopyFragReq *)&signal->theData[0];
tabptr.i = copyFragReq->tableId;
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
+ Uint32 i;
const Uint32 fragId = copyFragReq->fragId;
const Uint32 copyPtr = copyFragReq->userPtr;
const Uint32 userRef = copyFragReq->userRef;
@@ -9109,8 +9110,20 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
ndbrequire(cfirstfreeTcConrec != RNIL);
ndbrequire(fragptr.p->m_scanNumberMask.get(NR_ScanNo));
- fragptr.p->fragDistributionKey = copyFragReq->distributionKey;
-
+ Uint32 key = fragptr.p->fragDistributionKey = copyFragReq->distributionKey;
+
+ Uint32 checkversion = NDB_VERSION >= MAKE_VERSION(5,1,0) ?
+ NDBD_UPDATE_FRAG_DIST_KEY_51 : NDBD_UPDATE_FRAG_DIST_KEY_50;
+
+ Uint32 nodeCount = copyFragReq->nodeCount;
+ NdbNodeBitmask nodemask;
+ if (getNodeInfo(refToNode(userRef)).m_version >= checkversion)
+ {
+ ndbrequire(nodeCount <= MAX_REPLICAS);
+ for (i = 0; i<nodeCount; i++)
+ nodemask.set(copyFragReq->nodeList[i]);
+ }
+
if (DictTabInfo::isOrderedIndex(tabptr.p->tableType)) {
jam();
/**
@@ -9184,9 +9197,42 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
req->savePointId = tcConnectptr.p->savePointId;
sendSignal(tcConnectptr.p->tcAccBlockref, GSN_ACC_SCANREQ, signal,
AccScanReq::SignalLength, JBB);
+
+ if (! nodemask.isclear())
+ {
+ ndbrequire(nodemask.get(getOwnNodeId()));
+ ndbrequire(nodemask.get(nodeId)); // cpy dest
+ nodemask.clear(getOwnNodeId());
+ nodemask.clear(nodeId);
+
+ UpdateFragDistKeyOrd*
+ ord = (UpdateFragDistKeyOrd*)signal->getDataPtrSend();
+ ord->tableId = tabptr.i;
+ ord->fragId = fragId;
+ ord->fragDistributionKey = key;
+ i = 0;
+ while ((i = nodemask.find(i+1)) != NdbNodeBitmask::NotFound)
+ {
+ if (getNodeInfo(i).m_version >= checkversion)
+ sendSignal(calcLqhBlockRef(i), GSN_UPDATE_FRAG_DIST_KEY_ORD,
+ signal, UpdateFragDistKeyOrd::SignalLength, JBB);
+ }
+ }
return;
}//Dblqh::execCOPY_FRAGREQ()
+void
+Dblqh::execUPDATE_FRAG_DIST_KEY_ORD(Signal * signal)
+{
+ jamEntry();
+ UpdateFragDistKeyOrd* ord =(UpdateFragDistKeyOrd*)signal->getDataPtr();
+
+ tabptr.i = ord->tableId;
+ ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
+ ndbrequire(getFragmentrec(signal, ord->fragId));
+ fragptr.p->fragDistributionKey = ord->fragDistributionKey;
+}
+
void Dblqh::accScanConfCopyLab(Signal* signal)
{
AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
@@ -18437,6 +18483,18 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal)
if(tabPtr.p->tableStatus != Tablerec::NOT_DEFINED){
infoEvent("Table %d Status: %d Usage: %d",
i, tabPtr.p->tableStatus, tabPtr.p->usageCount);
+
+ for (Uint32 j = 0; j<MAX_FRAG_PER_NODE; j++)
+ {
+ FragrecordPtr fragPtr;
+ if ((fragPtr.i = tabPtr.p->fragrec[j]) != RNIL)
+ {
+ ptrCheckGuard(fragPtr, cfragrecFileSize, fragrecord);
+ infoEvent(" frag: %d distKey: %u",
+ tabPtr.p->fragid[j],
+ fragPtr.p->fragDistributionKey);
+ }
+ }
}
}
return;
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index dda743616f4..cc39219590f 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -1002,13 +1002,6 @@ Dbtc::handleFailedApiNode(Signal* signal,
TloopCount += 64;
break;
case CS_CONNECTED:
- /*********************************************************************/
- // The api record is connected to failed node. We need to release the
- // connection and set it in a disconnected state.
- /*********************************************************************/
- jam();
- releaseApiCon(signal, apiConnectptr.i);
- break;
case CS_REC_COMMITTING:
case CS_RECEIVING:
case CS_STARTED:
@@ -6312,6 +6305,18 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
break;
case CS_START_SCAN:{
jam();
+
+ /*
+ We are waiting for application to continue the transaction. In this
+ particular state we will use the application timeout parameter rather
+ than the shorter Deadlock detection timeout.
+ */
+ if (c_appl_timeout_value == 0 ||
+ (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
+ jam();
+ return;
+ }//if
+
ScanRecordPtr scanPtr;
scanPtr.i = apiConnectptr.p->apiScanRec;
ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
@@ -9832,6 +9837,17 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
conf->requestInfo = op_count | ScanTabConf::EndOfData;
releaseScanResources(scanPtr);
}
+ else
+ {
+ if (scanPtr.p->m_running_scan_frags.isEmpty())
+ {
+ jam();
+ /**
+ * All scan frags delivered...waiting for API
+ */
+ setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
+ }
+ }
if(4 + 3 * op_count > 25){
jam();
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
index 66e98bd2805..6b1056fdeac 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
@@ -142,6 +142,7 @@ Dbtup::Dbtup(const class Configuration & conf)
tablerec = 0;
tableDescriptor = 0;
undoPage = 0;
+ cnoOfPage = cnoOfAllocatedPages = 0;
}//Dbtup::Dbtup()
Dbtup::~Dbtup()
@@ -526,7 +527,7 @@ void Dbtup::execCONTINUEB(Signal* signal)
case ZREPORT_MEMORY_USAGE:{
ljam();
static int c_currentMemUsed = 0;
- int now = (cnoOfAllocatedPages * 100)/cnoOfPage;
+ int now = cnoOfPage ? (cnoOfAllocatedPages * 100)/cnoOfPage : 0;
const int thresholds[] = { 100, 90, 80, 0 };
Uint32 i = 0;
diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
index d4a44b9e641..9c4a38e9320 100644
--- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -23,6 +23,7 @@
#include <AttributeHeader.hpp>
#include <ArrayPool.hpp>
#include <DataBuffer.hpp>
+#include <DLFifoList.hpp>
#include <md5_hash.hpp>
// big brother
@@ -121,41 +122,17 @@ private:
// forward declarations
struct DescEnt;
- /*
- * Pointer to array of Uint32.
- */
- struct Data {
- private:
- Uint32* m_data;
- public:
- Data();
- Data(Uint32* data);
- Data& operator=(Uint32* data);
- operator Uint32*() const;
- Data& operator+=(size_t n);
- AttributeHeader& ah() const;
- };
- friend class Data;
+ // Pointer to array of Uint32 represents attribute data and bounds
- /*
- * Pointer to array of constant Uint32.
- */
- struct ConstData;
- friend struct ConstData;
- struct ConstData {
- private:
- const Uint32* m_data;
- public:
- ConstData();
- ConstData(const Uint32* data);
- ConstData& operator=(const Uint32* data);
- operator const Uint32*() const;
- ConstData& operator+=(size_t n);
- const AttributeHeader& ah() const;
- // non-const pointer can be cast to const pointer
- ConstData(Data data);
- ConstData& operator=(Data data);
- };
+ typedef Uint32 *Data;
+ inline AttributeHeader& ah(Data data) {
+ return *reinterpret_cast<AttributeHeader*>(data);
+ }
+
+ typedef const Uint32* ConstData;
+ inline const AttributeHeader& ah(ConstData data) {
+ return *reinterpret_cast<const AttributeHeader*>(data);
+ }
// AttributeHeader size is assumed to be 1 word
STATIC_CONST( AttributeHeaderSize = 1 );
@@ -212,6 +189,7 @@ private:
unsigned m_fragBit : 1; // which duplicated table fragment
TreeEnt();
// methods
+ bool eqtuple(const TreeEnt ent) const;
bool eq(const TreeEnt ent) const;
int cmp(const TreeEnt ent) const;
};
@@ -289,8 +267,7 @@ private:
struct TreePos {
TupLoc m_loc; // physical node address
Uint16 m_pos; // position 0 to m_occup
- Uint8 m_match; // at an existing entry
- Uint8 m_dir; // see scanNext()
+ Uint8 m_dir; // see scanNext
TreePos();
};
@@ -357,6 +334,18 @@ private:
typedef DataBuffer<ScanBoundSegmentSize>::ConstDataBufferIterator ScanBoundIterator;
typedef DataBuffer<ScanBoundSegmentSize>::DataBufferPool ScanBoundPool;
ScanBoundPool c_scanBoundPool;
+
+ // ScanLock
+ struct ScanLock {
+ Uint32 m_accLockOp;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+ typedef Ptr<ScanLock> ScanLockPtr;
+ ArrayPool<ScanLock> c_scanLockPool;
/*
* Scan operation.
@@ -381,12 +370,13 @@ private:
enum {
Undef = 0,
First = 1, // before first entry
- Current = 2, // at current before locking
- Blocked = 3, // at current waiting for ACC lock
- Locked = 4, // at current and locked or no lock needed
- Next = 5, // looking for next extry
- Last = 6, // after last entry
- Aborting = 7, // lock wait at scan close
+ Current = 2, // at some entry
+ Found = 3, // return current as next scan result
+ Blocked = 4, // found and waiting for ACC lock
+ Locked = 5, // found and locked or no lock needed
+ Next = 6, // looking for next extry
+ Last = 7, // after last entry
+ Aborting = 8, // lock wait at scan close
Invalid = 9 // cannot return REF to LQH currently
};
Uint16 m_state;
@@ -402,6 +392,8 @@ private:
Uint32 m_savePointId;
// lock waited for or obtained and not yet passed to LQH
Uint32 m_accLockOp;
+ // locks obtained and passed to LQH but not yet returned by LQH
+ DLFifoList<ScanLock>::Head m_accLockOps;
Uint8 m_readCommitted; // no locking
Uint8 m_lockMode;
Uint8 m_descending;
@@ -417,13 +409,6 @@ private:
Uint32 nextList;
};
Uint32 prevList;
- /*
- * Locks obtained and passed to LQH but not yet returned by LQH.
- * The max was increased from 16 to 992 (default 64). Record max
- * ever used in this scan. TODO fix quadratic behaviour
- */
- Uint32 m_maxAccLockOps;
- Uint32 m_accLockOps[MaxAccLockOps];
ScanOp(ScanBoundPool& scanBoundPool);
};
typedef Ptr<ScanOp> ScanOpPtr;
@@ -563,6 +548,7 @@ private:
void readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData);
void readTablePk(const Frag& frag, TreeEnt ent, Data pkData, unsigned& pkSize);
void copyAttrs(const Frag& frag, ConstData data1, Data data2, unsigned maxlen2 = MaxAttrDataSize);
+ void unpackBound(const ScanBound& bound, Data data);
/*
* DbtuxMeta.cpp
@@ -637,18 +623,21 @@ private:
void execACCKEYREF(Signal* signal);
void execACC_ABORTCONF(Signal* signal);
void scanFirst(ScanOpPtr scanPtr);
+ void scanFind(ScanOpPtr scanPtr);
void scanNext(ScanOpPtr scanPtr, bool fromMaintReq);
+ bool scanCheck(ScanOpPtr scanPtr, TreeEnt ent);
bool scanVisible(ScanOpPtr scanPtr, TreeEnt ent);
void scanClose(Signal* signal, ScanOpPtr scanPtr);
- void addAccLockOp(ScanOp& scan, Uint32 accLockOp);
- void removeAccLockOp(ScanOp& scan, Uint32 accLockOp);
+ void abortAccLockOps(Signal* signal, ScanOpPtr scanPtr);
+ void addAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp);
+ void removeAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp);
void releaseScanOp(ScanOpPtr& scanPtr);
/*
* DbtuxSearch.cpp
*/
- void searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
- void searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
+ bool searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
+ bool searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
void searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, bool descending, TreePos& treePos);
void searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
void searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
@@ -694,7 +683,8 @@ private:
DebugMeta = 1, // log create and drop index
DebugMaint = 2, // log maintenance ops
DebugTree = 4, // log and check tree after each op
- DebugScan = 8 // log scans
+ DebugScan = 8, // log scans
+ DebugLock = 16 // log ACC locks
};
STATIC_CONST( DataFillByte = 0xa2 );
STATIC_CONST( NodeFillByte = 0xa4 );
@@ -737,99 +727,6 @@ private:
static unsigned max(unsigned x, unsigned y);
};
-// Dbtux::Data
-
-inline
-Dbtux::Data::Data() :
- m_data(0)
-{
-}
-
-inline
-Dbtux::Data::Data(Uint32* data) :
- m_data(data)
-{
-}
-
-inline Dbtux::Data&
-Dbtux::Data::operator=(Uint32* data)
-{
- m_data = data;
- return *this;
-}
-
-inline
-Dbtux::Data::operator Uint32*() const
-{
- return m_data;
-}
-
-inline Dbtux::Data&
-Dbtux::Data::operator+=(size_t n)
-{
- m_data += n;
- return *this;
-}
-
-inline AttributeHeader&
-Dbtux::Data::ah() const
-{
- return *reinterpret_cast<AttributeHeader*>(m_data);
-}
-
-// Dbtux::ConstData
-
-inline
-Dbtux::ConstData::ConstData() :
- m_data(0)
-{
-}
-
-inline
-Dbtux::ConstData::ConstData(const Uint32* data) :
- m_data(data)
-{
-}
-
-inline Dbtux::ConstData&
-Dbtux::ConstData::operator=(const Uint32* data)
-{
- m_data = data;
- return *this;
-}
-
-inline
-Dbtux::ConstData::operator const Uint32*() const
-{
- return m_data;
-}
-
-inline Dbtux::ConstData&
-Dbtux::ConstData::operator+=(size_t n)
-{
- m_data += n;
- return *this;
-}
-
-inline const AttributeHeader&
-Dbtux::ConstData::ah() const
-{
- return *reinterpret_cast<const AttributeHeader*>(m_data);
-}
-
-inline
-Dbtux::ConstData::ConstData(Data data) :
- m_data(static_cast<Uint32*>(data))
-{
-}
-
-inline Dbtux::ConstData&
-Dbtux::ConstData::operator=(Data data)
-{
- m_data = static_cast<Uint32*>(data);
- return *this;
-}
-
// Dbtux::TupLoc
inline
@@ -899,6 +796,14 @@ Dbtux::TreeEnt::TreeEnt() :
}
inline bool
+Dbtux::TreeEnt::eqtuple(const TreeEnt ent) const
+{
+ return
+ m_tupLoc == ent.m_tupLoc &&
+ m_fragBit == ent.m_fragBit;
+}
+
+inline bool
Dbtux::TreeEnt::eq(const TreeEnt ent) const
{
return
@@ -910,6 +815,11 @@ Dbtux::TreeEnt::eq(const TreeEnt ent) const
inline int
Dbtux::TreeEnt::cmp(const TreeEnt ent) const
{
+ // compare frag first to improve cacheing in 5.0
+ if (m_fragBit < ent.m_fragBit)
+ return -1;
+ if (m_fragBit > ent.m_fragBit)
+ return +1;
if (m_tupLoc.getPageId() < ent.m_tupLoc.getPageId())
return -1;
if (m_tupLoc.getPageId() > ent.m_tupLoc.getPageId())
@@ -918,14 +828,25 @@ Dbtux::TreeEnt::cmp(const TreeEnt ent) const
return -1;
if (m_tupLoc.getPageOffset() > ent.m_tupLoc.getPageOffset())
return +1;
- if (m_tupVersion < ent.m_tupVersion)
- return -1;
- if (m_tupVersion > ent.m_tupVersion)
- return +1;
- if (m_fragBit < ent.m_fragBit)
- return -1;
- if (m_fragBit > ent.m_fragBit)
- return +1;
+ /*
+ * Guess if one tuple version has wrapped around. This is well
+ * defined ordering on existing versions since versions are assigned
+ * consecutively and different versions exists only on uncommitted
+ * tuple. Assuming max 2**14 uncommitted ops on same tuple.
+ */
+ const unsigned version_wrap_limit = (1 << (ZTUP_VERSION_BITS - 1));
+ if (m_tupVersion < ent.m_tupVersion) {
+ if (ent.m_tupVersion - m_tupVersion < version_wrap_limit)
+ return -1;
+ else
+ return +1;
+ }
+ if (m_tupVersion > ent.m_tupVersion) {
+ if (m_tupVersion - ent.m_tupVersion < version_wrap_limit)
+ return +1;
+ else
+ return -1;
+ }
return 0;
}
@@ -992,7 +913,6 @@ inline
Dbtux::TreePos::TreePos() :
m_loc(),
m_pos(ZNIL),
- m_match(false),
m_dir(255)
{
}
@@ -1028,6 +948,7 @@ Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
m_transId2(0),
m_savePointId(0),
m_accLockOp(RNIL),
+ m_accLockOps(),
m_readCommitted(0),
m_lockMode(0),
m_descending(0),
@@ -1035,18 +956,12 @@ Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
m_boundMax(scanBoundPool),
m_scanPos(),
m_scanEnt(),
- m_nodeScan(RNIL),
- m_maxAccLockOps(0)
+ m_nodeScan(RNIL)
{
m_bound[0] = &m_boundMin;
m_bound[1] = &m_boundMax;
m_boundCnt[0] = 0;
m_boundCnt[1] = 0;
-#ifdef VM_TRACE
- for (unsigned i = 0; i < MaxAccLockOps; i++) {
- m_accLockOps[i] = 0x1f1f1f1f;
- }
-#endif
}
// Dbtux::Index
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
index cf815b14c1a..058409c99b0 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp
@@ -34,7 +34,7 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, Cons
// skip to right position in search key only
for (unsigned i = 0; i < start; i++) {
jam();
- searchKey += AttributeHeaderSize + searchKey.ah().getDataSize();
+ searchKey += AttributeHeaderSize + ah(searchKey).getDataSize();
}
// number of words of entry data left
unsigned len2 = maxlen;
@@ -46,16 +46,16 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, Cons
break;
}
len2 -= AttributeHeaderSize;
- if (! searchKey.ah().isNULL()) {
- if (! entryData.ah().isNULL()) {
+ if (! ah(searchKey).isNULL()) {
+ if (! ah(entryData).isNULL()) {
jam();
// verify attribute id
const DescAttr& descAttr = descEnt.m_descAttr[start];
- ndbrequire(searchKey.ah().getAttributeId() == descAttr.m_primaryAttrId);
- ndbrequire(entryData.ah().getAttributeId() == descAttr.m_primaryAttrId);
+ ndbrequire(ah(searchKey).getAttributeId() == descAttr.m_primaryAttrId);
+ ndbrequire(ah(entryData).getAttributeId() == descAttr.m_primaryAttrId);
// sizes
- const unsigned size1 = searchKey.ah().getDataSize();
- const unsigned size2 = min(entryData.ah().getDataSize(), len2);
+ const unsigned size1 = ah(searchKey).getDataSize();
+ const unsigned size2 = min(ah(entryData).getDataSize(), len2);
len2 -= size2;
// compare
NdbSqlUtil::Cmp* const cmp = c_sqlCmp[start];
@@ -74,15 +74,15 @@ Dbtux::cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, Cons
break;
}
} else {
- if (! entryData.ah().isNULL()) {
+ if (! ah(entryData).isNULL()) {
jam();
// NULL < not NULL
ret = -1;
break;
}
}
- searchKey += AttributeHeaderSize + searchKey.ah().getDataSize();
- entryData += AttributeHeaderSize + entryData.ah().getDataSize();
+ searchKey += AttributeHeaderSize + ah(searchKey).getDataSize();
+ entryData += AttributeHeaderSize + ah(entryData).getDataSize();
start++;
}
return ret;
@@ -130,17 +130,17 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned idir, ConstData boundInfo, unsign
// get and skip bound type (it is used after the loop)
type = boundInfo[0];
boundInfo += 1;
- if (! boundInfo.ah().isNULL()) {
- if (! entryData.ah().isNULL()) {
+ if (! ah(boundInfo).isNULL()) {
+ if (! ah(entryData).isNULL()) {
jam();
// verify attribute id
- const Uint32 index = boundInfo.ah().getAttributeId();
+ const Uint32 index = ah(boundInfo).getAttributeId();
ndbrequire(index < frag.m_numAttrs);
const DescAttr& descAttr = descEnt.m_descAttr[index];
- ndbrequire(entryData.ah().getAttributeId() == descAttr.m_primaryAttrId);
+ ndbrequire(ah(entryData).getAttributeId() == descAttr.m_primaryAttrId);
// sizes
- const unsigned size1 = boundInfo.ah().getDataSize();
- const unsigned size2 = min(entryData.ah().getDataSize(), len2);
+ const unsigned size1 = ah(boundInfo).getDataSize();
+ const unsigned size2 = min(ah(entryData).getDataSize(), len2);
len2 -= size2;
// compare
NdbSqlUtil::Cmp* const cmp = c_sqlCmp[index];
@@ -159,14 +159,14 @@ Dbtux::cmpScanBound(const Frag& frag, unsigned idir, ConstData boundInfo, unsign
}
} else {
jam();
- if (! entryData.ah().isNULL()) {
+ if (! ah(entryData).isNULL()) {
jam();
// NULL < not NULL
return -1;
}
}
- boundInfo += AttributeHeaderSize + boundInfo.ah().getDataSize();
- entryData += AttributeHeaderSize + entryData.ah().getDataSize();
+ boundInfo += AttributeHeaderSize + ah(boundInfo).getDataSize();
+ entryData += AttributeHeaderSize + ah(entryData).getDataSize();
boundCount -= 1;
}
// all attributes were equal
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index ed29dc57915..4eb45c69501 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -311,7 +311,6 @@ operator<<(NdbOut& out, const Dbtux::TreePos& pos)
out << "[TreePos " << hex << &pos;
out << " [loc " << pos.m_loc << "]";
out << " [pos " << dec << pos.m_pos << "]";
- out << " [match " << dec << pos.m_match << "]";
out << " [dir " << dec << pos.m_dir << "]";
out << "]";
return out;
@@ -331,6 +330,7 @@ operator<<(NdbOut& out, const Dbtux::DescAttr& descAttr)
NdbOut&
operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
{
+ Dbtux* tux = (Dbtux*)globalData.getBlock(DBTUX);
out << "[ScanOp " << hex << &scan;
out << " [state " << dec << scan.m_state << "]";
out << " [lockwait " << dec << scan.m_lockwait << "]";
@@ -340,9 +340,15 @@ operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
out << " [savePointId " << dec << scan.m_savePointId << "]";
out << " [accLockOp " << hex << scan.m_accLockOp << "]";
out << " [accLockOps";
- for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
- if (scan.m_accLockOps[i] != RNIL)
- out << " " << hex << scan.m_accLockOps[i];
+ {
+ DLFifoList<Dbtux::ScanLock>::Head head = scan.m_accLockOps;
+ LocalDLFifoList<Dbtux::ScanLock> list(tux->c_scanLockPool, head);
+ Dbtux::ScanLockPtr lockPtr;
+ list.first(lockPtr);
+ while (lockPtr.i != RNIL) {
+ out << " " << hex << lockPtr.p->m_accLockOp;
+ list.next(lockPtr);
+ }
}
out << "]";
out << " [readCommitted " << dec << scan.m_readCommitted << "]";
@@ -368,13 +374,12 @@ operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
NdbOut&
operator<<(NdbOut& out, const Dbtux::Index& index)
{
+ Dbtux* tux = (Dbtux*)globalData.getBlock(DBTUX);
out << "[Index " << hex << &index;
out << " [tableId " << dec << index.m_tableId << "]";
out << " [numFrags " << dec << index.m_numFrags << "]";
for (unsigned i = 0; i < index.m_numFrags; i++) {
out << " [frag " << dec << i << " ";
- // dangerous and wrong
- Dbtux* tux = (Dbtux*)globalData.getBlock(DBTUX);
const Dbtux::Frag& frag = *tux->c_fragPool.getPtr(index.m_fragPtrI[i]);
out << frag;
out << "]";
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
index 5640fdf2899..e40f70ea397 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
@@ -159,6 +159,7 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal)
Uint32 nFragment;
Uint32 nAttribute;
Uint32 nScanOp;
+ Uint32 nScanBatch;
const ndb_mgm_configuration_iterator * p =
theConfiguration.getOwnConfigIterator();
@@ -168,9 +169,11 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal)
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_FRAGMENT, &nFragment));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_ATTRIBUTE, &nAttribute));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_BATCH_SIZE, &nScanBatch));
const Uint32 nDescPage = (nIndex * DescHeadSize + nAttribute * DescAttrSize + DescPageSize - 1) / DescPageSize;
const Uint32 nScanBoundWords = nScanOp * ScanBoundSegmentSize * 4;
+ const Uint32 nScanLock = nScanOp * nScanBatch;
c_indexPool.setSize(nIndex);
c_fragPool.setSize(nFragment);
@@ -178,6 +181,7 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal)
c_fragOpPool.setSize(MaxIndexFragments);
c_scanOpPool.setSize(nScanOp);
c_scanBoundPool.setSize(nScanBoundWords);
+ c_scanLockPool.setSize(nScanLock);
/*
* Index id is physical array index. We seize and initialize all
* index records now.
@@ -221,7 +225,7 @@ Dbtux::setKeyAttrs(const Frag& frag)
const DescAttr& descAttr = descEnt.m_descAttr[i];
Uint32 size = AttributeDescriptor::getSizeInWords(descAttr.m_attrDesc);
// set attr id and fixed size
- keyAttrs.ah() = AttributeHeader(descAttr.m_primaryAttrId, size);
+ ah(keyAttrs) = AttributeHeader(descAttr.m_primaryAttrId, size);
keyAttrs += 1;
// set comparison method pointer
const NdbSqlUtil::Type& sqlType = NdbSqlUtil::getTypeBinary(descAttr.m_typeId);
@@ -251,8 +255,8 @@ Dbtux::readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData)
ConstData data = keyData;
Uint32 totalSize = 0;
for (Uint32 i = start; i < frag.m_numAttrs; i++) {
- Uint32 attrId = data.ah().getAttributeId();
- Uint32 dataSize = data.ah().getDataSize();
+ Uint32 attrId = ah(data).getAttributeId();
+ Uint32 dataSize = ah(data).getDataSize();
debugOut << i << " attrId=" << attrId << " size=" << dataSize;
data += 1;
for (Uint32 j = 0; j < dataSize; j++) {
@@ -290,7 +294,7 @@ Dbtux::copyAttrs(const Frag& frag, ConstData data1, Data data2, unsigned maxlen2
unsigned len2 = maxlen2;
while (n != 0) {
jam();
- const unsigned dataSize = data1.ah().getDataSize();
+ const unsigned dataSize = ah(data1).getDataSize();
// copy header
if (len2 == 0)
return;
@@ -314,4 +318,17 @@ Dbtux::copyAttrs(const Frag& frag, ConstData data1, Data data2, unsigned maxlen2
#endif
}
+void
+Dbtux::unpackBound(const ScanBound& bound, Data dest)
+{
+ ScanBoundIterator iter;
+ bound.first(iter);
+ const unsigned n = bound.getSize();
+ unsigned j;
+ for (j = 0; j < n; j++) {
+ dest[j] = *iter.data;
+ bound.next(iter);
+ }
+}
+
BLOCK_FUNCTIONS(Dbtux)
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index 4b568badc67..e7138b4110d 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -113,16 +113,17 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
// do the operation
req->errorCode = 0;
TreePos treePos;
+ bool ok;
switch (opCode) {
case TuxMaintReq::OpAdd:
jam();
- searchToAdd(frag, c_searchKey, ent, treePos);
+ ok = searchToAdd(frag, c_searchKey, ent, treePos);
#ifdef VM_TRACE
if (debugFlags & DebugMaint) {
- debugOut << treePos << (treePos.m_match ? " - error" : "") << endl;
+ debugOut << treePos << (! ok ? " - error" : "") << endl;
}
#endif
- if (treePos.m_match) {
+ if (! ok) {
jam();
// there is no "Building" state so this will have to do
if (indexPtr.p->m_state == Index::Online) {
@@ -152,13 +153,13 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
break;
case TuxMaintReq::OpRemove:
jam();
- searchToRemove(frag, c_searchKey, ent, treePos);
+ ok = searchToRemove(frag, c_searchKey, ent, treePos);
#ifdef VM_TRACE
if (debugFlags & DebugMaint) {
- debugOut << treePos << (! treePos.m_match ? " - error" : "") << endl;
+ debugOut << treePos << (! ok ? " - error" : "") << endl;
}
#endif
- if (! treePos.m_match) {
+ if (! ok) {
jam();
// there is no "Building" state so this will have to do
if (indexPtr.p->m_state == Index::Online) {
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index a61b7c1f5ca..6d9385b3989 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -312,7 +312,7 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
jamEntry();
ndbrequire(lockReq->returnCode == AccLockReq::Success);
- removeAccLockOp(scan, req->accOperationPtr);
+ removeAccLockOp(scanPtr, req->accOperationPtr);
}
if (req->scanFlag == NextScanReq::ZSCAN_COMMIT) {
jam();
@@ -421,21 +421,17 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
jam();
// search is done only once in single range scan
scanFirst(scanPtr);
-#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "First scan " << scanPtr.i << " " << scan << endl;
- }
-#endif
}
- if (scan.m_state == ScanOp::Next) {
+ if (scan.m_state == ScanOp::Current ||
+ scan.m_state == ScanOp::Next) {
jam();
// look for next
- scanNext(scanPtr, false);
+ scanFind(scanPtr);
}
- // for reading tuple key in Current or Locked state
+ // for reading tuple key in Found or Locked state
Data pkData = c_dataBuffer;
unsigned pkSize = 0; // indicates not yet done
- if (scan.m_state == ScanOp::Current) {
+ if (scan.m_state == ScanOp::Found) {
// found an entry to return
jam();
ndbrequire(scan.m_accLockOp == RNIL);
@@ -470,7 +466,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
scan.m_state = ScanOp::Locked;
scan.m_accLockOp = lockReq->accOpPtr;
#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
+ if (debugFlags & (DebugScan | DebugLock)) {
debugOut << "Lock immediate scan " << scanPtr.i << " " << scan << endl;
}
#endif
@@ -482,7 +478,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
scan.m_lockwait = true;
scan.m_accLockOp = lockReq->accOpPtr;
#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
+ if (debugFlags & (DebugScan | DebugLock)) {
debugOut << "Lock wait scan " << scanPtr.i << " " << scan << endl;
}
#endif
@@ -509,8 +505,8 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
jam();
// max ops should depend on max scans (assert only)
ndbassert(false);
- // stay in Current state
- scan.m_state = ScanOp::Current;
+ // stay in Found state
+ scan.m_state = ScanOp::Found;
signal->theData[0] = scan.m_userPtr;
signal->theData[1] = true;
EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
@@ -538,7 +534,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
if (accLockOp != RNIL) {
scan.m_accLockOp = RNIL;
// remember it until LQH unlocks it
- addAccLockOp(scan, accLockOp);
+ addAccLockOp(scanPtr, accLockOp);
} else {
ndbrequire(scan.m_readCommitted);
// operation RNIL in LQH would signal no tuple returned
@@ -593,7 +589,7 @@ Dbtux::execACCKEYCONF(Signal* signal)
c_scanOpPool.getPtr(scanPtr);
ScanOp& scan = *scanPtr.p;
#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
+ if (debugFlags & (DebugScan | DebugLock)) {
debugOut << "Lock obtained scan " << scanPtr.i << " " << scan << endl;
}
#endif
@@ -638,7 +634,7 @@ Dbtux::execACCKEYREF(Signal* signal)
c_scanOpPool.getPtr(scanPtr);
ScanOp& scan = *scanPtr.p;
#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
+ if (debugFlags & (DebugScan | DebugLock)) {
debugOut << "Lock refused scan " << scanPtr.i << " " << scan << endl;
}
#endif
@@ -682,7 +678,7 @@ Dbtux::execACC_ABORTCONF(Signal* signal)
c_scanOpPool.getPtr(scanPtr);
ScanOp& scan = *scanPtr.p;
#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
+ if (debugFlags & (DebugScan | DebugLock)) {
debugOut << "ACC_ABORTCONF scan " << scanPtr.i << " " << scan << endl;
}
#endif
@@ -697,44 +693,95 @@ Dbtux::execACC_ABORTCONF(Signal* signal)
}
/*
- * Find start position for single range scan. If it exists, sets state
- * to Next and links the scan to the node. The first entry is returned
- * by scanNext.
+ * Find start position for single range scan.
*/
void
Dbtux::scanFirst(ScanOpPtr scanPtr)
{
ScanOp& scan = *scanPtr.p;
Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Enter first scan " << scanPtr.i << " " << scan << endl;
+ }
+#endif
TreeHead& tree = frag.m_tree;
// set up index keys for this operation
setKeyAttrs(frag);
// scan direction 0, 1
const unsigned idir = scan.m_descending;
- // unpack start key into c_dataBuffer
- const ScanBound& bound = *scan.m_bound[idir];
- ScanBoundIterator iter;
- bound.first(iter);
- for (unsigned j = 0; j < bound.getSize(); j++) {
- jam();
- c_dataBuffer[j] = *iter.data;
- bound.next(iter);
- }
+ unpackBound(*scan.m_bound[idir], c_dataBuffer);
TreePos treePos;
searchToScan(frag, c_dataBuffer, scan.m_boundCnt[idir], scan.m_descending, treePos);
- if (treePos.m_loc == NullTupLoc) {
- // empty result set
+ if (treePos.m_loc != NullTupLoc) {
+ scan.m_scanPos = treePos;
+ // link the scan to node found
+ NodeHandle node(frag);
+ selectNode(node, treePos.m_loc);
+ linkScan(node, scanPtr);
+ if (treePos.m_dir == 3) {
+ jam();
+ // check upper bound
+ TreeEnt ent = node.getEnt(treePos.m_pos);
+ if (scanCheck(scanPtr, ent))
+ scan.m_state = ScanOp::Current;
+ else
+ scan.m_state = ScanOp::Last;
+ } else {
+ scan.m_state = ScanOp::Next;
+ }
+ } else {
jam();
scan.m_state = ScanOp::Last;
- return;
}
- // set position and state
- scan.m_scanPos = treePos;
- scan.m_state = ScanOp::Next;
- // link the scan to node found
- NodeHandle node(frag);
- selectNode(node, treePos.m_loc);
- linkScan(node, scanPtr);
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Leave first scan " << scanPtr.i << " " << scan << endl;
+ }
+#endif
+}
+
+/*
+ * Look for entry to return as scan result.
+ */
+void
+Dbtux::scanFind(ScanOpPtr scanPtr)
+{
+ ScanOp& scan = *scanPtr.p;
+ Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Enter find scan " << scanPtr.i << " " << scan << endl;
+ }
+#endif
+ ndbrequire(scan.m_state == ScanOp::Current || scan.m_state == ScanOp::Next);
+ while (1) {
+ jam();
+ if (scan.m_state == ScanOp::Next)
+ scanNext(scanPtr, false);
+ if (scan.m_state == ScanOp::Current) {
+ jam();
+ const TreePos pos = scan.m_scanPos;
+ NodeHandle node(frag);
+ selectNode(node, pos.m_loc);
+ const TreeEnt ent = node.getEnt(pos.m_pos);
+ if (scanVisible(scanPtr, ent)) {
+ jam();
+ scan.m_state = ScanOp::Found;
+ scan.m_scanEnt = ent;
+ break;
+ }
+ } else {
+ jam();
+ break;
+ }
+ scan.m_state = ScanOp::Next;
+ }
+#ifdef VM_TRACE
+ if (debugFlags & DebugScan) {
+ debugOut << "Leave find scan " << scanPtr.i << " " << scan << endl;
+ }
+#endif
}
/*
@@ -752,6 +799,11 @@ Dbtux::scanFirst(ScanOpPtr scanPtr)
*
* If an entry was found, scan direction is 3. Therefore tree
* re-organizations need not worry about scan direction.
+ *
+ * This method is also used to move a scan when its entry is removed
+ * (see moveScanList). If the scan is Blocked, we check if it remains
+ * Blocked on a different version of the tuple. Otherwise the tuple is
+ * lost and state becomes Current.
*/
void
Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
@@ -759,8 +811,8 @@ Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
ScanOp& scan = *scanPtr.p;
Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Next in scan " << scanPtr.i << " " << scan << endl;
+ if (debugFlags & (DebugMaint | DebugScan)) {
+ debugOut << "Enter next scan " << scanPtr.i << " " << scan << endl;
}
#endif
// cannot be moved away from tuple we have locked
@@ -770,15 +822,6 @@ Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
// scan direction
const unsigned idir = scan.m_descending; // 0, 1
const int jdir = 1 - 2 * (int)idir; // 1, -1
- // unpack end key into c_dataBuffer
- const ScanBound& bound = *scan.m_bound[1 - idir];
- ScanBoundIterator iter;
- bound.first(iter);
- for (unsigned j = 0; j < bound.getSize(); j++) {
- jam();
- c_dataBuffer[j] = *iter.data;
- bound.next(iter);
- }
// use copy of position
TreePos pos = scan.m_scanPos;
// get and remember original node
@@ -792,15 +835,14 @@ Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
while (true) {
jam();
#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Scan next pos " << pos << " " << node << endl;
+ if (debugFlags & (DebugMaint | DebugScan)) {
+ debugOut << "Current scan " << scanPtr.i << " pos " << pos << " node " << node << endl;
}
#endif
if (pos.m_dir == 2) {
// coming up from root ends the scan
jam();
pos.m_loc = NullTupLoc;
- scan.m_state = ScanOp::Last;
break;
}
if (node.m_loc != pos.m_loc) {
@@ -832,41 +874,22 @@ Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
if (pos.m_dir == idir) {
// coming up from left child scan current node
jam();
- pos.m_pos = idir == 0 ? 0 : occup - 1;
- pos.m_match = false;
+ pos.m_pos = idir == 0 ? (Uint16)-1 : occup;
pos.m_dir = 3;
}
if (pos.m_dir == 3) {
- // within node
+ // before or within node
jam();
- // advance position
- if (! pos.m_match)
- pos.m_match = true;
- else
- // becomes ZNIL (which is > occup) if 0 and scan descending
- pos.m_pos += jdir;
+ // advance position - becomes ZNIL (> occup) if 0 and descending
+ pos.m_pos += jdir;
if (pos.m_pos < occup) {
jam();
- ent = node.getEnt(pos.m_pos);
pos.m_dir = 3; // unchanged
- // read and compare all attributes
- readKeyAttrs(frag, ent, 0, c_entryKey);
- int ret = cmpScanBound(frag, 1 - idir, c_dataBuffer, scan.m_boundCnt[1 - idir], c_entryKey);
- ndbrequire(ret != NdbSqlUtil::CmpUnknown);
- if (jdir * ret < 0) {
+ ent = node.getEnt(pos.m_pos);
+ if (! scanCheck(scanPtr, ent)) {
jam();
- // hit upper bound of single range scan
pos.m_loc = NullTupLoc;
- scan.m_state = ScanOp::Last;
- break;
- }
- // can we see it
- if (! scanVisible(scanPtr, ent)) {
- jam();
- continue;
}
- // found entry
- scan.m_state = ScanOp::Current;
break;
}
// after node proceed to right child
@@ -892,31 +915,64 @@ Dbtux::scanNext(ScanOpPtr scanPtr, bool fromMaintReq)
// copy back position
scan.m_scanPos = pos;
// relink
- if (scan.m_state == ScanOp::Current) {
- ndbrequire(pos.m_match == true && pos.m_dir == 3);
+ if (pos.m_loc != NullTupLoc) {
+ ndbrequire(pos.m_dir == 3);
ndbrequire(pos.m_loc == node.m_loc);
if (origNode.m_loc != node.m_loc) {
jam();
unlinkScan(origNode, scanPtr);
linkScan(node, scanPtr);
}
- // copy found entry
- scan.m_scanEnt = ent;
- } else if (scan.m_state == ScanOp::Last) {
+ if (scan.m_state != ScanOp::Blocked) {
+ scan.m_state = ScanOp::Current;
+ } else {
+ jam();
+ ndbrequire(fromMaintReq);
+ TreeEnt& scanEnt = scan.m_scanEnt;
+ ndbrequire(scanEnt.m_tupLoc != NullTupLoc);
+ if (scanEnt.eqtuple(ent)) {
+ // remains blocked on another version
+ scanEnt = ent;
+ } else {
+ jam();
+ scanEnt.m_tupLoc = NullTupLoc;
+ scan.m_state = ScanOp::Current;
+ }
+ }
+ } else {
jam();
- ndbrequire(pos.m_loc == NullTupLoc);
unlinkScan(origNode, scanPtr);
- } else {
- ndbrequire(false);
+ scan.m_state = ScanOp::Last;
}
#ifdef VM_TRACE
- if (debugFlags & DebugScan) {
- debugOut << "Next out scan " << scanPtr.i << " " << scan << endl;
+ if (debugFlags & (DebugMaint | DebugScan)) {
+ debugOut << "Leave next scan " << scanPtr.i << " " << scan << endl;
}
#endif
}
/*
+ * Check end key. Return true if scan is still within range.
+ */
+bool
+Dbtux::scanCheck(ScanOpPtr scanPtr, TreeEnt ent)
+{
+ ScanOp& scan = *scanPtr.p;
+ Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
+ const unsigned idir = scan.m_descending;
+ const int jdir = 1 - 2 * (int)idir;
+ unpackBound(*scan.m_bound[1 - idir], c_dataBuffer);
+ unsigned boundCnt = scan.m_boundCnt[1 - idir];
+ readKeyAttrs(frag, ent, 0, c_entryKey);
+ int ret = cmpScanBound(frag, 1 - idir, c_dataBuffer, boundCnt, c_entryKey);
+ ndbrequire(ret != NdbSqlUtil::CmpUnknown);
+ if (jdir * ret > 0)
+ return true;
+ // hit upper bound of single range scan
+ return false;
+}
+
+/*
* Check if an entry is visible to the scan.
*
* There is a special check to never accept same tuple twice in a row.
@@ -957,18 +1013,9 @@ Dbtux::scanClose(Signal* signal, ScanOpPtr scanPtr)
ScanOp& scan = *scanPtr.p;
ndbrequire(! scan.m_lockwait && scan.m_accLockOp == RNIL);
// unlock all not unlocked by LQH
- for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
- if (scan.m_accLockOps[i] != RNIL) {
- jam();
- AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
- lockReq->returnCode = RNIL;
- lockReq->requestInfo = AccLockReq::Abort;
- lockReq->accOpPtr = scan.m_accLockOps[i];
- EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
- jamEntry();
- ndbrequire(lockReq->returnCode == AccLockReq::Success);
- scan.m_accLockOps[i] = RNIL;
- }
+ if (! scan.m_accLockOps.isEmpty()) {
+ jam();
+ abortAccLockOps(signal, scanPtr);
}
// send conf
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
@@ -982,44 +1029,76 @@ Dbtux::scanClose(Signal* signal, ScanOpPtr scanPtr)
}
void
-Dbtux::addAccLockOp(ScanOp& scan, Uint32 accLockOp)
+Dbtux::abortAccLockOps(Signal* signal, ScanOpPtr scanPtr)
{
- ndbrequire(accLockOp != RNIL);
- Uint32* list = scan.m_accLockOps;
- bool ok = false;
- for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
- ndbrequire(list[i] != accLockOp);
- if (! ok && list[i] == RNIL) {
- list[i] = accLockOp;
- ok = true;
- // continue check for duplicates
- }
+ ScanOp& scan = *scanPtr.p;
+#ifdef VM_TRACE
+ if (debugFlags & (DebugScan | DebugLock)) {
+ debugOut << "Abort locks in scan " << scanPtr.i << " " << scan << endl;
}
- if (! ok) {
- unsigned i = scan.m_maxAccLockOps;
- if (i < MaxAccLockOps) {
- list[i] = accLockOp;
- ok = true;
- scan.m_maxAccLockOps = i + 1;
- }
+#endif
+ LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
+ ScanLockPtr lockPtr;
+ while (list.first(lockPtr)) {
+ jam();
+ AccLockReq* const lockReq = (AccLockReq*)signal->getDataPtrSend();
+ lockReq->returnCode = RNIL;
+ lockReq->requestInfo = AccLockReq::Abort;
+ lockReq->accOpPtr = lockPtr.p->m_accLockOp;
+ EXECUTE_DIRECT(DBACC, GSN_ACC_LOCKREQ, signal, AccLockReq::UndoSignalLength);
+ jamEntry();
+ ndbrequire(lockReq->returnCode == AccLockReq::Success);
+ list.release(lockPtr);
}
- ndbrequire(ok);
}
void
-Dbtux::removeAccLockOp(ScanOp& scan, Uint32 accLockOp)
+Dbtux::addAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp)
{
+ ScanOp& scan = *scanPtr.p;
+#ifdef VM_TRACE
+ if (debugFlags & (DebugScan | DebugLock)) {
+ debugOut << "Add lock " << hex << accLockOp << dec
+ << " to scan " << scanPtr.i << " " << scan << endl;
+ }
+#endif
+ LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
+ ScanLockPtr lockPtr;
+#ifdef VM_TRACE
+ list.first(lockPtr);
+ while (lockPtr.i != RNIL) {
+ ndbrequire(lockPtr.p->m_accLockOp != accLockOp);
+ list.next(lockPtr);
+ }
+#endif
+ bool ok = list.seize(lockPtr);
+ ndbrequire(ok);
ndbrequire(accLockOp != RNIL);
- Uint32* list = scan.m_accLockOps;
- bool ok = false;
- for (unsigned i = 0; i < scan.m_maxAccLockOps; i++) {
- if (list[i] == accLockOp) {
- list[i] = RNIL;
- ok = true;
+ lockPtr.p->m_accLockOp = accLockOp;
+}
+
+void
+Dbtux::removeAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp)
+{
+ ScanOp& scan = *scanPtr.p;
+#ifdef VM_TRACE
+ if (debugFlags & (DebugScan | DebugLock)) {
+ debugOut << "Remove lock " << hex << accLockOp << dec
+ << " from scan " << scanPtr.i << " " << scan << endl;
+ }
+#endif
+ LocalDLFifoList<ScanLock> list(c_scanLockPool, scan.m_accLockOps);
+ ScanLockPtr lockPtr;
+ list.first(lockPtr);
+ while (lockPtr.i != RNIL) {
+ if (lockPtr.p->m_accLockOp == accLockOp) {
+ jam();
break;
}
+ list.next(lockPtr);
}
- ndbrequire(ok);
+ ndbrequire(lockPtr.i != RNIL);
+ list.release(lockPtr);
}
/*
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
index b0e2a664bfd..da2321bdf6f 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp
@@ -21,22 +21,18 @@
* Search for entry to add.
*
* Similar to searchToRemove (see below).
- *
- * TODO optimize for initial equal attrs in node min/max
*/
-void
+bool
Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
{
const TreeHead& tree = frag.m_tree;
const unsigned numAttrs = frag.m_numAttrs;
NodeHandle currNode(frag);
currNode.m_loc = tree.m_root;
- // assume success
- treePos.m_match = false;
if (currNode.m_loc == NullTupLoc) {
// empty tree
jam();
- return;
+ return true;
}
NodeHandle glbNode(frag); // potential g.l.b of final node
/*
@@ -94,9 +90,8 @@ Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos&
jam();
treePos.m_loc = currNode.m_loc;
treePos.m_pos = 0;
- // failed
- treePos.m_match = true;
- return;
+ // entry found - error
+ return false;
}
break;
}
@@ -104,7 +99,7 @@ Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos&
treePos.m_loc = currNode.m_loc;
// binary search
int lo = -1;
- unsigned hi = currNode.getOccup();
+ int hi = currNode.getOccup();
int ret;
while (1) {
jam();
@@ -126,9 +121,8 @@ Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos&
lo = j;
else {
treePos.m_pos = j;
- // failed
- treePos.m_match = true;
- return;
+ // entry found - error
+ return false;
}
if (hi - lo == 1)
break;
@@ -136,22 +130,23 @@ Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos&
if (ret < 0) {
jam();
treePos.m_pos = hi;
- return;
+ return true;
}
- if (hi < currNode.getOccup()) {
+ if ((uint) hi < currNode.getOccup()) {
jam();
treePos.m_pos = hi;
- return;
+ return true;
}
if (bottomNode.isNull()) {
jam();
treePos.m_pos = hi;
- return;
+ return true;
}
jam();
// backwards compatible for now
treePos.m_loc = bottomNode.m_loc;
treePos.m_pos = 0;
+ return true;
}
/*
@@ -163,21 +158,17 @@ Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos&
* then the saved node is the g.l.b of the final node and we move back
* to it.
*/
-void
+bool
Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
{
const TreeHead& tree = frag.m_tree;
const unsigned numAttrs = frag.m_numAttrs;
NodeHandle currNode(frag);
currNode.m_loc = tree.m_root;
- // assume success
- treePos.m_match = true;
if (currNode.m_loc == NullTupLoc) {
- // empty tree
+ // empty tree - failed
jam();
- // failed
- treePos.m_match = false;
- return;
+ return false;
}
NodeHandle glbNode(frag); // potential g.l.b of final node
while (true) {
@@ -229,7 +220,7 @@ Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePo
jam();
treePos.m_loc = currNode.m_loc;
treePos.m_pos = 0;
- return;
+ return true;
}
break;
}
@@ -242,12 +233,12 @@ Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePo
if (searchEnt.eq(currNode.getEnt(j))) {
jam();
treePos.m_pos = j;
- return;
+ return true;
}
}
treePos.m_pos = currNode.getOccup();
- // failed
- treePos.m_match = false;
+ // not found - failed
+ return false;
}
/*
@@ -278,8 +269,6 @@ Dbtux::searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCoun
currNode.m_loc = tree.m_root;
NodeHandle glbNode(frag); // potential g.l.b of final node
NodeHandle bottomNode(frag);
- // always before entry
- treePos.m_match = false;
while (true) {
jam();
selectNode(currNode, currNode.m_loc);
@@ -315,7 +304,7 @@ Dbtux::searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCoun
treePos.m_dir = 3;
return;
}
- } else if (ret > 0) {
+ } else {
// bound is at or right of this node
jam();
const TupLoc loc = currNode.getLink(1);
@@ -327,8 +316,6 @@ Dbtux::searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCoun
currNode.m_loc = loc;
continue;
}
- } else {
- ndbrequire(false);
}
break;
}
@@ -369,8 +356,6 @@ Dbtux::searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCou
currNode.m_loc = tree.m_root;
NodeHandle glbNode(frag); // potential g.l.b of final node
NodeHandle bottomNode(frag);
- // always before entry
- treePos.m_match = false;
while (true) {
jam();
selectNode(currNode, currNode.m_loc);
@@ -403,7 +388,7 @@ Dbtux::searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCou
// empty result set
return;
}
- } else if (ret > 0) {
+ } else {
// bound is at or right of this node
jam();
const TupLoc loc = currNode.getLink(1);
@@ -415,8 +400,6 @@ Dbtux::searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCou
currNode.m_loc = loc;
continue;
}
- } else {
- ndbrequire(false);
}
break;
}
diff --git a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
index fe6caf04d8c..af05eeb9e9a 100644
--- a/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
+++ b/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
@@ -1524,6 +1524,11 @@ void Ndbcntr::execNODE_FAILREP(Signal* signal)
break;
}
+ case StopRecord::SR_BLOCK_GCP_START_GCP:
+ case StopRecord::SR_WAIT_COMPLETE_GCP:
+ case StopRecord::SR_UNBLOCK_GCP_START_GCP:
+ case StopRecord::SR_CLUSTER_SHUTDOWN:
+ break;
}
}
@@ -2273,7 +2278,33 @@ Ndbcntr::StopRecord::checkNodeFail(Signal* signal){
{
NdbNodeBitmask tmp;
tmp.assign(NdbNodeBitmask::Size, stopReq.nodes);
+
+ NdbNodeBitmask ndbStopNodes;
+ ndbStopNodes.assign(NdbNodeBitmask::Size, stopReq.nodes);
+ ndbStopNodes.bitAND(ndbMask);
+ ndbStopNodes.copyto(NdbNodeBitmask::Size, stopReq.nodes);
+
ndbMask.bitANDC(tmp);
+
+ bool allNodesStopped = true;
+ int i ;
+ for( i = 0; i < (int) NdbNodeBitmask::Size; i++ ){
+ if ( stopReq.nodes[i] != 0 ){
+ allNodesStopped = false;
+ break;
+ }
+ }
+
+ if ( allNodesStopped ) {
+ StopConf * const stopConf = (StopConf *)&signal->theData[0];
+ stopConf->senderData = stopReq.senderData;
+ stopConf->nodeState = (Uint32) NodeState::SL_NOTHING;
+ cntr.sendSignal(stopReq.senderRef, GSN_STOP_CONF, signal,
+ StopConf::SignalLength, JBB);
+ stopReq.senderRef = 0;
+ return false;
+ }
+
}
else
{
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index cc981f37987..68e649d8ae0 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -153,13 +153,14 @@ void Qmgr::execCONTINUEB(Signal* signal)
return;
}
Uint64 now = NdbTick_CurrentMillisecond();
+
if (now > (c_start_election_time + c_restartFailureTimeout))
{
jam();
BaseString tmp;
tmp.append("Shutting down node as total restart time exceeds "
" StartFailureTimeout as set in config file ");
- if(c_restartFailureTimeout == ~0)
+ if(c_restartFailureTimeout == (Uint32) ~0)
tmp.append(" 0 (inifinite)");
else
tmp.appfmt(" %d", c_restartFailureTimeout);
@@ -698,7 +699,40 @@ void Qmgr::execCM_REGREQ(Signal* signal)
sendCmRegrefLab(signal, Tblockref, CmRegRef::ZNOT_IN_CFG);
return;
}
-
+
+ if (getNodeState().getSingleUserMode())
+ {
+ /**
+ * The cluster is in single user mode.
+ * Data node is not allowed to get added in the cluster
+ * while in single user mode.
+ */
+ // handle rolling upgrade
+ {
+ unsigned int get_major = getMajor(startingVersion);
+ unsigned int get_minor = getMinor(startingVersion);
+ unsigned int get_build = getBuild(startingVersion);
+
+ if (startingVersion < NDBD_QMGR_SINGLEUSER_VERSION_5) {
+ jam();
+
+ infoEvent("QMGR: detect upgrade: new node %u old version %u.%u.%u",
+ (unsigned int)addNodePtr.i, get_major, get_minor, get_build);
+ /**
+ * The new node is old version, send ZINCOMPATIBLE_VERSION instead
+ * of ZSINGLE_USER_MODE.
+ */
+ sendCmRegrefLab(signal, Tblockref, CmRegRef::ZINCOMPATIBLE_VERSION);
+ } else {
+ jam();
+
+ sendCmRegrefLab(signal, Tblockref, CmRegRef::ZSINGLE_USER_MODE);
+ }//if
+ }
+
+ return;
+ }//if
+
ptrCheckGuard(addNodePtr, MAX_NDB_NODES, nodeRec);
Phase phase = addNodePtr.p->phase;
if (phase != ZINIT)
@@ -1093,6 +1127,19 @@ void Qmgr::execCM_REGREF(Signal* signal)
jam();
progError(__LINE__, NDBD_EXIT_NODE_NOT_DEAD);
break;
+ case CmRegRef::ZSINGLE_USER_MODE:
+ jam();
+ progError(__LINE__, NDBD_EXIT_SINGLE_USER_MODE);
+ break;
+ /**
+ * For generic refuse error.
+ * e.g. in online upgrade, we can use this error code instead
+ * of the incompatible error code.
+ */
+ case CmRegRef::ZGENERIC:
+ jam();
+ progError(__LINE__, NDBD_EXIT_GENERIC);
+ break;
case CmRegRef::ZELECTION:
jam();
if (candidate_gci > c_start.m_president_candidate_gci ||
@@ -1292,7 +1339,7 @@ Qmgr::check_startup(Signal* signal)
if (now < partial_timeout)
{
jam();
- signal->theData[1] = c_restartPartialTimeout == ~0 ? 2 : 3;
+ signal->theData[1] = c_restartPartialTimeout == (Uint32) ~0 ? 2 : 3;
signal->theData[2] = Uint32((partial_timeout - now + 500) / 1000);
report_mask.assign(wait);
retVal = 0;
@@ -1309,7 +1356,7 @@ Qmgr::check_startup(Signal* signal)
case CheckNodeGroups::Partitioning:
if (now < partitioned_timeout && result != CheckNodeGroups::Win)
{
- signal->theData[1] = c_restartPartionedTimeout == ~0 ? 4 : 5;
+ signal->theData[1] = c_restartPartionedTimeout == (Uint32) ~0 ? 4 : 5;
signal->theData[2] = Uint32((partitioned_timeout - now + 500) / 1000);
report_mask.assign(c_definedNodes);
report_mask.bitANDC(c_start.m_starting_nodes);
@@ -1356,6 +1403,7 @@ missing_nodegroup:
" starting: %s (missing fs for: %s)",
mask1, mask2);
progError(__LINE__, NDBD_EXIT_SR_RESTARTCONFLICT, buf);
+ return 0; // Deadcode
}
void
@@ -2025,7 +2073,7 @@ void Qmgr::initData(Signal* signal)
&c_restartPartionedTimeout);
ndb_mgm_get_int_parameter(p, CFG_DB_START_FAILURE_TIMEOUT,
&c_restartFailureTimeout);
-
+
if(c_restartPartialTimeout == 0)
{
c_restartPartialTimeout = ~0;
diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp
index 6c8bb1fe615..e95cd5c132f 100644
--- a/ndb/src/kernel/error/ErrorReporter.cpp
+++ b/ndb/src/kernel/error/ErrorReporter.cpp
@@ -185,6 +185,7 @@ ErrorReporter::handleAssert(const char* message, const char* file, int line, int
childReportError(ec);
NdbShutdown(s_errorHandlerShutdownType);
+ exit(1); // Deadcode
}
void
diff --git a/ndb/src/kernel/error/ErrorReporter.hpp b/ndb/src/kernel/error/ErrorReporter.hpp
index 0ec84190238..dffec14dff2 100644
--- a/ndb/src/kernel/error/ErrorReporter.hpp
+++ b/ndb/src/kernel/error/ErrorReporter.hpp
@@ -29,7 +29,7 @@ public:
static void setErrorHandlerShutdownType(NdbShutdownType nst = NST_ErrorHandler);
static void handleAssert(const char* message,
const char* file,
- int line, int ec = NDBD_EXIT_PRGERR);
+ int line, int ec = NDBD_EXIT_PRGERR) __attribute__((__noreturn__));
static void handleError(int faultID,
const char* problemData,
diff --git a/ndb/src/kernel/error/ndbd_exit_codes.c b/ndb/src/kernel/error/ndbd_exit_codes.c
index cb3272b38a9..205af85575a 100644
--- a/ndb/src/kernel/error/ndbd_exit_codes.c
+++ b/ndb/src/kernel/error/ndbd_exit_codes.c
@@ -14,6 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include <ndb_global.h>
#include <ndbd_exit_codes.h>
typedef struct ErrStruct {
@@ -45,6 +46,7 @@ typedef struct ErrStruct {
static const ErrStruct errArray[] =
{
+ {NDBD_EXIT_GENERIC, XRE, "Generic error"},
{NDBD_EXIT_PRGERR, XIE, "Assertion"},
{NDBD_EXIT_NODE_NOT_IN_CONFIG, XCE,
"node id in the configuration has the wrong type, (i.e. not an NDB node)"},
@@ -68,6 +70,8 @@ static const ErrStruct errArray[] =
"No more free UNDO log, increase UndoIndexBuffer"},
{NDBD_EXIT_SR_UNDOLOG, XFI,
"Error while reading the datapages and UNDO log"},
+ {NDBD_EXIT_SINGLE_USER_MODE, XRE, "Data node is not allowed to get added "
+ "to the cluster while it is in single user mode"},
{NDBD_EXIT_MEMALLOC, XCE, "Memory allocation failure, "
"please decrease some configuration parameters"},
{NDBD_EXIT_BLOCK_JBUFCONGESTION, XIE, "Job buffer congestion"},
diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp
index 7d1a5ed2ff4..13947f4b309 100644
--- a/ndb/src/kernel/vm/Configuration.cpp
+++ b/ndb/src/kernel/vm/Configuration.cpp
@@ -58,11 +58,14 @@ NDB_STD_OPTS_VARS;
// XXX should be my_bool ???
static int _daemon, _no_daemon, _foreground, _initial, _no_start;
static int _initialstart;
-static const char* _nowait_nodes;
+static const char* _nowait_nodes = 0;
+static const char* _bind_address = 0;
extern Uint32 g_start_type;
extern NdbNodeBitmask g_nowait_nodes;
+const char *load_default_groups[]= { "mysql_cluster","ndbd",0 };
+
/**
* Arguments to NDB process
*/
@@ -98,6 +101,10 @@ static struct my_option my_long_options[] =
"Perform initial start",
(gptr*) &_initialstart, (gptr*) &_initialstart, 0,
GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "bind-address", OPT_NOWAIT_NODES,
+ "Local bind address",
+ (gptr*) &_bind_address, (gptr*) &_bind_address, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
static void short_usage_sub(void)
@@ -108,6 +115,8 @@ static void usage()
{
short_usage_sub();
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
@@ -115,7 +124,6 @@ static void usage()
bool
Configuration::init(int argc, char** argv)
{
- const char *load_default_groups[]= { "mysql_cluster","ndbd",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
@@ -257,7 +265,9 @@ Configuration::fetch_configuration(){
m_mgmd_port= 0;
m_config_retriever= new ConfigRetriever(getConnectString(),
- NDB_VERSION, NODE_TYPE_DB);
+ NDB_VERSION,
+ NODE_TYPE_DB,
+ _bind_address);
if (m_config_retriever->hasError())
{
diff --git a/ndb/src/kernel/vm/DLFifoList.hpp b/ndb/src/kernel/vm/DLFifoList.hpp
index 963ab007b65..877a93110e2 100644
--- a/ndb/src/kernel/vm/DLFifoList.hpp
+++ b/ndb/src/kernel/vm/DLFifoList.hpp
@@ -34,6 +34,8 @@ public:
Head();
Uint32 firstItem;
Uint32 lastItem;
+
+ inline bool isEmpty() const { return firstItem == RNIL;}
};
DLFifoList(ArrayPool<T> & thePool);
diff --git a/ndb/src/kernel/vm/TransporterCallback.cpp b/ndb/src/kernel/vm/TransporterCallback.cpp
index f315918b871..badd2af669c 100644
--- a/ndb/src/kernel/vm/TransporterCallback.cpp
+++ b/ndb/src/kernel/vm/TransporterCallback.cpp
@@ -56,7 +56,7 @@ const char *lookupConnectionError(Uint32 err)
{
int i= 0;
while ((Uint32)connectionError[i].err != err &&
- (Uint32)connectionError[i].err != -1)
+ connectionError[i].err != -1)
i++;
return connectionError[i].text;
}
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index 9bf19dda3a4..8aa4f7213de 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -107,6 +107,7 @@ struct ndb_mgm_handle {
int mgmd_version_major;
int mgmd_version_minor;
int mgmd_version_build;
+ char * m_bindaddress;
};
#define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
@@ -162,6 +163,7 @@ ndb_mgm_create_handle()
h->cfg_i = -1;
h->errstream = stdout;
h->m_name = 0;
+ h->m_bindaddress = 0;
strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
@@ -176,7 +178,7 @@ ndb_mgm_create_handle()
h->mgmd_version_minor= -1;
h->mgmd_version_build= -1;
- DBUG_PRINT("info", ("handle=0x%x", (UintPtr)h));
+ DBUG_PRINT("info", ("handle: 0x%lx", (long)h));
DBUG_RETURN(h);
}
@@ -193,7 +195,7 @@ int
ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
{
DBUG_ENTER("ndb_mgm_set_connectstring");
- DBUG_PRINT("info", ("handle=0x%x", (UintPtr)handle));
+ DBUG_PRINT("info", ("handle: 0x%lx", (long)handle));
handle->cfg.~LocalConfig();
new (&(handle->cfg)) LocalConfig;
if (!handle->cfg.init(mgmsrv, 0) ||
@@ -209,6 +211,22 @@ ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
DBUG_RETURN(0);
}
+extern "C"
+int
+ndb_mgm_set_bindaddress(NdbMgmHandle handle, const char * arg)
+{
+ DBUG_ENTER("ndb_mgm_set_bindaddress");
+ if (handle->m_bindaddress)
+ free(handle->m_bindaddress);
+
+ if (arg)
+ handle->m_bindaddress = strdup(arg);
+ else
+ handle->m_bindaddress = 0;
+
+ DBUG_RETURN(0);
+}
+
/**
* Destroy a handle
*/
@@ -219,7 +237,7 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
DBUG_ENTER("ndb_mgm_destroy_handle");
if(!handle)
DBUG_VOID_RETURN;
- DBUG_PRINT("info", ("handle=0x%x", (UintPtr)(* handle)));
+ DBUG_PRINT("info", ("handle: 0x%lx", (long)(* handle)));
/**
* important! only disconnect if connected
* other code relies on this
@@ -235,6 +253,8 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
#endif
(*handle)->cfg.~LocalConfig();
my_free((*handle)->m_name, MYF(MY_ALLOW_ZERO_PTR));
+ if ((*handle)->m_bindaddress)
+ free((*handle)->m_bindaddress);
my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
* handle = 0;
DBUG_VOID_RETURN;
@@ -427,6 +447,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
BaseString::snprintf(logname, 64, "mgmapi.log");
handle->logfile = fopen(logname, "w");
#endif
+ char buf[1024];
/**
* Do connect
@@ -434,6 +455,50 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
LocalConfig &cfg= handle->cfg;
NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
Uint32 i;
+ int binderror = 0;
+ SocketClient s(0, 0);
+ if (!s.init())
+ {
+ fprintf(handle->errstream,
+ "Unable to create socket, "
+ "while trying to connect with connect string: %s\n",
+ cfg.makeConnectString(buf,sizeof(buf)));
+
+ setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
+ "Unable to create socket, "
+ "while trying to connect with connect string: %s\n",
+ cfg.makeConnectString(buf,sizeof(buf)));
+ DBUG_RETURN(-1);
+ }
+
+ if (handle->m_bindaddress)
+ {
+ BaseString::snprintf(buf, sizeof(buf), handle->m_bindaddress);
+ unsigned short portno = 0;
+ char * port = strchr(buf, ':');
+ if (port != 0)
+ {
+ portno = atoi(port+1);
+ * port = 0;
+ }
+ int err;
+ if ((err = s.bind(buf, portno)) != 0)
+ {
+ fprintf(handle->errstream,
+ "Unable to bind local address %s errno: %d, "
+ "while trying to connect with connect string: %s\n",
+ handle->m_bindaddress, err,
+ cfg.makeConnectString(buf,sizeof(buf)));
+
+ setError(handle, NDB_MGM_BIND_ADDRESS, __LINE__,
+ "Unable to bind local address %s errno: %d, "
+ "while trying to connect with connect string: %s\n",
+ handle->m_bindaddress, err,
+ cfg.makeConnectString(buf,sizeof(buf)));
+ DBUG_RETURN(-1);
+ }
+ }
+
while (sockfd == NDB_INVALID_SOCKET)
{
// do all the mgmt servers
@@ -441,8 +506,7 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
{
if (cfg.ids[i].type != MgmId_TCP)
continue;
- SocketClient s(cfg.ids[i].name.c_str(), cfg.ids[i].port);
- sockfd = s.connect();
+ sockfd = s.connect(cfg.ids[i].name.c_str(), cfg.ids[i].port);
if (sockfd != NDB_INVALID_SOCKET)
break;
}
@@ -450,19 +514,17 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
break;
#ifndef DBUG_OFF
{
- char buf[1024];
DBUG_PRINT("info",("Unable to connect with connect string: %s",
cfg.makeConnectString(buf,sizeof(buf))));
}
#endif
if (verbose > 0) {
- char buf[1024];
- fprintf(handle->errstream, "Unable to connect with connect string: %s\n",
+ fprintf(handle->errstream,
+ "Unable to connect with connect string: %s\n",
cfg.makeConnectString(buf,sizeof(buf)));
verbose= -1;
}
if (no_retries == 0) {
- char buf[1024];
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
"Unable to connect with connect string: %s",
cfg.makeConnectString(buf,sizeof(buf)));
@@ -503,6 +565,18 @@ ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
}
/**
+ * Only used for low level testing
+ * Never to be used by end user.
+ * Or anybody who doesn't know exactly what they're doing.
+ */
+extern "C"
+int
+ndb_mgm_get_fd(NdbMgmHandle handle)
+{
+ return handle->socket;
+}
+
+/**
* Disconnect from a mgm server
*/
extern "C"
@@ -692,22 +766,16 @@ ndb_mgm_get_status(NdbMgmHandle handle)
SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
return NULL;
}
- if(buf[strlen(buf)-1] == '\n')
- buf[strlen(buf)-1] = '\0';
-
- if(strcmp("node status", buf) != 0) {
+ if(strcmp("node status\n", buf) != 0) {
SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
return NULL;
}
-
if(!in.gets(buf, sizeof(buf)))
{
SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, "Probably disconnected");
return NULL;
}
- if(buf[strlen(buf)-1] == '\n')
- buf[strlen(buf)-1] = '\0';
-
+
BaseString tmp(buf);
Vector<BaseString> split;
tmp.split(split, ":");
@@ -715,7 +783,7 @@ ndb_mgm_get_status(NdbMgmHandle handle)
SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
return NULL;
}
-
+
if(!(split[0].trim() == "nodes")){
SET_ERROR(handle, NDB_MGM_ILLEGAL_NODE_STATUS, buf);
return NULL;
@@ -1300,6 +1368,45 @@ ndb_mgm_get_event_category_string(enum ndb_mgm_event_category status)
return 0;
}
+static const char *clusterlog_names[]=
+ { "startup", "shutdown", "statistics", "checkpoint", "noderestart", "connection", "info", "warning", "error", "congestion", "debug", "backup" };
+
+extern "C"
+const unsigned int *
+ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle)
+{
+ SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_loglevel");
+ int loglevel_count = CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1 ;
+ static unsigned int loglevel[CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1] = {0,0,0,0,0,0,0,0,0,0,0,0};
+ const ParserRow<ParserDummy> getloglevel_reply[] = {
+ MGM_CMD("get cluster loglevel", NULL, ""),
+ MGM_ARG(clusterlog_names[0], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[1], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[2], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[3], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[4], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[5], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[6], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[7], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[8], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[9], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[10], Int, Mandatory, ""),
+ MGM_ARG(clusterlog_names[11], Int, Mandatory, ""),
+ };
+ CHECK_HANDLE(handle, NULL);
+ CHECK_CONNECTED(handle, NULL);
+
+ Properties args;
+ const Properties *reply;
+ reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args);
+ CHECK_REPLY(reply, NULL);
+
+ for(int i=0; i < loglevel_count; i++) {
+ reply->get(clusterlog_names[i], &loglevel[i]);
+ }
+ return loglevel;
+}
+
extern "C"
int
ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId,
@@ -2280,7 +2387,6 @@ ndb_mgm_check_connection(NdbMgmHandle handle){
SocketOutputStream out(handle->socket);
SocketInputStream in(handle->socket, handle->read_timeout);
char buf[32];
-
if (out.println("check connection"))
goto ndb_mgm_check_connection_error;
@@ -2459,8 +2565,8 @@ int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length)
args.put("length", length);
BaseString data_string;
- for (int i = 0; i < length; i++)
- data_string.appfmt(" %u", data[i]);
+ for (int i = 0; i < (int) length; i++)
+ data_string.appfmt(" %lu", (ulong) data[i]);
args.put("data", data_string.c_str());
@@ -2490,7 +2596,6 @@ int ndb_mgm_end_session(NdbMgmHandle handle)
SocketInputStream in(handle->socket, handle->read_timeout);
char buf[32];
-
in.gets(buf, sizeof(buf));
DBUG_RETURN(0);
diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp
index ba68f6e4f0a..1dacd9689e8 100644
--- a/ndb/src/mgmclient/CommandInterpreter.cpp
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp
@@ -55,11 +55,11 @@ public:
*
* @return true until quit/bye/exit has been typed
*/
- int execute(const char *_line, int _try_reconnect=-1, int *error= 0);
+ int execute(const char *_line, int _try_reconnect=-1, bool interactive=1, int *error= 0);
private:
void printError();
- int execute_impl(const char *_line);
+ int execute_impl(const char *_line, bool interactive=1);
/**
* Analyse the command line, after the first token.
@@ -68,10 +68,11 @@ private:
* command will be sent to all DB processes.
* @param allAfterFirstToken: What the client gave after the
* first token on the command line
+ * @return: 0 if analyseAfterFirstToken succeeds, otherwise -1
*/
- void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
+ int analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
- void executeCommand(Vector<BaseString> &command_list,
+ int executeCommand(Vector<BaseString> &command_list,
unsigned command_pos,
int *node_ids, int no_of_nodes);
/**
@@ -97,54 +98,54 @@ private:
* this case "22". Each function is responsible to check the parameters
* argument.
*/
- void executeHelp(char* parameters);
- void executeShow(char* parameters);
- void executeConnect(char* parameters);
- void executePurge(char* parameters);
+ int executeHelp(char* parameters);
+ int executeShow(char* parameters);
+ int executePurge(char* parameters);
+ int executeConnect(char* parameters, bool interactive);
int executeShutdown(char* parameters);
void executeRun(char* parameters);
void executeInfo(char* parameters);
void executeClusterLog(char* parameters);
public:
- void executeStop(int processId, const char* parameters, bool all);
- void executeStop(Vector<BaseString> &command_list, unsigned command_pos,
+ int executeStop(int processId, const char* parameters, bool all);
+ int executeEnterSingleUser(char* parameters);
+ int executeExitSingleUser(char* parameters);
+ int executeStart(int processId, const char* parameters, bool all);
+ int executeRestart(int processId, const char* parameters, bool all);
+ int executeLogLevel(int processId, const char* parameters, bool all);
+ int executeError(int processId, const char* parameters, bool all);
+ int executeLog(int processId, const char* parameters, bool all);
+ int executeLogIn(int processId, const char* parameters, bool all);
+ int executeLogOut(int processId, const char* parameters, bool all);
+ int executeLogOff(int processId, const char* parameters, bool all);
+ int executeTestOn(int processId, const char* parameters, bool all);
+ int executeTestOff(int processId, const char* parameters, bool all);
+ int executeSet(int processId, const char* parameters, bool all);
+ int executeGetStat(int processId, const char* parameters, bool all);
+ int executeStatus(int processId, const char* parameters, bool all);
+ int executeEventReporting(int processId, const char* parameters, bool all);
+ int executeDumpState(int processId, const char* parameters, bool all);
+ int executeStartBackup(char * parameters);
+ int executeAbortBackup(char * parameters);
+ int executeStop(Vector<BaseString> &command_list, unsigned command_pos,
int *node_ids, int no_of_nodes);
- void executeEnterSingleUser(char* parameters);
- void executeExitSingleUser(char* parameters);
- void executeStart(int processId, const char* parameters, bool all);
- void executeRestart(int processId, const char* parameters, bool all);
- void executeRestart(Vector<BaseString> &command_list, unsigned command_pos,
+ int executeRestart(Vector<BaseString> &command_list, unsigned command_pos,
int *node_ids, int no_of_nodes);
- void executeLogLevel(int processId, const char* parameters, bool all);
- void executeError(int processId, const char* parameters, bool all);
- void executeLog(int processId, const char* parameters, bool all);
- void executeLogIn(int processId, const char* parameters, bool all);
- void executeLogOut(int processId, const char* parameters, bool all);
- void executeLogOff(int processId, const char* parameters, bool all);
- void executeTestOn(int processId, const char* parameters, bool all);
- void executeTestOff(int processId, const char* parameters, bool all);
- void executeSet(int processId, const char* parameters, bool all);
- void executeGetStat(int processId, const char* parameters, bool all);
- void executeStatus(int processId, const char* parameters, bool all);
- void executeEventReporting(int processId, const char* parameters, bool all);
- void executeDumpState(int processId, const char* parameters, bool all);
- int executeStartBackup(char * parameters);
- void executeAbortBackup(char * parameters);
-
- void executeRep(char* parameters);
+
+ int executeRep(char* parameters);
void executeCpc(char * parameters);
public:
- bool connect();
+ bool connect(bool interactive);
bool disconnect();
/**
* A execute function definition
*/
public:
- typedef void (CommandInterpreter::* ExecuteFunction)(int processId,
+ typedef int (CommandInterpreter::* ExecuteFunction)(int processId,
const char * param,
bool all);
@@ -156,7 +157,7 @@ private:
/**
*
*/
- void executeForAll(const char * cmd,
+ int executeForAll(const char * cmd,
ExecuteFunction fun,
const char * param);
@@ -198,9 +199,9 @@ Ndb_mgmclient::~Ndb_mgmclient()
{
delete m_cmd;
}
-int Ndb_mgmclient::execute(const char *_line, int _try_reconnect, int *error)
+int Ndb_mgmclient::execute(const char *_line, int _try_reconnect, bool interactive, int *error)
{
- return m_cmd->execute(_line,_try_reconnect,error);
+ return m_cmd->execute(_line,_try_reconnect,interactive, error);
}
int
Ndb_mgmclient::disconnect()
@@ -246,7 +247,7 @@ extern "C" {
#include <util/InputStream.hpp>
#include <util/OutputStream.hpp>
-int Ndb_mgmclient::execute(int argc, char** argv, int _try_reconnect, int *error)
+int Ndb_mgmclient::execute(int argc, char** argv, int _try_reconnect, bool interactive, int *error)
{
if (argc <= 0)
return 0;
@@ -255,7 +256,7 @@ int Ndb_mgmclient::execute(int argc, char** argv, int _try_reconnect, int *error
{
_line.appfmt(" %s", argv[i]);
}
- return m_cmd->execute(_line.c_str(),_try_reconnect, error);
+ return m_cmd->execute(_line.c_str(),_try_reconnect, interactive, error);
}
/*****************************************************************************
@@ -266,7 +267,7 @@ static const char* helpText =
" NDB Cluster -- Management Client -- Help\n"
"---------------------------------------------------------------------------\n"
"HELP Print help text\n"
-"HELP SHOW Help for SHOW command\n"
+"HELP COMMAND Print detailed help for COMMAND(e.g. SHOW)\n"
#ifdef HAVE_GLOBAL_REPLICATION
"HELP REPLICATION Help for global replication\n"
#endif // HAVE_GLOBAL_REPLICATION
@@ -286,10 +287,10 @@ static const char* helpText =
"CLUSTERLOG OFF [<severity>] ... Disable Cluster logging\n"
"CLUSTERLOG TOGGLE [<severity>] ... Toggle severity filter on/off\n"
"CLUSTERLOG INFO Print cluster log information\n"
-"<id> START Start DB node (started with -n)\n"
-"<id> RESTART [-n] [-i] Restart DB node\n"
-"<id> STOP Stop DB node\n"
-"ENTER SINGLE USER MODE <api-node> Enter single user mode\n"
+"<id> START Start data node (started with -n)\n"
+"<id> RESTART [-n] [-i] Restart data or management server node\n"
+"<id> STOP Stop data or management server node\n"
+"ENTER SINGLE USER MODE <id> Enter single user mode\n"
"EXIT SINGLE USER MODE Exit single user mode\n"
"<id> STATUS Print status\n"
"<id> CLUSTERLOG {<category>=<level>}+ Set log level for cluster log\n"
@@ -305,14 +306,296 @@ static const char* helpTextShow =
"---------------------------------------------------------------------------\n"
" NDB Cluster -- Management Client -- Help for SHOW command\n"
"---------------------------------------------------------------------------\n"
-"SHOW prints NDB Cluster information\n\n"
-"SHOW Print information about cluster\n"
+"SHOW Print information about cluster\n\n"
+"SHOW Print information about cluster.The status reported is from\n"
+" the perspective of the data nodes. API and Management Server nodes\n"
+" are only reported as connected once the data nodes have started.\n"
#if 0
"SHOW CONFIG Print configuration (in initial config file format)\n"
"SHOW PARAMETERS Print information about configuration parameters\n\n"
#endif
;
+static const char* helpTextHelp =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for HELP command\n"
+"---------------------------------------------------------------------------\n"
+"HELP List available commands of NDB Cluster Management Client\n\n"
+"HELP List available commands.\n"
+;
+
+static const char* helpTextBackup =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for BACKUP command\n"
+"---------------------------------------------------------------------------\n"
+"BACKUP A backup is a snapshot of the database at a given time. \n"
+" The backup consists of three main parts:\n\n"
+" Metadata: the names and definitions of all database tables. \n"
+" Table records: the data actually stored in the database tables \n"
+" at the time that the backup was made.\n"
+" Transaction log: a sequential record telling how \n"
+" and when data was stored in the database.\n\n"
+" Backups are stored on each data node in the cluster that \n"
+" participates in the backup.\n\n"
+" The cluster log records backup related events (such as \n"
+" backup started, aborted, finished).\n"
+;
+
+static const char* helpTextStartBackup =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for START BACKUP command\n"
+"---------------------------------------------------------------------------\n"
+"START BACKUP Start a cluster backup\n\n"
+"START BACKUP [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
+" Start a backup for the cluster.\n"
+" Each backup gets an ID number that is reported to the\n"
+" user. This ID number can help you find the backup on the\n"
+" file system, or ABORT BACKUP if you wish to cancel a \n"
+" running backup.\n\n"
+" NOWAIT \n"
+" Start a cluster backup and return immediately.\n"
+" The management client will return control directly\n"
+" to the user without waiting for the backup\n"
+" to have started.\n"
+" The status of the backup is recorded in the Cluster log.\n"
+" WAIT STARTED\n"
+" Start a cluster backup and return until the backup has\n"
+" started. The management client will wait for the backup \n"
+" to have started before returning control to the user.\n"
+" WAIT COMPLETED\n"
+" Start a cluster backup and return until the backup has\n"
+" completed. The management client will wait for the backup\n"
+" to complete before returning control to the user.\n"
+;
+
+static const char* helpTextAbortBackup =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for ABORT BACKUP command\n"
+"---------------------------------------------------------------------------\n"
+"ABORT BACKUP Abort a cluster backup\n\n"
+"ABORT BACKUP <backup id> \n"
+" Abort a backup that is already in progress.\n"
+" The backup id can be seen in the cluster log or in the\n"
+" output of the START BACKUP command.\n"
+;
+
+static const char* helpTextShutdown =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for SHUTDOWN command\n"
+"---------------------------------------------------------------------------\n"
+"SHUTDOWN Shutdown the cluster\n\n"
+"SHUTDOWN Shutdown the data nodes and management nodes.\n"
+" MySQL Servers and NDBAPI nodes are currently not \n"
+" shut down by issuing this command.\n"
+;
+
+static const char* helpTextClusterlogOn =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for CLUSTERLOG ON command\n"
+"---------------------------------------------------------------------------\n"
+"CLUSTERLOG ON Enable Cluster logging\n\n"
+"CLUSTERLOG ON [<severity>] ... \n"
+" Turn the cluster log on.\n"
+" It tells management server which severity levels\n"
+" messages will be logged.\n\n"
+" <severity> can be any one of the following values:\n"
+" ALERT, CRITICAL, ERROR, WARNING, INFO, DEBUG.\n"
+;
+
+static const char* helpTextClusterlogOff =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for CLUSTERLOG OFF command\n"
+"---------------------------------------------------------------------------\n"
+"CLUSTERLOG OFF Disable Cluster logging\n\n"
+"CLUSTERLOG OFF [<severity>] ... \n"
+" Turn the cluster log off.\n"
+" It tells management server which serverity\n"
+" levels logging will be disabled.\n\n"
+" <severity> can be any one of the following values:\n"
+" ALERT, CRITICAL, ERROR, WARNING, INFO, DEBUG.\n"
+;
+
+static const char* helpTextClusterlogToggle =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for CLUSTERLOG TOGGLE command\n"
+"---------------------------------------------------------------------------\n"
+"CLUSTERLOG TOGGLE Toggle severity filter on/off\n\n"
+"CLUSTERLOG TOGGLE [<severity>] ... \n"
+" Toggle serverity filter on/off.\n"
+" If a serverity level is already enabled,then it will\n"
+" be disabled after you use the command,vice versa.\n\n"
+" <severity> can be any one of the following values:\n"
+" ALERT, CRITICAL, ERROR, WARNING, INFO, DEBUG.\n"
+;
+
+static const char* helpTextClusterlogInfo =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for CLUSTERLOG INFO command\n"
+"---------------------------------------------------------------------------\n"
+"CLUSTERLOG INFO Print cluster log information\n\n"
+"CLUSTERLOG INFO Display which severity levels have been enabled,\n"
+" see HELP CLUSTERLOG for list of the severity levels.\n"
+;
+
+static const char* helpTextStart =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for START command\n"
+"---------------------------------------------------------------------------\n"
+"START Start data node (started with -n)\n\n"
+"<id> START Start the data node identified by <id>.\n"
+" Only starts data nodes that have not\n"
+" yet joined the cluster. These are nodes\n"
+" launched or restarted with the -n(--nostart)\n"
+" option.\n\n"
+" It does not launch the ndbd process on a remote\n"
+" machine.\n"
+;
+
+static const char* helpTextRestart =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for RESTART command\n"
+"---------------------------------------------------------------------------\n"
+"RESTART Restart data or management server node\n\n"
+"<id> RESTART [-n] [-i] \n"
+" Restart the data or management node <id>(or All data nodes).\n\n"
+" -n (--nostart) restarts the node but does not\n"
+" make it join the cluster. Use '<id> START' to\n"
+" join the node to the cluster.\n\n"
+" -i (--initial) perform initial start.\n"
+" This cleans the file system (ndb_<id>_fs)\n"
+" and the node will copy data from another node\n"
+" in the same node group during start up.\n\n"
+" Consult the documentation before using -i.\n\n"
+" INCORRECT USE OF -i WILL CAUSE DATA LOSS!\n"
+;
+
+static const char* helpTextStop =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for STOP command\n"
+"---------------------------------------------------------------------------\n"
+"STOP Stop data or management server node\n\n"
+"<id> STOP Stop the data or management server node <id>.\n\n"
+" ALL STOP will just stop all data nodes.\n\n"
+" If you desire to also shut down management servers,\n"
+" use SHUTDOWN instead.\n"
+;
+
+static const char* helpTextEnterSingleUserMode =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for ENTER SINGLE USER MODE command\n"
+"---------------------------------------------------------------------------\n"
+"ENTER SINGLE USER MODE Enter single user mode\n\n"
+"ENTER SINGLE USER MODE <id> \n"
+" Enters single-user mode, whereby only the MySQL Server or NDBAPI\n"
+" node identified by <id> is allowed to access the database. \n"
+;
+
+static const char* helpTextExitSingleUserMode =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for EXIT SINGLE USER MODE command\n"
+"---------------------------------------------------------------------------\n"
+"EXIT SINGLE USER MODE Exit single user mode\n\n"
+"EXIT SINGLE USER MODE \n"
+" Exits single-user mode, allowing all SQL nodes \n"
+" (that is, all running mysqld processes) to access the database. \n"
+;
+
+static const char* helpTextStatus =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for STATUS command\n"
+"---------------------------------------------------------------------------\n"
+"STATUS Print status\n\n"
+"<id> STATUS Displays status information for the data node <id>\n"
+" or for All data nodes. \n\n"
+" e.g.\n"
+" ALL STATUS\n"
+" 1 STATUS\n\n"
+" When a node is starting, the start phase will be\n"
+" listed.\n\n"
+" Start Phase Meaning\n"
+" 1 Clear the cluster file system(ndb_<id>_fs). \n"
+" This stage occurs only when the --initial option \n"
+" has been specified.\n"
+" 2 This stage sets up Cluster connections, establishes \n"
+" inter-node communications and starts Cluster heartbeats.\n"
+" 3 The arbitrator node is elected.\n"
+" 4 Initializes a number of internal cluster variables.\n"
+" 5 For an initial start or initial node restart,\n"
+" the redo log files are created.\n"
+" 6 If this is an initial start, create internal system tables.\n"
+" 7 Update internal variables. \n"
+" 8 In a system restart, rebuild all indexes.\n"
+" 9 Update internal variables. \n"
+" 10 The node can be connected by APIs and can receive events.\n"
+" 11 At this point,event delivery is handed over to\n"
+" the node joining the cluster.\n"
+"(see manual for more information)\n"
+;
+
+static const char* helpTextClusterlog =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for CLUSTERLOG command\n"
+"---------------------------------------------------------------------------\n"
+"CLUSTERLOG Set log level for cluster log\n\n"
+" <id> CLUSTERLOG {<category>=<level>}+ \n"
+" Logs <category> events with priority less than \n"
+" or equal to <level> in the cluster log.\n\n"
+" <category> can be any one of the following values:\n"
+" STARTUP, SHUTDOWN, STATISTICS, CHECKPOINT, NODERESTART,\n"
+" CONNECTION, ERROR, INFO, CONGESTION, DEBUG, or BACKUP. \n\n"
+" <level> is represented by one of the numbers \n"
+" from 1 to 15 inclusive, where 1 indicates 'most important' \n"
+" and 15 'least important'.\n\n"
+" <severity> can be any one of the following values:\n"
+" ALERT, CRITICAL, ERROR, WARNING, INFO, DEBUG.\n"
+;
+
+
+static const char* helpTextPurgeStaleSessions =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for PURGE STALE SESSIONS command\n"
+"---------------------------------------------------------------------------\n"
+"PURGE STALE SESSIONS Reset reserved nodeid's in the mgmt server\n\n"
+"PURGE STALE SESSIONS \n"
+" Running this statement forces all reserved \n"
+" node IDs to be checked; any that are not \n"
+" being used by nodes acutally connected to \n"
+" the cluster are then freed.\n\n"
+" This command is not normally needed, but may be\n"
+" required in some situations where failed nodes \n"
+" cannot rejoin the cluster due to failing to\n"
+" allocate a node id.\n"
+;
+
+static const char* helpTextConnect =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for CONNECT command\n"
+"---------------------------------------------------------------------------\n"
+"CONNECT Connect to management server (reconnect if already connected)\n\n"
+"CONNECT [<connectstring>] \n"
+" Connect to management server.\n"
+" The optional parameter connectstring specifies the \n"
+" connect string to user.\n\n"
+" A connect string may be:\n"
+" mgm-server\n"
+" mgm-server:port\n"
+" mgm1:port,mgm2:port\n"
+" With multiple management servers comma separated.\n"
+" The management client with try to connect to the \n"
+" management servers in the order they are listed.\n\n"
+" If no connect string is specified, the default \n"
+" is used. \n"
+;
+
+static const char* helpTextQuit =
+"---------------------------------------------------------------------------\n"
+" NDB Cluster -- Management Client -- Help for QUIT command\n"
+"---------------------------------------------------------------------------\n"
+"QUIT Quit management client\n\n"
+"QUIT Terminates the management client. \n"
+;
+
+
#ifdef HAVE_GLOBAL_REPLICATION
static const char* helpTextRep =
"---------------------------------------------------------------------------\n"
@@ -370,6 +653,44 @@ static const char* helpTextDebug =
;
#endif
+struct st_cmd_help {
+ const char *cmd;
+ const char * help;
+}help_items[]={
+ {"SHOW", helpTextShow},
+ {"HELP", helpTextHelp},
+ {"BACKUP", helpTextBackup},
+ {"START BACKUP", helpTextStartBackup},
+ {"START BACKUP NOWAIT", helpTextStartBackup},
+ {"START BACKUP WAIT STARTED", helpTextStartBackup},
+ {"START BACKUP WAIT", helpTextStartBackup},
+ {"START BACKUP WAIT COMPLETED", helpTextStartBackup},
+ {"ABORT BACKUP", helpTextAbortBackup},
+ {"SHUTDOWN", helpTextShutdown},
+ {"CLUSTERLOG ON", helpTextClusterlogOn},
+ {"CLUSTERLOG OFF", helpTextClusterlogOff},
+ {"CLUSTERLOG TOGGLE", helpTextClusterlogToggle},
+ {"CLUSTERLOG INFO", helpTextClusterlogInfo},
+ {"START", helpTextStart},
+ {"RESTART", helpTextRestart},
+ {"STOP", helpTextStop},
+ {"ENTER SINGLE USER MODE", helpTextEnterSingleUserMode},
+ {"EXIT SINGLE USER MODE", helpTextExitSingleUserMode},
+ {"STATUS", helpTextStatus},
+ {"CLUSTERLOG", helpTextClusterlog},
+ {"PURGE STALE SESSIONS", helpTextPurgeStaleSessions},
+ {"CONNECT", helpTextConnect},
+ {"QUIT", helpTextQuit},
+#ifdef HAVE_GLOBAL_REPLICATION
+ {"REPLICATION", helpTextRep},
+ {"REP", helpTextRep},
+#endif // HAVE_GLOBAL_REPLICATION
+#ifdef VM_TRACE // DEBUG ONLY
+ {"DEBUG", helpTextDebug},
+#endif //VM_TRACE
+ {NULL, NULL}
+};
+
static bool
convert(const char* s, int& val) {
@@ -400,7 +721,7 @@ CommandInterpreter::CommandInterpreter(const char *_host,int verbose)
{
m_constr= _host;
m_connected= false;
- m_event_thread= 0;
+ m_event_thread= NULL;
try_reconnect = 0;
m_print_mutex= NdbMutex_Create();
#ifdef HAVE_GLOBAL_REPLICATION
@@ -495,7 +816,7 @@ event_thread_run(void* p)
}
bool
-CommandInterpreter::connect()
+CommandInterpreter::connect(bool interactive)
{
DBUG_ENTER("CommandInterpreter::connect");
@@ -507,10 +828,12 @@ CommandInterpreter::connect()
ndbout_c("Cannot create handle to management server.");
exit(-1);
}
- m_mgmsrv2 = ndb_mgm_create_handle();
- if(m_mgmsrv2 == NULL) {
- ndbout_c("Cannot create 2:nd handle to management server.");
- exit(-1);
+ if (interactive) {
+ m_mgmsrv2 = ndb_mgm_create_handle();
+ if(m_mgmsrv2 == NULL) {
+ ndbout_c("Cannot create 2:nd handle to management server.");
+ exit(-1);
+ }
}
if (ndb_mgm_set_connectstring(m_mgmsrv, m_constr))
@@ -524,62 +847,64 @@ CommandInterpreter::connect()
const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
- BaseString constr;
- constr.assfmt("%s:%d",host,port);
- if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) &&
- !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1))
- {
- DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d",
- host, port));
- assert(m_event_thread == 0);
- assert(do_event_thread == 0);
- do_event_thread= 0;
- struct event_thread_param p;
- p.m= &m_mgmsrv2;
- p.p= &m_print_mutex;
- m_event_thread = NdbThread_Create(event_thread_run,
- (void**)&p,
- 32768,
- "CommandInterpreted_event_thread",
- NDB_THREAD_PRIO_LOW);
- if (m_event_thread != 0)
- {
- DBUG_PRINT("info",("Thread created ok, waiting for started..."));
- int iter= 1000; // try for 30 seconds
- while(do_event_thread == 0 &&
- iter-- > 0)
- NdbSleep_MilliSleep(30);
- }
- if (m_event_thread == 0 ||
- do_event_thread == 0 ||
- do_event_thread == -1)
+ if (interactive) {
+ BaseString constr;
+ constr.assfmt("%s:%d",host,port);
+ if(!ndb_mgm_set_connectstring(m_mgmsrv2, constr.c_str()) &&
+ !ndb_mgm_connect(m_mgmsrv2, try_reconnect-1, 5, 1))
{
- DBUG_PRINT("info",("Warning, event thread startup failed, "
- "degraded printouts as result, errno=%d",
- errno));
- printf("Warning, event thread startup failed, "
- "degraded printouts as result, errno=%d\n", errno);
+ DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d",
+ host, port));
+ assert(m_event_thread == NULL);
+ assert(do_event_thread == 0);
do_event_thread= 0;
+ struct event_thread_param p;
+ p.m= &m_mgmsrv2;
+ p.p= &m_print_mutex;
+ m_event_thread = NdbThread_Create(event_thread_run,
+ (void**)&p,
+ 32768,
+ "CommandInterpreted_event_thread",
+ NDB_THREAD_PRIO_LOW);
if (m_event_thread)
{
- void *res;
- NdbThread_WaitFor(m_event_thread, &res);
- NdbThread_Destroy(&m_event_thread);
+ DBUG_PRINT("info",("Thread created ok, waiting for started..."));
+ int iter= 1000; // try for 30 seconds
+ while(do_event_thread == 0 &&
+ iter-- > 0)
+ NdbSleep_MilliSleep(30);
+ }
+ if (m_event_thread == NULL ||
+ do_event_thread == 0 ||
+ do_event_thread == -1)
+ {
+ DBUG_PRINT("info",("Warning, event thread startup failed, "
+ "degraded printouts as result, errno=%d",
+ errno));
+ printf("Warning, event thread startup failed, "
+ "degraded printouts as result, errno=%d\n", errno);
+ do_event_thread= 0;
+ if (m_event_thread)
+ {
+ void *res;
+ NdbThread_WaitFor(m_event_thread, &res);
+ NdbThread_Destroy(&m_event_thread);
+ }
+ ndb_mgm_disconnect(m_mgmsrv2);
}
- ndb_mgm_disconnect(m_mgmsrv2);
}
- }
- else
- {
- DBUG_PRINT("warning",
- ("Could not do 2:nd connect to mgmtserver for event listening"));
- DBUG_PRINT("info", ("code: %d, msg: %s",
- ndb_mgm_get_latest_error(m_mgmsrv2),
- ndb_mgm_get_latest_error_msg(m_mgmsrv2)));
- printf("Warning, event connect failed, degraded printouts as result\n");
- printf("code: %d, msg: %s\n",
- ndb_mgm_get_latest_error(m_mgmsrv2),
- ndb_mgm_get_latest_error_msg(m_mgmsrv2));
+ else
+ {
+ DBUG_PRINT("warning",
+ ("Could not do 2:nd connect to mgmtserver for event listening"));
+ DBUG_PRINT("info", ("code: %d, msg: %s",
+ ndb_mgm_get_latest_error(m_mgmsrv2),
+ ndb_mgm_get_latest_error_msg(m_mgmsrv2)));
+ printf("Warning, event connect failed, degraded printouts as result\n");
+ printf("code: %d, msg: %s\n",
+ ndb_mgm_get_latest_error(m_mgmsrv2),
+ ndb_mgm_get_latest_error_msg(m_mgmsrv2));
+ }
}
m_connected= true;
DBUG_PRINT("info",("Connected to Management Server at: %s:%d", host, port));
@@ -602,7 +927,7 @@ CommandInterpreter::disconnect()
do_event_thread= 0;
NdbThread_WaitFor(m_event_thread, &res);
NdbThread_Destroy(&m_event_thread);
- m_event_thread= 0;
+ m_event_thread= NULL;
ndb_mgm_destroy_handle(&m_mgmsrv2);
}
if (m_connected)
@@ -618,11 +943,11 @@ CommandInterpreter::disconnect()
int
CommandInterpreter::execute(const char *_line, int _try_reconnect,
- int *error)
+ bool interactive, int *error)
{
if (_try_reconnect >= 0)
try_reconnect=_try_reconnect;
- int result= execute_impl(_line);
+ int result= execute_impl(_line, interactive);
if (error)
*error= m_error;
@@ -637,7 +962,7 @@ invalid_command(const char *cmd)
}
int
-CommandInterpreter::execute_impl(const char *_line)
+CommandInterpreter::execute_impl(const char *_line, bool interactive)
{
DBUG_ENTER("CommandInterpreter::execute_impl");
DBUG_PRINT("enter",("line=\"%s\"",_line));
@@ -645,6 +970,7 @@ CommandInterpreter::execute_impl(const char *_line)
char * line;
if(_line == NULL) {
+ m_error = -1;
DBUG_RETURN(false);
}
line = my_strdup(_line,MYF(MY_WME));
@@ -682,16 +1008,17 @@ CommandInterpreter::execute_impl(const char *_line)
if (strcasecmp(firstToken, "HELP") == 0 ||
strcasecmp(firstToken, "?") == 0) {
- executeHelp(allAfterFirstToken);
+ m_error = executeHelp(allAfterFirstToken);
DBUG_RETURN(true);
}
else if (strcasecmp(firstToken, "CONNECT") == 0) {
- executeConnect(allAfterFirstToken);
+ m_error = executeConnect(allAfterFirstToken, interactive);
DBUG_RETURN(true);
}
else if (strcasecmp(firstToken, "SLEEP") == 0) {
if (allAfterFirstToken)
- sleep(atoi(allAfterFirstToken));
+ if (sleep(atoi(allAfterFirstToken)) != 0 )
+ m_error = -1;
DBUG_RETURN(true);
}
else if((strcasecmp(firstToken, "QUIT") == 0 ||
@@ -701,12 +1028,20 @@ CommandInterpreter::execute_impl(const char *_line)
DBUG_RETURN(false);
}
- if (!connect())
+ if (!connect(interactive)){
+ m_error = -1;
DBUG_RETURN(true);
+ }
+
+ if (ndb_mgm_check_connection(m_mgmsrv))
+ {
+ disconnect();
+ connect(interactive);
+ }
if (strcasecmp(firstToken, "SHOW") == 0) {
Guard g(m_print_mutex);
- executeShow(allAfterFirstToken);
+ m_error = executeShow(allAfterFirstToken);
DBUG_RETURN(true);
}
else if (strcasecmp(firstToken, "SHUTDOWN") == 0) {
@@ -726,17 +1061,17 @@ CommandInterpreter::execute_impl(const char *_line)
else if(strcasecmp(firstToken, "ABORT") == 0 &&
allAfterFirstToken != NULL &&
strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
- executeAbortBackup(allAfterFirstToken);
+ m_error = executeAbortBackup(allAfterFirstToken);
DBUG_RETURN(true);
}
else if (strcasecmp(firstToken, "PURGE") == 0) {
- executePurge(allAfterFirstToken);
+ m_error = executePurge(allAfterFirstToken);
DBUG_RETURN(true);
}
#ifdef HAVE_GLOBAL_REPLICATION
else if(strcasecmp(firstToken, "REPLICATION") == 0 ||
strcasecmp(firstToken, "REP") == 0) {
- executeRep(allAfterFirstToken);
+ m_error = executeRep(allAfterFirstToken);
DBUG_RETURN(true);
}
#endif // HAVE_GLOBAL_REPLICATION
@@ -744,18 +1079,18 @@ CommandInterpreter::execute_impl(const char *_line)
allAfterFirstToken != NULL &&
strncasecmp(allAfterFirstToken, "SINGLE USER MODE ",
sizeof("SINGLE USER MODE") - 1) == 0){
- executeEnterSingleUser(allAfterFirstToken);
+ m_error = executeEnterSingleUser(allAfterFirstToken);
DBUG_RETURN(true);
}
else if(strcasecmp(firstToken, "EXIT") == 0 &&
allAfterFirstToken != NULL &&
strncasecmp(allAfterFirstToken, "SINGLE USER MODE ",
sizeof("SINGLE USER MODE") - 1) == 0){
- executeExitSingleUser(allAfterFirstToken);
+ m_error = executeExitSingleUser(allAfterFirstToken);
DBUG_RETURN(true);
}
else if (strcasecmp(firstToken, "ALL") == 0) {
- analyseAfterFirstToken(-1, allAfterFirstToken);
+ m_error = analyseAfterFirstToken(-1, allAfterFirstToken);
} else {
/**
* First tokens should be digits, node ID's
@@ -767,7 +1102,7 @@ CommandInterpreter::execute_impl(const char *_line)
int node_id;
if (convert(command_list[pos].c_str(), node_id))
{
- if (node_id <= 0) {
+ if (node_id <= 0 || node_id > MAX_NODES) {
ndbout << "Invalid node ID: " << command_list[pos].c_str()
<< "." << endl;
DBUG_RETURN(true);
@@ -782,20 +1117,22 @@ CommandInterpreter::execute_impl(const char *_line)
{
/* No digit found */
invalid_command(_line);
+ m_error = -1;
DBUG_RETURN(true);
}
if (pos == command_list.size())
{
/* No command found */
invalid_command(_line);
+ m_error = -1;
DBUG_RETURN(true);
}
if (no_of_nodes == 1)
{
- analyseAfterFirstToken(node_ids[0], allAfterFirstToken);
+ m_error = analyseAfterFirstToken(node_ids[0], allAfterFirstToken);
DBUG_RETURN(true);
}
- executeCommand(command_list, pos, node_ids, no_of_nodes);
+ m_error = executeCommand(command_list, pos, node_ids, no_of_nodes);
DBUG_RETURN(true);
}
DBUG_RETURN(true);
@@ -829,14 +1166,15 @@ static const CommandInterpreter::CommandFunctionPair commands[] = {
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::analyseAfterFirstToken(int processId,
char* allAfterFirstToken) {
+ int retval = 0;
if (emptyString(allAfterFirstToken)) {
ndbout << "Expected a command after "
<< ((processId == -1) ? "ALL." : "node ID.") << endl;
- return;
+ return -1;
}
char* secondToken = strtok(allAfterFirstToken, " ");
@@ -855,36 +1193,39 @@ CommandInterpreter::analyseAfterFirstToken(int processId,
if(fun == 0){
invalid_command(secondToken);
- return;
+ return -1;
}
if(processId == -1){
- executeForAll(command, fun, allAfterSecondToken);
+ retval = executeForAll(command, fun, allAfterSecondToken);
} else {
- (this->*fun)(processId, allAfterSecondToken, false);
+ retval = (this->*fun)(processId, allAfterSecondToken, false);
}
ndbout << endl;
+ return retval;
}
-void
+int
CommandInterpreter::executeCommand(Vector<BaseString> &command_list,
unsigned command_pos,
int *node_ids, int no_of_nodes)
{
const char *cmd= command_list[command_pos].c_str();
+ int retval = 0;
+
if (strcasecmp("STOP", cmd) == 0)
{
- executeStop(command_list, command_pos+1, node_ids, no_of_nodes);
- return;
+ retval = executeStop(command_list, command_pos+1, node_ids, no_of_nodes);
+ return retval;
}
if (strcasecmp("RESTART", cmd) == 0)
{
- executeRestart(command_list, command_pos+1, node_ids, no_of_nodes);
- return;
+ retval = executeRestart(command_list, command_pos+1, node_ids, no_of_nodes);
+ return retval;
}
ndbout_c("Invalid command: '%s' after multi node id list. "
"Expected STOP or RESTART.", cmd);
- return;
+ return -1;
}
/**
@@ -925,18 +1266,20 @@ get_next_nodeid(struct ndb_mgm_cluster_state *cl,
return 0;
}
-void
+int
CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun,
const char * allAfterSecondToken)
{
int nodeId = 0;
+ int retval = 0;
+
if(strcasecmp(cmd, "STOP") == 0) {
ndbout_c("Executing STOP on all nodes.");
- (this->*fun)(nodeId, allAfterSecondToken, true);
+ retval = (this->*fun)(nodeId, allAfterSecondToken, true);
} else if(strcasecmp(cmd, "RESTART") == 0) {
ndbout_c("Executing RESTART on all nodes.");
ndbout_c("Starting shutdown. This may take a while. Please wait...");
- (this->*fun)(nodeId, allAfterSecondToken, true);
+ retval = (this->*fun)(nodeId, allAfterSecondToken, true);
ndbout_c("Trying to start all nodes of system.");
ndbout_c("Use ALL STATUS to see the system start-up phases.");
} else {
@@ -945,12 +1288,13 @@ CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun,
if(cl == 0){
ndbout_c("Unable get status from management server");
printError();
- return;
+ return -1;
}
NdbAutoPtr<char> ap1((char*)cl);
while(get_next_nodeid(cl, &nodeId, NDB_MGM_NODE_TYPE_NDB))
- (this->*fun)(nodeId, allAfterSecondToken, true);
+ retval = (this->*fun)(nodeId, allAfterSecondToken, true);
}
+ return retval;
}
//*****************************************************************************
@@ -1020,7 +1364,7 @@ CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
/*****************************************************************************
* HELP
*****************************************************************************/
-void
+int
CommandInterpreter::executeHelp(char* parameters)
{
if (emptyString(parameters)) {
@@ -1045,20 +1389,23 @@ CommandInterpreter::executeHelp(char* parameters)
ndbout << "<level> = " << "0 - 15" << endl;
ndbout << "<id> = " << "ALL | Any database node id" << endl;
ndbout << endl;
- } else if (strcasecmp(parameters, "SHOW") == 0) {
- ndbout << helpTextShow;
-#ifdef HAVE_GLOBAL_REPLICATION
- } else if (strcasecmp(parameters, "REPLICATION") == 0 ||
- strcasecmp(parameters, "REP") == 0) {
- ndbout << helpTextRep;
-#endif // HAVE_GLOBAL_REPLICATION
-#ifdef VM_TRACE // DEBUG ONLY
- } else if (strcasecmp(parameters, "DEBUG") == 0) {
- ndbout << helpTextDebug;
-#endif
+ ndbout << "For detailed help on COMMAND, use HELP COMMAND." << endl;
} else {
- invalid_command(parameters);
+ int i = 0;
+ for (i = 0; help_items[i].cmd != NULL; i++)
+ {
+ if (strcasecmp(parameters, help_items[i].cmd) == 0)
+ {
+ ndbout << help_items[i].help;
+ break;
+ }
+ }
+ if (help_items[i].cmd == NULL){
+ ndbout << "No help for " << parameters << " available" << endl;
+ return -1;
+ }
}
+ return 0;
}
@@ -1181,7 +1528,7 @@ print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it,
ndbout << endl;
}
-void
+int
CommandInterpreter::executePurge(char* parameters)
{
int command_ok= 0;
@@ -1200,7 +1547,7 @@ CommandInterpreter::executePurge(char* parameters)
if (!command_ok) {
ndbout_c("Unexpected command, expected: PURGE STALE SESSIONS");
- return;
+ return -1;
}
int i;
@@ -1208,7 +1555,7 @@ CommandInterpreter::executePurge(char* parameters)
if (ndb_mgm_purge_stale_sessions(m_mgmsrv, &str)) {
ndbout_c("Command failed");
- return;
+ return -1;
}
if (str) {
ndbout_c("Purged sessions with node id's: %s", str);
@@ -1218,9 +1565,10 @@ CommandInterpreter::executePurge(char* parameters)
{
ndbout_c("No sessions purged");
}
+ return 0;
}
-void
+int
CommandInterpreter::executeShow(char* parameters)
{
int i;
@@ -1229,7 +1577,7 @@ CommandInterpreter::executeShow(char* parameters)
if(state == NULL) {
ndbout_c("Could not get status");
printError();
- return;
+ return -1;
}
NdbAutoPtr<char> ap1((char*)state);
@@ -1237,7 +1585,7 @@ CommandInterpreter::executeShow(char* parameters)
if(conf == 0){
ndbout_c("Could not get configuration");
printError();
- return;
+ return -1;
}
ndb_mgm_configuration_iterator * it;
@@ -1246,7 +1594,7 @@ CommandInterpreter::executeShow(char* parameters)
if(it == 0){
ndbout_c("Unable to create config iterator");
ndb_mgm_destroy_configuration(conf);
- return;
+ return -1;
}
NdbAutoPtr<ndb_mgm_configuration_iterator> ptr(it);
@@ -1280,7 +1628,7 @@ CommandInterpreter::executeShow(char* parameters)
break;
case NDB_MGM_NODE_TYPE_UNKNOWN:
ndbout << "Error: Unknown Node Type" << endl;
- return;
+ return -1;
case NDB_MGM_NODE_TYPE_REP:
abort();
}
@@ -1293,7 +1641,7 @@ CommandInterpreter::executeShow(char* parameters)
print_nodes(state, it, "mysqld", api_nodes, NDB_MGM_NODE_TYPE_API, 0);
// ndbout << helpTextShow;
ndb_mgm_destroy_configuration(conf);
- return;
+ return 0;
} else if (strcasecmp(parameters, "PROPERTIES") == 0 ||
strcasecmp(parameters, "PROP") == 0) {
ndbout << "SHOW PROPERTIES is not yet implemented." << endl;
@@ -1310,17 +1658,29 @@ CommandInterpreter::executeShow(char* parameters)
// << endl; /* XXX */
} else {
ndbout << "Invalid argument." << endl;
+ return -1;
}
+ return 0;
}
-void
-CommandInterpreter::executeConnect(char* parameters)
+int
+CommandInterpreter::executeConnect(char* parameters, bool interactive)
{
+ BaseString *basestring = NULL;
+
+ int retval;
disconnect();
if (!emptyString(parameters)) {
- m_constr= BaseString(parameters).trim().c_str();
+ basestring= new BaseString(parameters);
+ m_constr= basestring->trim().c_str();
+ }
+ if ( connect(interactive) == false ){
+ return -1;
}
- connect();
+ if (basestring != NULL)
+ delete basestring;
+
+ return 0;
}
//*****************************************************************************
@@ -1333,6 +1693,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
if (emptyString(parameters))
{
ndbout << "Missing argument." << endl;
+ m_error = -1;
DBUG_VOID_RETURN;
}
@@ -1348,6 +1709,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
if(enabled == NULL) {
ndbout << "Couldn't get status" << endl;
printError();
+ m_error = -1;
DBUG_VOID_RETURN;
}
@@ -1359,6 +1721,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
if(enabled[0] == 0)
{
ndbout << "Cluster logging is disabled." << endl;
+ m_error = 0;
DBUG_VOID_RETURN;
}
#if 0
@@ -1377,6 +1740,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
ndbout << BaseString(str).ndb_toupper() << " ";
}
ndbout << endl;
+ m_error = 0;
DBUG_VOID_RETURN;
}
@@ -1395,6 +1759,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
enable= 1;
} else {
ndbout << "Invalid argument." << endl;
+ m_error = -1;
DBUG_VOID_RETURN;
}
@@ -1409,9 +1774,11 @@ CommandInterpreter::executeClusterLog(char* parameters)
{
ndbout << "Couldn't set filter" << endl;
printError();
+ m_error = -1;
DBUG_VOID_RETURN;
}
ndbout << "Cluster logging is " << (res_enable ? "enabled.":"disabled") << endl;
+ m_error = 0;
DBUG_VOID_RETURN;
}
@@ -1438,6 +1805,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
}
if (severity == NDB_MGM_ILLEGAL_EVENT_SEVERITY) {
ndbout << "Invalid severity level: " << item << endl;
+ m_error = -1;
DBUG_VOID_RETURN;
}
@@ -1447,23 +1815,27 @@ CommandInterpreter::executeClusterLog(char* parameters)
{
ndbout << "Couldn't set filter" << endl;
printError();
+ m_error = -1;
DBUG_VOID_RETURN;
}
ndbout << BaseString(item).ndb_toupper().c_str() << " " << (res_enable ? "enabled":"disabled") << endl;
item = strtok_r(NULL, " ", &tmpPtr);
} while(item != NULL);
-
+
+ m_error = 0;
DBUG_VOID_RETURN;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeStop(int processId, const char *parameters,
bool all)
{
+ int retval = 0;
+
Vector<BaseString> command_list;
if (parameters)
{
@@ -1473,18 +1845,22 @@ CommandInterpreter::executeStop(int processId, const char *parameters,
command_list[i].c_str()[0] ? i++ : (command_list.erase(i),0);
}
if (all)
- executeStop(command_list, 0, 0, 0);
+ retval = executeStop(command_list, 0, 0, 0);
else
- executeStop(command_list, 0, &processId, 1);
+ retval = executeStop(command_list, 0, &processId, 1);
+
+ return retval;
}
-void
+int
CommandInterpreter::executeStop(Vector<BaseString> &command_list,
unsigned command_pos,
int *node_ids, int no_of_nodes)
{
int need_disconnect;
int abort= 0;
+ int retval = 0;
+
for (; command_pos < command_list.size(); command_pos++)
{
const char *item= command_list[command_pos].c_str();
@@ -1495,7 +1871,7 @@ CommandInterpreter::executeStop(Vector<BaseString> &command_list,
}
ndbout_c("Invalid option: %s. Expecting -A after STOP",
item);
- return;
+ return -1;
}
int result= ndb_mgm_stop3(m_mgmsrv, no_of_nodes, node_ids, abort,
@@ -1504,6 +1880,7 @@ CommandInterpreter::executeStop(Vector<BaseString> &command_list,
{
ndbout_c("Shutdown failed.");
printError();
+ retval = -1;
}
else
{
@@ -1524,9 +1901,10 @@ CommandInterpreter::executeStop(Vector<BaseString> &command_list,
disconnect();
}
+ return retval;
}
-void
+int
CommandInterpreter::executeEnterSingleUser(char* parameters)
{
strtok(parameters, " ");
@@ -1538,37 +1916,42 @@ CommandInterpreter::executeEnterSingleUser(char* parameters)
if(id == 0 || sscanf(id, "%d", &nodeId) != 1){
ndbout_c("Invalid arguments: expected <NodeId>");
ndbout_c("Use SHOW to see what API nodes are configured");
- return;
+ return -1;
}
int result = ndb_mgm_enter_single_user(m_mgmsrv, nodeId, &reply);
if (result != 0) {
ndbout_c("Entering single user mode for node %d failed", nodeId);
printError();
+ return -1;
} else {
ndbout_c("Single user mode entered");
ndbout_c("Access is granted for API node %d only.", nodeId);
}
+ return 0;
}
-void
+int
CommandInterpreter::executeExitSingleUser(char* parameters)
{
int result = ndb_mgm_exit_single_user(m_mgmsrv, 0);
if (result != 0) {
ndbout_c("Exiting single user mode failed.");
printError();
+ return -1;
} else {
ndbout_c("Exiting single user mode in progress.");
ndbout_c("Use ALL STATUS or SHOW to see when single user mode has been exited.");
+ return 0;
}
}
-void
+int
CommandInterpreter::executeStart(int processId, const char* parameters,
bool all)
{
int result;
+ int retval = 0;
if(all) {
result = ndb_mgm_start(m_mgmsrv, 0, 0);
} else {
@@ -1578,6 +1961,7 @@ CommandInterpreter::executeStart(int processId, const char* parameters,
if (result <= 0) {
ndbout << "Start failed." << endl;
printError();
+ retval = -1;
} else
{
if(all)
@@ -1585,13 +1969,16 @@ CommandInterpreter::executeStart(int processId, const char* parameters,
else
ndbout_c("Database node %d is being started.", processId);
}
+ return retval;
}
-void
+int
CommandInterpreter::executeRestart(int processId, const char* parameters,
bool all)
{
Vector<BaseString> command_list;
+ int retval = 0;
+
if (parameters)
{
BaseString tmp(parameters);
@@ -1600,17 +1987,20 @@ CommandInterpreter::executeRestart(int processId, const char* parameters,
command_list[i].c_str()[0] ? i++ : (command_list.erase(i),0);
}
if (all)
- executeRestart(command_list, 0, 0, 0);
+ retval = executeRestart(command_list, 0, 0, 0);
else
- executeRestart(command_list, 0, &processId, 1);
+ retval = executeRestart(command_list, 0, &processId, 1);
+
+ return retval;
}
-void
+int
CommandInterpreter::executeRestart(Vector<BaseString> &command_list,
unsigned command_pos,
int *node_ids, int no_of_nodes)
{
int result;
+ int retval = 0;
int nostart= 0;
int initialstart= 0;
int abort= 0;
@@ -1636,7 +2026,7 @@ CommandInterpreter::executeRestart(Vector<BaseString> &command_list,
}
ndbout_c("Invalid option: %s. Expecting -A,-N or -I after RESTART",
item);
- return;
+ return -1;
}
result= ndb_mgm_restart3(m_mgmsrv, no_of_nodes, node_ids,
@@ -1645,6 +2035,7 @@ CommandInterpreter::executeRestart(Vector<BaseString> &command_list,
if (result <= 0) {
ndbout_c("Restart failed.");
printError();
+ retval = -1;
}
else
{
@@ -1660,15 +2051,16 @@ CommandInterpreter::executeRestart(Vector<BaseString> &command_list,
if(need_disconnect)
disconnect();
}
+ return retval;
}
-void
+int
CommandInterpreter::executeDumpState(int processId, const char* parameters,
bool all)
{
if(emptyString(parameters)){
ndbout << "Expected argument" << endl;
- return;
+ return -1;
}
Uint32 no = 0;
@@ -1685,7 +2077,7 @@ CommandInterpreter::executeDumpState(int processId, const char* parameters,
ndbout << "Illegal value in argument to signal." << endl
<< "(Value must be between 0 and 0xffffffff.)"
<< endl;
- return;
+ return -1;
}
no++;
item = strtok_r(NULL, " ", &tmpPtr);
@@ -1697,16 +2089,16 @@ CommandInterpreter::executeDumpState(int processId, const char* parameters,
}
struct ndb_mgm_reply reply;
- ndb_mgm_dump_state(m_mgmsrv, processId, pars, no, &reply);
+ return ndb_mgm_dump_state(m_mgmsrv, processId, pars, no, &reply);
}
-void
+int
CommandInterpreter::executeStatus(int processId,
const char* parameters, bool all)
{
if (! emptyString(parameters)) {
ndbout_c("No parameters expected to this command.");
- return;
+ return -1;
}
ndb_mgm_node_status status;
@@ -1718,7 +2110,7 @@ CommandInterpreter::executeStatus(int processId,
if(cl == NULL) {
ndbout_c("Cannot get status of node %d.", processId);
printError();
- return;
+ return -1;
}
NdbAutoPtr<char> ap1((char*)cl);
@@ -1727,7 +2119,7 @@ CommandInterpreter::executeStatus(int processId,
i++;
if(cl->node_states[i].node_id != processId) {
ndbout << processId << ": Node not found" << endl;
- return;
+ return -1;
}
status = cl->node_states[i].node_status;
startPhase = cl->node_states[i].start_phase;
@@ -1751,27 +2143,29 @@ CommandInterpreter::executeStatus(int processId,
getBuild(version));
else
ndbout << endl;
+
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeLogLevel(int processId, const char* parameters,
bool all)
{
(void) all;
if (emptyString(parameters)) {
ndbout << "Expected argument" << endl;
- return;
+ return -1;
}
BaseString tmp(parameters);
Vector<BaseString> spec;
tmp.split(spec, "=");
if(spec.size() != 2){
ndbout << "Invalid loglevel specification: " << parameters << endl;
- return;
+ return -1;
}
spec[0].trim().ndb_toupper();
@@ -1781,14 +2175,14 @@ CommandInterpreter::executeLogLevel(int processId, const char* parameters,
if(category < NDB_MGM_MIN_EVENT_CATEGORY ||
category > NDB_MGM_MAX_EVENT_CATEGORY){
ndbout << "Unknown category: \"" << spec[0].c_str() << "\"" << endl;
- return;
+ return -1;
}
}
int level = atoi(spec[1].c_str());
if(level < 0 || level > 15){
ndbout << "Invalid level: " << spec[1].c_str() << endl;
- return;
+ return -1;
}
ndbout << "Executing LOGLEVEL on node " << processId << flush;
@@ -1804,20 +2198,22 @@ CommandInterpreter::executeLogLevel(int processId, const char* parameters,
if (result < 0) {
ndbout_c(" failed.");
printError();
+ return -1;
} else {
ndbout_c(" OK!");
}
-
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void CommandInterpreter::executeError(int processId,
+int CommandInterpreter::executeError(int processId,
const char* parameters, bool /* all */)
{
+ int retval = 0;
if (emptyString(parameters)) {
ndbout << "Missing error number." << endl;
- return;
+ return -1;
}
// Copy parameters since strtok will modify it
@@ -1828,29 +2224,30 @@ void CommandInterpreter::executeError(int processId,
int errorNo;
if (! convert(firstParameter, errorNo)) {
ndbout << "Expected an integer." << endl;
- return;
+ return -1;
}
char* allAfterFirstParameter = strtok(NULL, "\0");
if (! emptyString(allAfterFirstParameter)) {
ndbout << "Nothing expected after error number." << endl;
- return;
+ return -1;
}
- ndb_mgm_insert_error(m_mgmsrv, processId, errorNo, NULL);
+ retval = ndb_mgm_insert_error(m_mgmsrv, processId, errorNo, NULL);
+ return retval;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeLog(int processId,
const char* parameters, bool all)
{
struct ndb_mgm_reply reply;
Vector<const char *> blocks;
if (! parseBlockSpecification(parameters, blocks)) {
- return;
+ return -1;
}
int len=1;
Uint32 i;
@@ -1874,82 +2271,91 @@ CommandInterpreter::executeLog(int processId,
if (result != 0) {
ndbout_c("Execute LOG on node %d failed.", processId);
printError();
+ return -1;
}
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeLogIn(int /* processId */,
const char* parameters, bool /* all */)
{
ndbout << "Command LOGIN not implemented." << endl;
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeLogOut(int /*processId*/,
const char* parameters, bool /*all*/)
{
ndbout << "Command LOGOUT not implemented." << endl;
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeLogOff(int /*processId*/,
const char* parameters, bool /*all*/)
{
ndbout << "Command LOGOFF not implemented." << endl;
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeTestOn(int processId,
const char* parameters, bool /*all*/)
{
if (! emptyString(parameters)) {
ndbout << "No parameters expected to this command." << endl;
- return;
+ return -1;
}
struct ndb_mgm_reply reply;
int result = ndb_mgm_start_signallog(m_mgmsrv, processId, &reply);
if (result != 0) {
ndbout_c("Execute TESTON failed.");
printError();
+ return -1;
}
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeTestOff(int processId,
const char* parameters, bool /*all*/)
{
if (! emptyString(parameters)) {
ndbout << "No parameters expected to this command." << endl;
- return;
+ return -1;
}
struct ndb_mgm_reply reply;
int result = ndb_mgm_stop_signallog(m_mgmsrv, processId, &reply);
if (result != 0) {
ndbout_c("Execute TESTOFF failed.");
printError();
+ return -1;
}
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeSet(int /*processId*/,
const char* parameters, bool /*all*/)
{
if (emptyString(parameters)) {
ndbout << "Missing parameter name." << endl;
- return;
+ return -1;
}
#if 0
// Copy parameters since strtok will modify it
@@ -2013,17 +2419,18 @@ CommandInterpreter::executeSet(int /*processId*/,
abort();
}
}
-#endif
+#endif
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void CommandInterpreter::executeGetStat(int /*processId*/,
+int CommandInterpreter::executeGetStat(int /*processId*/,
const char* parameters, bool /*all*/)
{
if (! emptyString(parameters)) {
ndbout << "No parameters expected to this command." << endl;
- return;
+ return -1;
}
#if 0
@@ -2039,25 +2446,27 @@ void CommandInterpreter::executeGetStat(int /*processId*/,
ndbout << "Number of GETSTAT commands: "
<< statistics._test1 << endl;
*/
+ return 0;
}
//*****************************************************************************
//*****************************************************************************
-void
+int
CommandInterpreter::executeEventReporting(int processId,
const char* parameters,
bool all)
{
+ int retval = 0;
if (emptyString(parameters)) {
ndbout << "Expected argument" << endl;
- return;
+ return -1;
}
BaseString tmp(parameters);
Vector<BaseString> specs;
tmp.split(specs, " ");
- for (int i=0; i < specs.size(); i++)
+ for (int i=0; i < (int) specs.size(); i++)
{
Vector<BaseString> spec;
specs[i].split(spec, "=");
@@ -2098,10 +2507,12 @@ CommandInterpreter::executeEventReporting(int processId,
if (result != 0) {
ndbout_c(" failed.");
printError();
+ retval = -1;
} else {
ndbout_c(" OK!");
}
}
+ return retval;
}
/*****************************************************************************
@@ -2161,7 +2572,7 @@ CommandInterpreter::executeStartBackup(char* parameters)
}
if (result != 0) {
- ndbout << "Start of backup failed" << endl;
+ ndbout << "Backup failed" << endl;
printError();
#if 0
close(fd);
@@ -2202,7 +2613,7 @@ CommandInterpreter::executeStartBackup(char* parameters)
return 0;
}
-void
+int
CommandInterpreter::executeAbortBackup(char* parameters)
{
int bid = -1;
@@ -2221,14 +2632,15 @@ CommandInterpreter::executeAbortBackup(char* parameters)
if (result != 0) {
ndbout << "Abort of backup " << bid << " failed" << endl;
printError();
+ return -1;
} else {
ndbout << "Abort of backup " << bid << " ordered" << endl;
}
}
- return;
+ return 0;
executeAbortBackupError1:
ndbout << "Invalid arguments: expected <BackupId>" << endl;
- return;
+ return -1;
}
#ifdef HAVE_GLOBAL_REPLICATION
@@ -2259,12 +2671,12 @@ CommandInterpreter::executeAbortBackup(char* parameters)
*****************************************************************************/
-void
+int
CommandInterpreter::executeRep(char* parameters)
{
if (emptyString(parameters)) {
ndbout << helpTextRep;
- return;
+ return 0;
}
char * line = my_strdup(parameters,MYF(MY_WME));
@@ -2284,7 +2696,7 @@ CommandInterpreter::executeRep(char* parameters)
if(host == NULL)
{
ndbout_c("host:port must be specified.");
- return;
+ return -1;
}
if(rep_connected) {
@@ -2296,14 +2708,17 @@ CommandInterpreter::executeRep(char* parameters)
if(m_repserver == NULL)
m_repserver = ndb_rep_create_handle();
- if(ndb_rep_connect(m_repserver, host) < 0)
- ndbout_c("Failed to connect to %s", host);
+ if(ndb_rep_connect(m_repserver, host) < 0){
+ ndbout_c("Failed to connect to %s", host);
+ return -1;
+ }
else
rep_connected=true;
- return;
+ return 0;
if(!rep_connected) {
ndbout_c("Not connected to REP server");
+ return -1;
}
}
@@ -2337,17 +2752,18 @@ CommandInterpreter::executeRep(char* parameters)
req = GrepReq::START_DELETE;
} else {
ndbout_c("Illegal argument to command 'REPLICATION START'");
- return;
+ return -1;
}
int result = ndb_rep_command(m_repserver, req, &repId, &reply);
if (result != 0) {
ndbout << "Start of Global Replication failed" << endl;
+ return -1;
} else {
ndbout << "Start of Global Replication ordered" << endl;
}
- return;
+ return 0;
}
/********
@@ -2367,7 +2783,7 @@ CommandInterpreter::executeRep(char* parameters)
char *strEpoch = strtok(NULL, "\0");
if(strEpoch == NULL) {
ndbout_c("Epoch expected!");
- return;
+ return -1;
}
req = GrepReq::STOP;
epoch=atoi(strEpoch);
@@ -2391,16 +2807,17 @@ CommandInterpreter::executeRep(char* parameters)
req = GrepReq::STOP_DELETE;
} else {
ndbout_c("Illegal argument to command 'REPLICATION STOP'");
- return;
+ return -1;
}
int result = ndb_rep_command(m_repserver, req, &repId, &reply, epoch);
if (result != 0) {
ndbout << "Stop command failed" << endl;
+ return -1;
} else {
ndbout << "Stop ordered" << endl;
}
- return;
+ return 0;
}
/*********
@@ -2413,6 +2830,7 @@ CommandInterpreter::executeRep(char* parameters)
if (result != 0) {
ndbout << "Status request of Global Replication failed" << endl;
+ return -1;
} else {
ndbout << "Status request of Global Replication ordered" << endl;
ndbout << "See printout at one of the DB nodes" << endl;
@@ -2420,7 +2838,7 @@ CommandInterpreter::executeRep(char* parameters)
ndbout << " SubscriptionId " << repstate.subid
<< " SubscriptionKey " << repstate.subkey << endl;
}
- return;
+ return 0;
}
/*********
@@ -2439,6 +2857,7 @@ CommandInterpreter::executeRep(char* parameters)
if (result != 0) {
ndbout << "Query repserver failed" << endl;
+ return -1;
} else {
ndbout << "Query repserver sucessful" << endl;
ndbout_c("repstate : QueryCounter %d, f=%d l=%d"
@@ -2447,8 +2866,9 @@ CommandInterpreter::executeRep(char* parameters)
repstate.first[0], repstate.last[0],
repstate.no_of_nodegroups );
}
- return;
+ return 0;
}
+ return 0;
}
#endif // HAVE_GLOBAL_REPLICATION
diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp
index ba5d0308f1f..219559876ec 100644
--- a/ndb/src/mgmclient/main.cpp
+++ b/ndb/src/mgmclient/main.cpp
@@ -38,6 +38,7 @@ extern "C" int add_history(const char *command); /* From readline directory */
#include "ndb_mgmclient.hpp"
const char *progname = "ndb_mgm";
+const char *load_default_groups[]= { "mysql_cluster","ndb_mgm",0 };
static Ndb_mgmclient* com;
@@ -87,6 +88,8 @@ static void usage()
{
short_usage_sub();
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
@@ -121,14 +124,13 @@ read_and_execute(int _try_reconnect)
line_read= strdup(linebuffer);
}
#endif
- return com->execute(line_read,_try_reconnect);
+ return com->execute(line_read, _try_reconnect, 1);
}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
const char *_host = 0;
int _port = 0;
- const char *load_default_groups[]= { "mysql_cluster","ndb_mgm",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
@@ -163,7 +165,7 @@ int main(int argc, char** argv){
}
else
{
- com->execute(opt_execute_str,_try_reconnect, &ret);
+ com->execute(opt_execute_str,_try_reconnect, 0, &ret);
}
delete com;
diff --git a/ndb/src/mgmclient/ndb_mgmclient.hpp b/ndb/src/mgmclient/ndb_mgmclient.hpp
index bffdf69f920..956caebe803 100644
--- a/ndb/src/mgmclient/ndb_mgmclient.hpp
+++ b/ndb/src/mgmclient/ndb_mgmclient.hpp
@@ -23,8 +23,8 @@ class Ndb_mgmclient
public:
Ndb_mgmclient(const char*,int verbose=0);
~Ndb_mgmclient();
- int execute(const char *_line, int _try_reconnect=-1, int *error= 0);
- int execute(int argc, char** argv, int _try_reconnect=-1, int *error= 0);
+ int execute(const char *_line, int _try_reconnect=-1, bool interactive=1, int *error= 0);
+ int execute(int argc, char** argv, int _try_reconnect=-1, bool interactive=1, int *error= 0);
int disconnect();
private:
CommandInterpreter *m_cmd;
diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp
index ab4f2b413b3..d4e72a7ff1d 100644
--- a/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -2604,6 +2604,13 @@ transformNode(InitConfigFileParser::Context & ctx, const char * data){
return false;
}
+ if(id >= MAX_NODES)
+ {
+ ctx.reportError("too many nodes configured, only up to %d nodes supported.",
+ MAX_NODES);
+ return false;
+ }
+
// next node id _always_ next numbers after last used id
ctx.m_userProperties.put("NextNodeId", id+1, true);
@@ -3495,11 +3502,11 @@ sanity_checks(Vector<ConfigInfo::ConfigRuleSection>&sections,
Uint32 mgm_nodes = 0;
Uint32 api_nodes = 0;
if (!ctx.m_userProperties.get("DB", &db_nodes)) {
- ctx.reportError("At least one database node should be defined in config file");
+ ctx.reportError("At least one database node (ndbd) should be defined in config file");
return false;
}
if (!ctx.m_userProperties.get("MGM", &mgm_nodes)) {
- ctx.reportError("At least one management server node should be defined in config file");
+ ctx.reportError("At least one management server node (ndb_mgmd) should be defined in config file");
return false;
}
if (!ctx.m_userProperties.get("API", &api_nodes)) {
diff --git a/ndb/src/mgmsrv/Makefile.am b/ndb/src/mgmsrv/Makefile.am
index 7fd3fa66b43..effad38be10 100644
--- a/ndb/src/mgmsrv/Makefile.am
+++ b/ndb/src/mgmsrv/Makefile.am
@@ -23,7 +23,7 @@ INCLUDES_LOC = -I$(top_srcdir)/ndb/src/ndbapi \
-I$(top_srcdir)/ndb/src/common/mgmcommon \
-I$(top_srcdir)/ndb/src/mgmclient
-LDADD_LOC = $(top_srcdir)/ndb/src/mgmclient/CommandInterpreter.o \
+LDADD_LOC = $(top_builddir)/ndb/src/mgmclient/CommandInterpreter.o \
$(top_builddir)/ndb/src/libndbclient.la \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/mysys/libmysys.a \
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index 5fabb84adb7..766992af0cb 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -449,7 +449,10 @@ MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
// read config locally
_config= readConfig();
if (_config == 0) {
- ndbout << "Unable to read config file" << endl;
+ if (config_filename != NULL)
+ ndbout << "Invalid configuration file: " << config_filename << endl;
+ else
+ ndbout << "Invalid configuration file" << endl;
exit(-1);
}
}
@@ -832,7 +835,7 @@ MgmtSrvr::sendVersionReq(int v_nodeId, Uint32 &version, const char **address)
case GSN_API_VERSION_CONF: {
const ApiVersionConf * const conf =
CAST_CONSTPTR(ApiVersionConf, signal->getDataPtr());
- assert(conf->nodeId == v_nodeId);
+ assert((int) conf->nodeId == v_nodeId);
version = conf->version;
struct in_addr in;
in.s_addr= conf->inet_addr;
@@ -1011,6 +1014,11 @@ int MgmtSrvr::sendSTOP_REQ(const Vector<NodeId> &node_ids,
{
nodeId= node_ids[i];
ndbout << "asked to stop " << nodeId << endl;
+
+ if ((getNodeType(nodeId) != NDB_MGM_NODE_TYPE_MGM)
+ &&(getNodeType(nodeId) != NDB_MGM_NODE_TYPE_NDB))
+ return WRONG_PROCESS_TYPE;
+
if (getNodeType(nodeId) != NDB_MGM_NODE_TYPE_MGM)
nodes_to_stop.set(nodeId);
else if (nodeId != getOwnNodeId())
@@ -1565,7 +1573,7 @@ MgmtSrvr::setEventReportingLevelImpl(int nodeId,
NodeBitmask nodes;
nodes.clear();
Uint32 max = (nodeId == 0) ? (nodeId = 1, MAX_NDB_NODES) : nodeId;
- for(; nodeId <= max; nodeId++)
+ for(; (Uint32) nodeId <= max; nodeId++)
{
if (nodeTypes[nodeId] != NODE_TYPE_DB)
continue;
@@ -1993,8 +2001,8 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
int log_event)
{
DBUG_ENTER("MgmtSrvr::alloc_node_id");
- DBUG_PRINT("enter", ("nodeid=%d, type=%d, client_addr=%d",
- *nodeId, type, client_addr));
+ DBUG_PRINT("enter", ("nodeid: %d type: %d client_addr: 0x%ld",
+ *nodeId, type, (long) client_addr));
if (g_no_nodeid_checks) {
if (*nodeId == 0) {
error_string.appfmt("no-nodeid-checks set in management server.\n"
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 7f5b0e29442..bf16aa03d04 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -33,6 +33,7 @@
#include "../mgmapi/ndb_logevent.hpp"
#include <base64.h>
+#include <ndberror.h>
extern bool g_StopServer;
extern bool g_RestartServer;
@@ -146,6 +147,7 @@ ParserRow<MgmApiSession> commands[] = {
MGM_CMD("get status", &MgmApiSession::getStatus, ""),
MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""),
+ MGM_CMD("get cluster loglevel", &MgmApiSession::getClusterLogLevel, ""),
MGM_CMD("restart node", &MgmApiSession::restart_v1, ""),
MGM_ARG("node", String, Mandatory, "Nodes to restart"),
@@ -803,6 +805,32 @@ MgmApiSession::endSession(Parser<MgmApiSession>::Context &,
}
void
+MgmApiSession::getClusterLogLevel(Parser<MgmApiSession>::Context & , Properties const &) {
+ const char* names[] = { "startup",
+ "shutdown",
+ "statistics",
+ "checkpoint",
+ "noderestart",
+ "connection",
+ "info",
+ "warning",
+ "error",
+ "congestion",
+ "debug",
+ "backup" };
+
+ int loglevel_count = (CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1) ;
+ LogLevel::EventCategory category;
+
+ m_output->println("get cluster loglevel");
+ for(int i = 0; i < loglevel_count; i++) {
+ category = (LogLevel::EventCategory) i;
+ m_output->println("%s: %d", names[i], m_mgmsrv.m_event_listner[0].m_logLevel.getLogLevel(category));
+ }
+ m_output->println("");
+}
+
+void
MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
Properties const &args) {
const char *reply= "set cluster loglevel reply";
@@ -1671,7 +1699,7 @@ MgmApiSession::report_event(Parser_t::Context &ctx,
BaseString tmp(data_string);
Vector<BaseString> item;
tmp.split(item, " ");
- for (int i = 0; i < length ; i++)
+ for (int i = 0; (Uint32) i < length ; i++)
{
sscanf(item[i].c_str(), "%u", data+i);
}
diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp
index 6e0bb701d7b..f9b87e3b63d 100644
--- a/ndb/src/mgmsrv/Services.hpp
+++ b/ndb/src/mgmsrv/Services.hpp
@@ -87,6 +87,8 @@ public:
void bye(Parser_t::Context &ctx, const class Properties &args);
void endSession(Parser_t::Context &ctx, const class Properties &args);
void setLogLevel(Parser_t::Context &ctx, const class Properties &args);
+ void getClusterLogLevel(Parser_t::Context &ctx,
+ const class Properties &args);
void setClusterLogLevel(Parser_t::Context &ctx,
const class Properties &args);
void setLogFilter(Parser_t::Context &ctx, const class Properties &args);
diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp
index 5960a3517b5..32b9de92d90 100644
--- a/ndb/src/mgmsrv/main.cpp
+++ b/ndb/src/mgmsrv/main.cpp
@@ -47,6 +47,7 @@
#define DEBUG(x) ndbout << x << endl;
const char progname[] = "mgmtsrvr";
+const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 };
// copied from mysql.cc to get readline
extern "C" {
@@ -183,6 +184,8 @@ static void usage()
{
short_usage_sub();
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
@@ -196,7 +199,6 @@ int main(int argc, char** argv)
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
diff --git a/ndb/src/ndbapi/ClusterMgr.cpp b/ndb/src/ndbapi/ClusterMgr.cpp
index 475561af225..8545c599341 100644
--- a/ndb/src/ndbapi/ClusterMgr.cpp
+++ b/ndb/src/ndbapi/ClusterMgr.cpp
@@ -213,7 +213,7 @@ ClusterMgr::forceHB()
int nodeId= 0;
for(int i=0;
- NodeBitmask::NotFound!=(nodeId= waitForHBFromNodes.find(i));
+ (int) NodeBitmask::NotFound != (nodeId= waitForHBFromNodes.find(i));
i= nodeId+1)
{
#ifdef DEBUG_REG
diff --git a/ndb/src/ndbapi/DictCache.cpp b/ndb/src/ndbapi/DictCache.cpp
index bb59c16fb7c..ba8b0799398 100644
--- a/ndb/src/ndbapi/DictCache.cpp
+++ b/ndb/src/ndbapi/DictCache.cpp
@@ -116,7 +116,8 @@ void GlobalDictCache::printCache()
NdbElement_t<Vector<TableVersion> > * curr = m_tableHash.getNext(0);
while(curr != 0){
DBUG_PRINT("curr", ("len: %d, hash: %d, lk: %d, str: %s",
- curr->len, curr->hash, curr->localkey1, curr->str));
+ curr->len, curr->hash, curr->localkey1,
+ (char*) curr->str));
if (curr->theData){
Vector<TableVersion> * vers = curr->theData;
const unsigned sz = vers->size();
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index 9d1c78a5972..59a204be2a8 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -355,8 +355,9 @@ Ndb::startTransaction(const NdbDictionary::Table *table,
{
NdbTransaction *trans= startTransactionLocal(0, nodeId);
- DBUG_PRINT("exit",("start trans: 0x%x transid: 0x%llx",
- trans, trans ? trans->getTransactionId() : 0));
+ DBUG_PRINT("exit",("start trans: 0x%lx transid: 0x%lx",
+ (long) trans,
+ (long) (trans ? trans->getTransactionId() : 0)));
DBUG_RETURN(trans);
}
} else {
@@ -377,7 +378,7 @@ Ndb::hupp(NdbTransaction* pBuddyTrans)
{
DBUG_ENTER("Ndb::hupp");
- DBUG_PRINT("enter", ("trans: 0x%x",pBuddyTrans));
+ DBUG_PRINT("enter", ("trans: 0x%lx", (long) pBuddyTrans));
Uint32 aPriority = 0;
if (pBuddyTrans == NULL){
@@ -402,8 +403,9 @@ Ndb::hupp(NdbTransaction* pBuddyTrans)
}
pCon->setTransactionId(pBuddyTrans->getTransactionId());
pCon->setBuddyConPtr((Uint32)pBuddyTrans->getTC_ConnectPtr());
- DBUG_PRINT("exit", ("hupp trans: 0x%x transid: 0x%llx",
- pCon, pCon ? pCon->getTransactionId() : 0));
+ DBUG_PRINT("exit", ("hupp trans: 0x%lx transid: 0x%lx",
+ (long) pCon,
+ (long) (pCon ? pCon->getTransactionId() : 0)));
DBUG_RETURN(pCon);
} else {
DBUG_RETURN(NULL);
@@ -490,8 +492,9 @@ Ndb::closeTransaction(NdbTransaction* aConnection)
tCon = theTransactionList;
theRemainingStartTransactions++;
- DBUG_PRINT("info",("close trans: 0x%x transid: 0x%llx",
- aConnection, aConnection->getTransactionId()));
+ DBUG_PRINT("info",("close trans: 0x%lx transid: 0x%lx",
+ (long) aConnection,
+ (long) aConnection->getTransactionId()));
DBUG_PRINT("info",("magic number: 0x%x TCConPtr: 0x%x theMyRef: 0x%x 0x%x",
aConnection->theMagicNumber, aConnection->theTCConPtr,
aConnection->theMyRef, getReference()));
@@ -774,7 +777,7 @@ Ndb::getAutoIncrementValue(const char* aTableName,
}
if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1)
DBUG_RETURN(-1);
- DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_PRINT("info", ("value %lu", (ulong) tupleId));
DBUG_RETURN(0);
}
@@ -795,7 +798,7 @@ Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable,
}
if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1)
DBUG_RETURN(-1);
- DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_PRINT("info", ("value %lu", (ulong)tupleId));
DBUG_RETURN(0);
}
@@ -808,7 +811,7 @@ Ndb::getTupleIdFromNdb(Ndb_local_table_info* info,
{
assert(info->m_first_tuple_id < info->m_last_tuple_id);
tupleId = ++info->m_first_tuple_id;
- DBUG_PRINT("info", ("next cached value %llu", (ulonglong)tupleId));
+ DBUG_PRINT("info", ("next cached value %lu", (ulong)tupleId));
}
else
{
@@ -842,7 +845,7 @@ Ndb::readAutoIncrementValue(const char* aTableName,
}
if (readTupleIdFromNdb(info, tupleId) == -1)
DBUG_RETURN(-1);
- DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_PRINT("info", ("value %lu", (ulong)tupleId));
DBUG_RETURN(0);
}
@@ -863,7 +866,7 @@ Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable,
}
if (readTupleIdFromNdb(info, tupleId) == -1)
DBUG_RETURN(-1);
- DBUG_PRINT("info", ("value %llu", (ulonglong)tupleId));
+ DBUG_PRINT("info", ("value %lu", (ulong)tupleId));
DBUG_RETURN(0);
}
@@ -945,8 +948,8 @@ Ndb::setTupleIdInNdb(Ndb_local_table_info* info,
{
info->m_first_tuple_id = tupleId - 1;
DBUG_PRINT("info",
- ("Setting next auto increment cached value to %llu",
- (ulonglong)tupleId));
+ ("Setting next auto increment cached value to %lu",
+ (ulong)tupleId));
DBUG_RETURN(0);
}
}
@@ -973,7 +976,8 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op)
{
DBUG_ENTER("Ndb::opTupleIdOnNdb");
Uint32 aTableId = info->m_table_impl->m_tableId;
- DBUG_PRINT("enter", ("table=%u value=%llu op=%u", aTableId, opValue, op));
+ DBUG_PRINT("enter", ("table: %u value: %lu op: %u",
+ aTableId, (ulong) opValue, op));
NdbTransaction* tConnection;
NdbOperation* tOperation= 0; // Compiler warning if not initialized
@@ -1047,8 +1051,8 @@ Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op)
else
{
DBUG_PRINT("info",
- ("Setting next auto increment value (db) to %llu",
- (ulonglong)opValue));
+ ("Setting next auto increment value (db) to %lu",
+ (ulong)opValue));
info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1;
}
break;
@@ -1244,7 +1248,7 @@ Ndb::internalize_index_name(const NdbTableImpl * table,
if (!table)
{
DBUG_PRINT("error", ("!table"));
- return ret;
+ DBUG_RETURN(ret);
}
if (fullyQualifiedNames)
diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp
index ca08c39e070..86875cafbab 100644
--- a/ndb/src/ndbapi/NdbOperation.cpp
+++ b/ndb/src/ndbapi/NdbOperation.cpp
@@ -319,13 +319,31 @@ NdbOperation::setValue( Uint32 anAttrId,
NdbBlob*
NdbOperation::getBlobHandle(const char* anAttrName)
{
- return getBlobHandle(theNdbCon, m_currentTable->getColumn(anAttrName));
+ const NdbColumnImpl* col = m_currentTable->getColumn(anAttrName);
+ if (col == NULL)
+ {
+ setErrorCode(4004);
+ return NULL;
+ }
+ else
+ {
+ return getBlobHandle(theNdbCon, col);
+ }
}
NdbBlob*
NdbOperation::getBlobHandle(Uint32 anAttrId)
{
- return getBlobHandle(theNdbCon, m_currentTable->getColumn(anAttrId));
+ const NdbColumnImpl* col = m_currentTable->getColumn(anAttrId);
+ if (col == NULL)
+ {
+ setErrorCode(4004);
+ return NULL;
+ }
+ else
+ {
+ return getBlobHandle(theNdbCon, col);
+ }
}
int
diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp
index 835e33dfb40..42dec161307 100644
--- a/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -407,10 +407,10 @@ NdbOperation::setValue( const NdbColumnImpl* tAttrInfo,
const char* aValuePassed, Uint32 len)
{
DBUG_ENTER("NdbOperation::setValue");
- DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
+ DBUG_PRINT("enter", ("col: %s op: %d val: 0x%lx len: %u",
tAttrInfo->m_name.c_str(),
theOperationType,
- aValuePassed, len));
+ (long) aValuePassed, len));
if (aValuePassed != NULL)
DBUG_DUMP("value", (char*)aValuePassed, len);
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
index 58a816e3c1a..11713678478 100644
--- a/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -205,7 +205,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
tcKeyReq->setKeyLength(tReqInfo, tTupKeyLen);
// A simple read is always ignore error
- abortOption = tSimpleIndicator ? AO_IgnoreError : abortOption;
+ abortOption = tSimpleIndicator ? (Uint8) AO_IgnoreError : abortOption;
tcKeyReq->setAbortOption(tReqInfo, abortOption);
Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
diff --git a/ndb/src/ndbapi/NdbOperationInt.cpp b/ndb/src/ndbapi/NdbOperationInt.cpp
index 41e0cb1d140..6defb37467f 100644
--- a/ndb/src/ndbapi/NdbOperationInt.cpp
+++ b/ndb/src/ndbapi/NdbOperationInt.cpp
@@ -1015,8 +1015,8 @@ NdbOperation::branch_col(Uint32 type,
bool nopad, Uint32 Label){
DBUG_ENTER("NdbOperation::branch_col");
- DBUG_PRINT("enter", ("type=%u col=%u val=0x%x len=%u label=%u",
- type, ColId, val, len, Label));
+ DBUG_PRINT("enter", ("type: %u col:%u val: 0x%lx len: %u label: %u",
+ type, ColId, (long) val, len, Label));
if (val != NULL)
DBUG_DUMP("value", (char*)val, len);
diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp
index 4be7ccb313c..ede3240e9f4 100644
--- a/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -58,10 +58,10 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
Uint32 aVariableKeyLen)
{
DBUG_ENTER("NdbOperation::equal_impl");
- DBUG_PRINT("enter", ("col=%s op=%d val=0x%x len=%u",
+ DBUG_PRINT("enter", ("col: %s op: %d val: 0x%lx len: %u",
tAttrInfo->m_name.c_str(),
theOperationType,
- aValuePassed, aVariableKeyLen));
+ (long) aValuePassed, aVariableKeyLen));
if (aValuePassed != NULL)
DBUG_DUMP("value", (char*)aValuePassed, aVariableKeyLen);
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index c5a0ebbaf60..92a1e476b45 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -507,6 +507,8 @@ int NdbScanOperation::nextResultImpl(bool fetchAllowed, bool forceSend)
int return_code = theNdb->receiveResponse(3*timeout);
if (return_code == 0 && seq == tp->getNodeSequence(nodeId)) {
continue;
+ } else if(return_code == -1){
+ retVal = -1;
} else {
idx = last;
retVal = -2; //return_code;
@@ -651,9 +653,9 @@ NdbScanOperation::doSend(int ProcessorId)
void NdbScanOperation::close(bool forceSend, bool releaseOp)
{
DBUG_ENTER("NdbScanOperation::close");
- DBUG_PRINT("enter", ("this=%x tcon=%x con=%x force=%d release=%d",
- (UintPtr)this,
- (UintPtr)m_transConnection, (UintPtr)theNdbCon,
+ DBUG_PRINT("enter", ("this: 0x%lx tcon: 0x%lx con: 0x%lx force: %d release: %d",
+ (long)this,
+ (long)m_transConnection, (long)theNdbCon,
forceSend, releaseOp));
if(m_transConnection){
@@ -678,9 +680,27 @@ void NdbScanOperation::close(bool forceSend, bool releaseOp)
theNdbCon = NULL;
m_transConnection = NULL;
- if (releaseOp && tTransCon) {
+ if (tTransCon && releaseOp)
+ {
NdbIndexScanOperation* tOp = (NdbIndexScanOperation*)this;
- tTransCon->releaseExecutedScanOperation(tOp);
+
+ bool ret = true;
+ if (theStatus != WaitResponse)
+ {
+ /**
+ * Not executed yet
+ */
+ ret =
+ tTransCon->releaseScanOperation(&tTransCon->m_theFirstScanOperation,
+ &tTransCon->m_theLastScanOperation,
+ tOp);
+ }
+ else
+ {
+ ret = tTransCon->releaseScanOperation(&tTransCon->m_firstExecutedScanOp,
+ 0, tOp);
+ }
+ assert(ret);
}
tCon->theScanningOp = 0;
@@ -1380,7 +1400,11 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed,
continue;
}
if(DEBUG_NEXT_RESULT) ndbout_c("return -1");
- setErrorCode(4028);
+ if(return_code == -1){
+ setErrorCode(4008);
+ } else {
+ setErrorCode(4028);
+ }
return -1;
}
diff --git a/ndb/src/ndbapi/NdbTransaction.cpp b/ndb/src/ndbapi/NdbTransaction.cpp
index e82e02067a6..36b1217c101 100644
--- a/ndb/src/ndbapi/NdbTransaction.cpp
+++ b/ndb/src/ndbapi/NdbTransaction.cpp
@@ -357,8 +357,37 @@ NdbTransaction::execute(ExecType aTypeOfExec,
ret = -1;
if(savedError.code==0)
savedError= theError;
+
+ /**
+ * If AO_IgnoreError, error codes arent always set on individual
+ * operations, making postExecute impossible
+ */
+ if (abortOption == AO_IgnoreError)
+ {
+ if (theCompletedFirstOp != NULL)
+ {
+ if (tCompletedFirstOp != NULL)
+ {
+ tCompletedLastOp->next(theCompletedFirstOp);
+ theCompletedFirstOp = tCompletedFirstOp;
+ }
+ }
+ else
+ {
+ theCompletedFirstOp = tCompletedFirstOp;
+ theCompletedLastOp = tCompletedLastOp;
+ }
+ if (tPrepOp != NULL && tRestOp != NULL) {
+ if (theFirstOpInList == NULL)
+ theFirstOpInList = tRestOp;
+ else
+ theLastOpInList->next(tRestOp);
+ theLastOpInList = tLastOp;
+ }
+ DBUG_RETURN(-1);
+ }
}
-
+
#ifdef ndb_api_crash_on_complex_blob_abort
assert(theFirstOpInList == NULL && theLastOpInList == NULL);
#else
@@ -501,8 +530,8 @@ NdbTransaction::executeAsynchPrepare( ExecType aTypeOfExec,
AbortOption abortOption)
{
DBUG_ENTER("NdbTransaction::executeAsynchPrepare");
- DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: %x, anyObject: %x",
- aTypeOfExec, aCallback, anyObject));
+ DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: 0x%lx, anyObject: Ox%lx",
+ aTypeOfExec, (long) aCallback, (long) anyObject));
/**
* Reset error.code on execute
@@ -978,27 +1007,59 @@ void
NdbTransaction::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
{
DBUG_ENTER("NdbTransaction::releaseExecutedScanOperation");
- DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp))
+ DBUG_PRINT("enter", ("this: 0x%lx op=0x%lx",
+ (long)this, (long)cursorOp));
+
+ releaseScanOperation(&m_firstExecutedScanOp, 0, cursorOp);
+
+ DBUG_VOID_RETURN;
+}//NdbTransaction::releaseExecutedScanOperation()
- // here is one reason to make op lists doubly linked
- if (m_firstExecutedScanOp == cursorOp) {
- m_firstExecutedScanOp = (NdbIndexScanOperation*)cursorOp->theNext;
- cursorOp->release();
- theNdb->releaseScanOperation(cursorOp);
- } else if (m_firstExecutedScanOp != NULL) {
- NdbIndexScanOperation* tOp = m_firstExecutedScanOp;
- while (tOp->theNext != NULL) {
- if (tOp->theNext == cursorOp) {
- tOp->theNext = cursorOp->theNext;
- cursorOp->release();
- theNdb->releaseScanOperation(cursorOp);
- break;
+bool
+NdbTransaction::releaseScanOperation(NdbIndexScanOperation** listhead,
+ NdbIndexScanOperation** listtail,
+ NdbIndexScanOperation* op)
+{
+ if (* listhead == op)
+ {
+ * listhead = (NdbIndexScanOperation*)op->theNext;
+ if (listtail && *listtail == op)
+ {
+ assert(* listhead == 0);
+ * listtail = 0;
+ }
+
+ }
+ else
+ {
+ NdbIndexScanOperation* tmp = * listhead;
+ while (tmp != NULL)
+ {
+ if (tmp->theNext == op)
+ {
+ tmp->theNext = (NdbIndexScanOperation*)op->theNext;
+ if (listtail && *listtail == op)
+ {
+ assert(op->theNext == 0);
+ *listtail = tmp;
+ }
+ break;
}
- tOp = (NdbIndexScanOperation*)tOp->theNext;
+ tmp = (NdbIndexScanOperation*)tmp->theNext;
}
+ if (tmp == NULL)
+ op = NULL;
}
- DBUG_VOID_RETURN;
-}//NdbTransaction::releaseExecutedScanOperation()
+
+ if (op != NULL)
+ {
+ op->release();
+ theNdb->releaseScanOperation(op);
+ return true;
+ }
+
+ return false;
+}
/*****************************************************************************
NdbOperation* getNdbOperation(const char* aTableName);
@@ -1170,9 +1231,9 @@ NdbTransaction::getNdbIndexScanOperation(const NdbIndexImpl* index,
if(tOp)
{
tOp->m_currentTable = table;
+ // Mark that this really an NdbIndexScanOperation
+ tOp->m_type = NdbOperation::OrderedIndexScan;
}
- // Mark that this really an NdbIndexScanOperation
- tOp->m_type = NdbOperation::OrderedIndexScan;
return tOp;
} else {
setOperationErrorCodeAbort(4271);
diff --git a/ndb/src/ndbapi/Ndbif.cpp b/ndb/src/ndbapi/Ndbif.cpp
index 6aaf44d0168..3ab9446e011 100644
--- a/ndb/src/ndbapi/Ndbif.cpp
+++ b/ndb/src/ndbapi/Ndbif.cpp
@@ -193,11 +193,11 @@ void Ndb::connected(Uint32 ref)
((Uint64)tmpTheNode << 40);
theFirstTransId += theFacade->m_max_trans_id;
// assert(0);
- DBUG_PRINT("info",("connected with ref=%x, id=%d, no_db_nodes=%d, first_trans_id=%lx",
+ DBUG_PRINT("info",("connected with ref=%x, id=%d, no_db_nodes=%d, first_trans_id: 0x%lx",
theMyRef,
tmpTheNode,
theImpl->theNoOfDBnodes,
- theFirstTransId));
+ (long) theFirstTransId));
theCommitAckSignal = new NdbApiSignal(theMyRef);
theDictionary->m_receiver.m_reference= theMyRef;
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index 40cac675b21..fbabe9e6dc6 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -39,7 +39,7 @@ Ndb::Ndb( Ndb_cluster_connection *ndb_cluster_connection,
: theImpl(NULL)
{
DBUG_ENTER("Ndb::Ndb()");
- DBUG_PRINT("enter",("Ndb::Ndb this=0x%x", this));
+ DBUG_PRINT("enter",("Ndb::Ndb this: 0x%lx", (long) this));
setup(ndb_cluster_connection, aDataBase, aSchema);
DBUG_VOID_RETURN;
}
@@ -115,7 +115,7 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
Ndb::~Ndb()
{
DBUG_ENTER("Ndb::~Ndb()");
- DBUG_PRINT("enter",("Ndb::~Ndb this=0x%x",this));
+ DBUG_PRINT("enter",("Ndb::~Ndb this: 0x%lx",(long) this));
doDisconnect();
if (TransporterFacade::instance() != NULL && theNdbBlockNumber > 0){
diff --git a/ndb/src/ndbapi/Ndblist.cpp b/ndb/src/ndbapi/Ndblist.cpp
index f82348fc91d..00ab4599fdf 100644
--- a/ndb/src/ndbapi/Ndblist.cpp
+++ b/ndb/src/ndbapi/Ndblist.cpp
@@ -361,7 +361,7 @@ void
Ndb::releaseScanOperation(NdbIndexScanOperation* aScanOperation)
{
DBUG_ENTER("Ndb::releaseScanOperation");
- DBUG_PRINT("enter", ("op=%x", (UintPtr)aScanOperation));
+ DBUG_PRINT("enter", ("op: 0x%lx", (long)aScanOperation));
#ifdef ndb_release_check_dup
{ NdbIndexScanOperation* tOp = theScanOpIdleList;
while (tOp != NULL) {
diff --git a/ndb/src/ndbapi/ndb_cluster_connection.cpp b/ndb/src/ndbapi/ndb_cluster_connection.cpp
index 1e53558f179..3ae84125112 100644
--- a/ndb/src/ndbapi/ndb_cluster_connection.cpp
+++ b/ndb/src/ndbapi/ndb_cluster_connection.cpp
@@ -262,7 +262,7 @@ Ndb_cluster_connection_impl::Ndb_cluster_connection_impl(const char *
m_name(0)
{
DBUG_ENTER("Ndb_cluster_connection");
- DBUG_PRINT("enter",("Ndb_cluster_connection this=0x%x", this));
+ DBUG_PRINT("enter",("Ndb_cluster_connection this=0x%lx", (long) this));
g_eventLogger.createConsoleHandler();
g_eventLogger.setCategory("NdbApi");
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index 946e6fe4cc2..6173292261d 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -378,7 +378,7 @@ ErrorBundle ErrorCodes[] = {
{ 1305, IE, "Backup definition not implemented" },
{ 1306, AE, "Backup not supported in diskless mode (change Diskless)" },
- { 1321, IE, "Backup aborted by application" },
+ { 1321, UD, "Backup aborted by user request" },
{ 1322, IE, "Backup already completed" },
{ 1323, IE, "1323" },
{ 1324, IE, "Backup log buffer full" },
@@ -401,7 +401,7 @@ ErrorBundle ErrorCodes[] = {
* Still uncategorized
*/
{ 720, AE, "Attribute name reused in table definition" },
- { 4004, AE, "Attribute name not found in the Table" },
+ { 4004, AE, "Attribute name or id not found in the table" },
{ 4100, AE, "Status Error in NDB" },
{ 4101, AE, "No connections to NDB available and connect failed" },
diff --git a/ndb/test/ndbapi/flexScan.cpp b/ndb/test/ndbapi/flexScan.cpp
index 4d2c85d6955..1f001bd0210 100644
--- a/ndb/test/ndbapi/flexScan.cpp
+++ b/ndb/test/ndbapi/flexScan.cpp
@@ -27,7 +27,7 @@
verify delete
Arguments:
- -f Location of Ndb.cfg file, default Ndb.cfg
+ -f Location of my.cnf file, default my.cnf
-t Number of threads to start, default 1
-o Number of operations per loop, default 500 -l Number of loops to run, default 1, 0=infinite
-a Number of attributes, default 25
@@ -829,7 +829,7 @@ static int createTables(Ndb* pMyNdb)
static void printUsage()
{
ndbout << "Usage of flexScan:" << endl;
- ndbout << "-f <path> Location of Ndb.cfg file, default: Ndb.cfg" << endl;
+ ndbout << "-f <path> Location of my.cnf file, default: my.cnf" << endl;
ndbout << "-t <int> Number of threads to start, default 1" << endl;
ndbout << "-o <int> Number of operations per loop, default 500" << endl;
ndbout << "-l <int> Number of loops to run, default 1, 0=infinite" << endl;
diff --git a/ndb/test/ndbapi/testMgm.cpp b/ndb/test/ndbapi/testMgm.cpp
index ef653d3f972..3234117405c 100644
--- a/ndb/test/ndbapi/testMgm.cpp
+++ b/ndb/test/ndbapi/testMgm.cpp
@@ -21,6 +21,8 @@
#include <NdbRestarter.hpp>
#include <Vector.hpp>
#include <random.h>
+#include <mgmapi.h>
+#include <mgmapi_debug.h>
int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
@@ -167,6 +169,26 @@ int runTestSingleUserMode(NDBT_Context* ctx, NDBT_Step* step){
return result;
}
+int runTestApiSession(NDBT_Context* ctx, NDBT_Step* step)
+{
+ char *mgm= ctx->getRemoteMgm();
+
+ NdbMgmHandle h;
+ h= ndb_mgm_create_handle();
+ ndb_mgm_set_connectstring(h, mgm);
+ ndb_mgm_connect(h,0,0,0);
+ int s= ndb_mgm_get_fd(h);
+ write(s,"get",3);
+ ndb_mgm_disconnect(h);
+ ndb_mgm_destroy_handle(&h);
+ /** NOTE: WE CANNOT REALLY TEST ANYTHING in 5.0
+ *
+ * a more conservative patch for 5.0, full get and list
+ * sessions in 5.1.
+ *
+ * This is kept so that we can at least manually test easily
+ */
+}
NDBT_TESTSUITE(testMgm);
@@ -175,6 +197,11 @@ TESTCASE("SingleUserMode",
INITIALIZER(runTestSingleUserMode);
FINALIZER(runClearTable);
}
+TESTCASE("ApiSessionFailure",
+ "Test failures in MGMAPI session"){
+ INITIALIZER(runTestApiSession);
+
+}
NDBT_TESTSUITE_END(testMgm);
int main(int argc, const char** argv){
diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp
index 942ee2ec966..271f19a5477 100644
--- a/ndb/test/ndbapi/testOIBasic.cpp
+++ b/ndb/test/ndbapi/testOIBasic.cpp
@@ -47,7 +47,6 @@ struct Opt {
int m_die;
bool m_dups;
NdbDictionary::Object::FragmentType m_fragtype;
- unsigned m_subsubloop;
const char* m_index;
unsigned m_loop;
bool m_msglock;
@@ -56,6 +55,7 @@ struct Opt {
unsigned m_pctnull;
unsigned m_rows;
unsigned m_samples;
+ unsigned m_scanbatch;
unsigned m_scanpar;
unsigned m_scanstop;
int m_seed;
@@ -74,7 +74,6 @@ struct Opt {
m_die(0),
m_dups(false),
m_fragtype(NdbDictionary::Object::FragUndefined),
- m_subsubloop(4),
m_index(0),
m_loop(1),
m_msglock(true),
@@ -83,6 +82,7 @@ struct Opt {
m_pctnull(10),
m_rows(1000),
m_samples(0),
+ m_scanbatch(0),
m_scanpar(0),
m_scanstop(0),
m_seed(-1),
@@ -120,9 +120,10 @@ printhelp()
<< " -pctnull N pct NULL values in nullable column [" << d.m_pctnull << "]" << endl
<< " -rows N rows per thread [" << d.m_rows << "]" << endl
<< " -samples N samples for some timings (0=all) [" << d.m_samples << "]" << endl
- << " -scanpar N scan parallelism [" << d.m_scanpar << "]" << endl
+ << " -scanbatch N scan batch 0=default [" << d.m_scanbatch << "]" << endl
+ << " -scanpar N scan parallel 0=default [" << d.m_scanpar << "]" << endl
<< " -seed N srandom seed 0=loop number -1=random [" << d.m_seed << "]" << endl
- << " -subloop N subtest loop count [" << d.m_subloop << "]" << endl
+ << " -subloop N subtest (and subsubtest) loop count [" << d.m_subloop << "]" << endl
<< " -table xyz only given table numbers (digits 0-9)" << endl
<< " -threads N number of threads [" << d.m_threads << "]" << endl
<< " -vN verbosity [" << d.m_v << "]" << endl
@@ -294,6 +295,7 @@ struct Par : public Opt {
Set& set() const { assert(m_set != 0); return *m_set; }
Tmr* m_tmr;
Tmr& tmr() const { assert(m_tmr != 0); return *m_tmr; }
+ char m_currcase[2];
unsigned m_lno;
unsigned m_slno;
unsigned m_totrows;
@@ -302,6 +304,7 @@ struct Par : public Opt {
unsigned m_pctrange;
unsigned m_pctbrange;
int m_bdir;
+ bool m_noindexkeyupdate;
// choice of key
bool m_randomkey;
// do verify after read
@@ -330,6 +333,7 @@ struct Par : public Opt {
m_pctrange(40),
m_pctbrange(80),
m_bdir(0),
+ m_noindexkeyupdate(false),
m_randomkey(false),
m_verify(false),
m_deadlock(false),
@@ -337,7 +341,9 @@ struct Par : public Opt {
m_lockmode(NdbOperation::LM_Read),
m_tupscan(false),
m_ordered(false),
- m_descending(false) {
+ m_descending(false)
+ {
+ m_currcase[0] = 0;
}
};
@@ -892,6 +898,8 @@ struct Tab {
const Col** m_col;
unsigned m_itabs;
const ITab** m_itab;
+ unsigned m_orderedindexes;
+ unsigned m_hashindexes;
// pk must contain an Unsigned column
unsigned m_keycol;
void coladd(unsigned k, Col* colptr);
@@ -906,6 +914,8 @@ Tab::Tab(const char* name, unsigned cols, unsigned itabs, unsigned keycol) :
m_col(new const Col* [cols + 1]),
m_itabs(itabs),
m_itab(new const ITab* [itabs + 1]),
+ m_orderedindexes(0),
+ m_hashindexes(0),
m_keycol(keycol)
{
for (unsigned k = 0; k <= cols; k++)
@@ -935,8 +945,12 @@ Tab::coladd(unsigned k, Col* colptr)
void
Tab::itabadd(unsigned j, ITab* itabptr)
{
- assert(j < m_itabs && m_itab[j] == 0);
+ assert(j < m_itabs && m_itab[j] == 0 && itabptr != 0);
m_itab[j] = itabptr;
+ if (itabptr->m_type == ITab::OrderedIndex)
+ m_orderedindexes++;
+ else
+ m_hashindexes++;
}
static NdbOut&
@@ -1434,7 +1448,7 @@ Con::readTuples(Par par)
int scan_flags = 0;
if (par.m_tupscan)
scan_flags |= NdbScanOperation::SF_TupScan;
- CHKCON(m_scanop->readTuples(par.m_lockmode, scan_flags, par.m_scanpar) == 0, *this);
+ CHKCON(m_scanop->readTuples(par.m_lockmode, scan_flags, par.m_scanpar, par.m_scanbatch) == 0, *this);
return 0;
}
@@ -1442,7 +1456,12 @@ int
Con::readIndexTuples(Par par)
{
assert(m_tx != 0 && m_indexscanop != 0);
- CHKCON(m_indexscanop->readTuples(par.m_lockmode, 0, par.m_scanpar, par.m_ordered, par.m_descending) == 0, *this);
+ int scan_flags = 0;
+ if (par.m_ordered)
+ scan_flags |= NdbScanOperation::SF_OrderBy;
+ if (par.m_descending)
+ scan_flags |= NdbScanOperation::SF_Descending;
+ CHKCON(m_indexscanop->readTuples(par.m_lockmode, scan_flags, par.m_scanpar, par.m_scanbatch) == 0, *this);
return 0;
}
@@ -2193,7 +2212,7 @@ struct Row {
void copy(const Row& row2);
void calc(Par par, unsigned i, unsigned mask = 0);
const Row& dbrow() const;
- int verify(Par par, const Row& row2) const;
+ int verify(Par par, const Row& row2, bool pkonly) const;
int insrow(Par par);
int updrow(Par par);
int updrow(Par par, const ITab& itab);
@@ -2275,15 +2294,18 @@ Row::dbrow() const
}
int
-Row::verify(Par par, const Row& row2) const
+Row::verify(Par par, const Row& row2, bool pkonly) const
{
const Tab& tab = m_tab;
const Row& row1 = *this;
assert(&row1.m_tab == &row2.m_tab && row1.m_exist && row2.m_exist);
for (unsigned k = 0; k < tab.m_cols; k++) {
- const Val& val1 = *row1.m_val[k];
- const Val& val2 = *row2.m_val[k];
- CHK(val1.verify(par, val2) == 0);
+ const Col& col = row1.m_val[k]->m_col;
+ if (! pkonly || col.m_pk) {
+ const Val& val1 = *row1.m_val[k];
+ const Val& val2 = *row2.m_val[k];
+ CHK(val1.verify(par, val2) == 0);
+ }
}
return 0;
}
@@ -2585,8 +2607,11 @@ struct Set {
int getval(Par par);
int getkey(Par par, unsigned* i);
int putval(unsigned i, bool force, unsigned n = ~0);
+ // sort rows in-place according to ordered index
+ void sort(Par par, const ITab& itab);
+ void sort(Par par, const ITab& itab, unsigned lo, unsigned hi);
// verify
- int verify(Par par, const Set& set2) const;
+ int verify(Par par, const Set& set2, bool pkonly) const;
int verifyorder(Par par, const ITab& itab, bool descending) const;
// protect structure
NdbMutex* m_mutex;
@@ -2890,6 +2915,7 @@ Set::getkey(Par par, unsigned* i)
assert(m_rec[k] != 0);
const char* aRef = m_rec[k]->aRef();
Uint32 key = *(const Uint32*)aRef;
+ LL5("getkey: " << key);
CHK(key < m_rows);
*i = key;
return 0;
@@ -2922,8 +2948,43 @@ Set::putval(unsigned i, bool force, unsigned n)
return 0;
}
+void
+Set::sort(Par par, const ITab& itab)
+{
+ if (m_rows != 0)
+ sort(par, itab, 0, m_rows - 1);
+}
+
+void
+Set::sort(Par par, const ITab& itab, unsigned lo, unsigned hi)
+{
+ assert(lo < m_rows && hi < m_rows && lo <= hi);
+ Row* const p = m_row[lo];
+ unsigned i = lo;
+ unsigned j = hi;
+ while (i < j) {
+ while (i < j && m_row[j]->cmp(par, *p, itab) >= 0)
+ j--;
+ if (i < j) {
+ m_row[i] = m_row[j];
+ i++;
+ }
+ while (i < j && m_row[i]->cmp(par, *p, itab) <= 0)
+ i++;
+ if (i < j) {
+ m_row[j] = m_row[i];
+ j--;
+ }
+ }
+ m_row[i] = p;
+ if (lo < i)
+ sort(par, itab, lo, i - 1);
+ if (hi > i)
+ sort(par, itab, i + 1, hi);
+}
+
int
-Set::verify(Par par, const Set& set2) const
+Set::verify(Par par, const Set& set2, bool pkonly) const
{
assert(&m_tab == &set2.m_tab && m_rows == set2.m_rows);
LL4("verify set1 count=" << count() << " vs set2 count=" << set2.count());
@@ -2932,7 +2993,7 @@ Set::verify(Par par, const Set& set2) const
if (exist(i) != set2.exist(i)) {
ok = false;
} else if (exist(i)) {
- if (dbrow(i).verify(par, set2.dbrow(i)) != 0)
+ if (dbrow(i).verify(par, set2.dbrow(i), pkonly) != 0)
ok = false;
}
if (! ok) {
@@ -3490,7 +3551,7 @@ pkread(Par par)
con.closeTransaction();
}
if (par.m_verify)
- CHK(set1.verify(par, set2) == 0);
+ CHK(set1.verify(par, set2, false) == 0);
return 0;
}
@@ -3657,7 +3718,7 @@ hashindexread(Par par, const ITab& itab)
con.closeTransaction();
}
if (par.m_verify)
- CHK(set1.verify(par, set2) == 0);
+ CHK(set1.verify(par, set2, false) == 0);
return 0;
}
@@ -3698,7 +3759,7 @@ scanreadtable(Par par)
}
con.closeTransaction();
if (par.m_verify)
- CHK(set1.verify(par, set2) == 0);
+ CHK(set1.verify(par, set2, false) == 0);
LL3("scanread " << tab.m_name << " done rows=" << n);
return 0;
}
@@ -3730,6 +3791,23 @@ scanreadtablefast(Par par, unsigned countcheck)
return 0;
}
+// try to get interesting bounds
+static void
+calcscanbounds(Par par, const ITab& itab, BSet& bset, const Set& set, Set& set1)
+{
+ while (true) {
+ bset.calc(par);
+ bset.filter(par, set, set1);
+ unsigned n = set1.count();
+ // prefer proper subset
+ if (0 < n && n < set.m_rows)
+ break;
+ if (urandom(5) == 0)
+ break;
+ set1.reset();
+ }
+}
+
static int
scanreadindex(Par par, const ITab& itab, BSet& bset, bool calc)
{
@@ -3738,21 +3816,11 @@ scanreadindex(Par par, const ITab& itab, BSet& bset, bool calc)
const Set& set = par.set();
Set set1(tab, set.m_rows);
if (calc) {
- while (true) {
- bset.calc(par);
- bset.filter(par, set, set1);
- unsigned n = set1.count();
- // prefer proper subset
- if (0 < n && n < set.m_rows)
- break;
- if (urandom(3) == 0)
- break;
- set1.reset();
- }
+ calcscanbounds(par, itab, bset, set, set1);
} else {
bset.filter(par, set, set1);
}
- LL3("scanread " << itab.m_name << " " << bset << " lockmode=" << par.m_lockmode << " expect=" << set1.count() << " verify=" << par.m_verify << " ordered=" << par.m_ordered << " descending=" << par.m_descending);
+ LL3("scanread " << itab.m_name << " " << bset << " lockmode=" << par.m_lockmode << " expect=" << set1.count() << " ordered=" << par.m_ordered << " descending=" << par.m_descending << " verify=" << par.m_verify);
Set set2(tab, set.m_rows);
CHK(con.startTransaction() == 0);
CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
@@ -3780,7 +3848,7 @@ scanreadindex(Par par, const ITab& itab, BSet& bset, bool calc)
}
con.closeTransaction();
if (par.m_verify) {
- CHK(set1.verify(par, set2) == 0);
+ CHK(set1.verify(par, set2, false) == 0);
if (par.m_ordered)
CHK(set2.verifyorder(par, itab, par.m_descending) == 0);
}
@@ -3825,17 +3893,7 @@ scanreadfilter(Par par, const ITab& itab, BSet& bset, bool calc)
const Set& set = par.set();
Set set1(tab, set.m_rows);
if (calc) {
- while (true) {
- bset.calc(par);
- bset.filter(par, set, set1);
- unsigned n = set1.count();
- // prefer proper subset
- if (0 < n && n < set.m_rows)
- break;
- if (urandom(3) == 0)
- break;
- set1.reset();
- }
+ calcscanbounds(par, itab, bset, set, set1);
} else {
bset.filter(par, set, set1);
}
@@ -3867,7 +3925,7 @@ scanreadfilter(Par par, const ITab& itab, BSet& bset, bool calc)
}
con.closeTransaction();
if (par.m_verify) {
- CHK(set1.verify(par, set2) == 0);
+ CHK(set1.verify(par, set2, false) == 0);
}
LL3("scanfilter " << itab.m_name << " done rows=" << n);
return 0;
@@ -3877,7 +3935,7 @@ static int
scanreadindex(Par par, const ITab& itab)
{
const Tab& tab = par.tab();
- for (unsigned i = 0; i < par.m_subsubloop; i++) {
+ for (unsigned i = 0; i < par.m_subloop; i++) {
if (itab.m_type == ITab::OrderedIndex) {
BSet bset(tab, itab, par.m_rows);
CHK(scanreadfilter(par, itab, bset, true) == 0);
@@ -4068,12 +4126,19 @@ out:
}
static int
-scanupdateindex(Par par, const ITab& itab, const BSet& bset)
+scanupdateindex(Par par, const ITab& itab, BSet& bset, bool calc)
{
Con& con = par.con();
const Tab& tab = par.tab();
Set& set = par.set();
- LL3("scan update " << itab.m_name);
+ // expected
+ Set set1(tab, set.m_rows);
+ if (calc) {
+ calcscanbounds(par, itab, bset, set, set1);
+ } else {
+ bset.filter(par, set, set1);
+ }
+ LL3("scan update " << itab.m_name << " " << bset << " expect=" << set1.count() << " ordered=" << par.m_ordered << " descending=" << par.m_descending << " verify=" << par.m_verify);
Set set2(tab, set.m_rows);
par.m_lockmode = NdbOperation::LM_Exclusive;
CHK(con.startTransaction() == 0);
@@ -4117,7 +4182,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
Par par2 = par;
par2.m_con = &con2;
set.dbsave(i);
- set.calc(par, i);
+ set.calc(par, i, ! par.m_noindexkeyupdate ? 0 : itab.m_colmask);
CHKTRY(set.setrow(par2, i) == 0, set.unlock());
LL4("scan update " << itab.m_name << ": " << row);
lst.push(i);
@@ -4131,6 +4196,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
goto out;
}
con2.closeTransaction();
+ LL4("scanupdateindex: committed batch [at 1]");
set.lock();
set.notpending(lst);
set.dbdiscard(lst);
@@ -4148,6 +4214,7 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
goto out;
}
con2.closeTransaction();
+ LL4("scanupdateindex: committed batch [at 2]");
set.lock();
set.notpending(lst);
set.dbdiscard(lst);
@@ -4160,6 +4227,11 @@ scanupdateindex(Par par, const ITab& itab, const BSet& bset)
}
out:
con2.closeTransaction();
+ if (par.m_verify) {
+ CHK(set1.verify(par, set2, true) == 0);
+ if (par.m_ordered)
+ CHK(set2.verifyorder(par, itab, par.m_descending) == 0);
+ }
LL3("scan update " << itab.m_name << " rows updated=" << count);
con.closeTransaction();
return 0;
@@ -4169,11 +4241,10 @@ static int
scanupdateindex(Par par, const ITab& itab)
{
const Tab& tab = par.tab();
- for (unsigned i = 0; i < par.m_subsubloop; i++) {
+ for (unsigned i = 0; i < par.m_subloop; i++) {
if (itab.m_type == ITab::OrderedIndex) {
BSet bset(tab, itab, par.m_rows);
- bset.calc(par);
- CHK(scanupdateindex(par, itab, bset) == 0);
+ CHK(scanupdateindex(par, itab, bset, true) == 0);
} else {
CHK(hashindexupdate(par, itab) == 0);
}
@@ -4205,22 +4276,6 @@ scanupdateall(Par par)
// medium level routines
static int
-readverify(Par par)
-{
- if (par.m_noverify)
- return 0;
- par.m_verify = true;
- if (par.m_abortpct != 0) {
- LL2("skip verify in this version"); // implement in 5.0 version
- par.m_verify = false;
- }
- par.m_lockmode = NdbOperation::LM_CommittedRead;
- CHK(pkread(par) == 0);
- CHK(scanreadall(par) == 0);
- return 0;
-}
-
-static int
readverifyfull(Par par)
{
if (par.m_noverify)
@@ -4237,8 +4292,7 @@ readverifyfull(Par par)
CHK(scanreadtable(par) == 0);
// once more via tup scan
par.m_tupscan = true;
- if (NDB_VERSION < MAKE_VERSION(5, 1, 0)) //TODO
- CHK(scanreadtable(par) == 0);
+ CHK(scanreadtable(par) == 0);
}
// each thread scans different indexes
for (unsigned i = 0; i < tab.m_itabs; i++) {
@@ -4278,7 +4332,7 @@ pkops(Par par)
{
const Tab& tab = par.tab();
par.m_randomkey = true;
- for (unsigned i = 0; i < par.m_subsubloop; i++) {
+ for (unsigned i = 0; i < par.m_subloop; i++) {
unsigned j = 0;
while (j < tab.m_itabs) {
if (tab.m_itab[j] != 0) {
@@ -4378,6 +4432,33 @@ mixedoperations(Par par)
}
static int
+parallelorderedupdate(Par par)
+{
+ const Tab& tab = par.tab();
+ unsigned k = 0;
+ for (unsigned i = 0; i < tab.m_itabs; i++) {
+ if (tab.m_itab[i] == 0)
+ continue;
+ const ITab& itab = *tab.m_itab[i];
+ if (itab.m_type != ITab::OrderedIndex)
+ continue;
+ // cannot sync threads yet except via subloop
+ if (k++ == par.m_slno % tab.m_orderedindexes) {
+ LL3("parallelorderedupdate: " << itab.m_name);
+ par.m_noindexkeyupdate = true;
+ par.m_ordered = true;
+ par.m_descending = (par.m_slno != 0);
+ par.m_verify = true;
+ BSet bset(tab, itab, par.m_rows); // empty bounds
+ // prefer empty bounds
+ unsigned sel = urandom(10);
+ CHK(scanupdateindex(par, itab, bset, sel < 2) == 0);
+ }
+ }
+ return 0;
+}
+
+static int
pkupdateindexbuild(Par par)
{
if (par.m_no == 0) {
@@ -4579,7 +4660,7 @@ getthrno()
static int
runstep(Par par, const char* fname, TFunc func, unsigned mode)
{
- LL2(fname);
+ LL2("step: " << fname);
const int threads = (mode & ST ? 1 : par.m_threads);
int n;
for (n = 0; n < threads; n++) {
@@ -4605,7 +4686,12 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode)
return 0;
}
-#define RUNSTEP(par, func, mode) CHK(runstep(par, #func, func, mode) == 0)
+#define RUNSTEP(par, func, mode) \
+ CHK(runstep(par, #func, func, mode) == 0)
+
+#define SUBLOOP(par) \
+ "subloop: " << par.m_lno << "/" << par.m_currcase << "/" << \
+ par.m_tab->m_name << "/" << par.m_slno
static int
tbuild(Par par)
@@ -4614,20 +4700,30 @@ tbuild(Par par)
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
- if (par.m_slno % 2 == 0) {
+ LL1(SUBLOOP(par));
+ if (par.m_slno % 3 == 0) {
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, pkupdate, MT);
+ } else if (par.m_slno % 3 == 1) {
+ RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ RUNSTEP(par, pkupdate, MT);
} else {
RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, pkupdate, MT);
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
}
- RUNSTEP(par, pkupdate, MT);
RUNSTEP(par, readverifyfull, MT);
- RUNSTEP(par, pkdelete, MT);
- RUNSTEP(par, readverifyfull, MT);
- RUNSTEP(par, dropindex, ST);
+ // leave last one
+ if (par.m_slno + 1 < par.m_subloop) {
+ RUNSTEP(par, pkdelete, MT);
+ RUNSTEP(par, readverifyfull, MT);
+ RUNSTEP(par, dropindex, ST);
+ }
}
return 0;
}
@@ -4643,7 +4739,7 @@ tindexscan(Par par)
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, readverifyfull, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
- LL4("subloop " << par.m_slno);
+ LL1(SUBLOOP(par));
RUNSTEP(par, readverifyindex, MT);
}
return 0;
@@ -4659,6 +4755,7 @@ tpkops(Par par)
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, pkops, MT);
LL2("rows=" << par.set().count());
RUNSTEP(par, readverifyfull, MT);
@@ -4675,13 +4772,14 @@ tpkopsread(Par par)
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, ST);
+ RUNSTEP(par, readverifyfull, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, pkupdatescanread, MT);
- RUNSTEP(par, readverify, ST);
+ RUNSTEP(par, readverifyfull, MT);
}
RUNSTEP(par, pkdelete, MT);
- RUNSTEP(par, readverify, ST);
+ RUNSTEP(par, readverifyfull, MT);
return 0;
}
@@ -4694,10 +4792,11 @@ tmixedops(Par par)
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, ST);
+ RUNSTEP(par, readverifyfull, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, mixedoperations, MT);
- RUNSTEP(par, readverify, ST);
+ RUNSTEP(par, readverifyfull, MT);
}
return 0;
}
@@ -4710,9 +4809,10 @@ tbusybuild(Par par)
RUNSTEP(par, invalidatetable, MT);
RUNSTEP(par, pkinsert, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, pkupdateindexbuild, MT);
RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, ST);
+ RUNSTEP(par, readverifyfull, MT);
RUNSTEP(par, dropindex, ST);
}
return 0;
@@ -4728,10 +4828,29 @@ trollback(Par par)
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
RUNSTEP(par, invalidateindex, MT);
- RUNSTEP(par, readverify, ST);
+ RUNSTEP(par, readverifyfull, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, mixedoperations, MT);
- RUNSTEP(par, readverify, ST);
+ RUNSTEP(par, readverifyfull, MT);
+ }
+ return 0;
+}
+
+static int
+tparupdate(Par par)
+{
+ RUNSTEP(par, droptable, ST);
+ RUNSTEP(par, createtable, ST);
+ RUNSTEP(par, invalidatetable, MT);
+ RUNSTEP(par, pkinsert, MT);
+ RUNSTEP(par, createindex, ST);
+ RUNSTEP(par, invalidateindex, MT);
+ RUNSTEP(par, readverifyfull, MT);
+ for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
+ RUNSTEP(par, parallelorderedupdate, MT);
+ RUNSTEP(par, readverifyfull, MT);
}
return 0;
}
@@ -4744,6 +4863,7 @@ ttimebuild(Par par)
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, pkinsert, MT);
t1.on();
RUNSTEP(par, createindex, ST);
@@ -4763,6 +4883,7 @@ ttimemaint(Par par)
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, pkinsert, MT);
t1.on();
RUNSTEP(par, pkupdate, MT);
@@ -4792,6 +4913,7 @@ ttimescan(Par par)
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
par.m_tmr = &t1;
@@ -4818,6 +4940,7 @@ ttimepkread(Par par)
RUNSTEP(par, createtable, ST);
RUNSTEP(par, invalidatetable, MT);
for (par.m_slno = 0; par.m_slno < par.m_subloop; par.m_slno++) {
+ LL1(SUBLOOP(par));
RUNSTEP(par, pkinsert, MT);
RUNSTEP(par, createindex, ST);
par.m_tmr = &t1;
@@ -4859,6 +4982,7 @@ tcaselist[] = {
TCase("e", tmixedops, "pk operations and scan operations"),
TCase("f", tbusybuild, "pk operations and index build"),
TCase("g", trollback, "operations with random rollbacks"),
+ TCase("h", tparupdate, "parallel ordered update (bug20446)"),
TCase("t", ttimebuild, "time index build"),
TCase("u", ttimemaint, "time index maintenance"),
TCase("v", ttimescan, "time full scan table vs index on pk"),
@@ -4916,17 +5040,16 @@ printtables()
static int
runtest(Par par)
{
- LL1("start");
if (par.m_seed == -1) {
// good enough for daily run
- unsigned short seed = (getpid() ^ time(0));
- LL1("random seed: " << seed);
+ unsigned short seed = (unsigned short)getpid();
+ LL0("random seed: " << seed);
srandom((unsigned)seed);
} else if (par.m_seed != 0) {
- LL1("random seed: " << par.m_seed);
+ LL0("random seed: " << par.m_seed);
srandom(par.m_seed);
} else {
- LL1("random seed: loop number");
+ LL0("random seed: loop number");
}
// cs
assert(par.m_csname != 0);
@@ -4951,22 +5074,25 @@ runtest(Par par)
assert(thr.m_thread != 0);
}
for (par.m_lno = 0; par.m_loop == 0 || par.m_lno < par.m_loop; par.m_lno++) {
- LL1("loop " << par.m_lno);
- if (par.m_seed == 0)
+ LL1("loop: " << par.m_lno);
+ if (par.m_seed == 0) {
+ LL1("random seed: " << par.m_lno);
srandom(par.m_lno);
+ }
for (unsigned i = 0; i < tcasecount; i++) {
const TCase& tcase = tcaselist[i];
if (par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0)
continue;
+ sprintf(par.m_currcase, "%c", tcase.m_name[0]);
makebuiltintables(par);
- LL1("case " << tcase.m_name << " - " << tcase.m_desc);
+ LL1("case: " << par.m_lno << "/" << tcase.m_name << " - " << tcase.m_desc);
for (unsigned j = 0; j < tabcount; j++) {
if (tablist[j] == 0)
continue;
const Tab& tab = *tablist[j];
par.m_tab = &tab;
par.m_set = new Set(tab, par.m_totrows);
- LL1("table " << tab.m_name);
+ LL1("table: " << par.m_lno << "/" << tcase.m_name << "/" << tab.m_name);
CHK(tcase.m_func(par) == 0);
delete par.m_set;
par.m_set = 0;
@@ -4985,15 +5111,21 @@ runtest(Par par)
delete [] g_thrlist;
g_thrlist = 0;
con.disconnect();
- LL1("done");
return 0;
}
-NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
+static const char* g_progname = "testOIBasic";
+
+int
+main(int argc, char** argv)
{
ndb_init();
- if (ndbout_mutex == NULL)
- ndbout_mutex = NdbMutex_Create();
+ unsigned i;
+ ndbout << g_progname;
+ for (i = 1; i < argc; i++)
+ ndbout << " " << argv[i];
+ ndbout << endl;
+ ndbout_mutex = NdbMutex_Create();
while (++argv, --argc > 0) {
const char* arg = argv[0];
if (*arg != '-') {
@@ -5103,6 +5235,12 @@ NDB_COMMAND(testOIBasic, "testOIBasic", "testOIBasic", "testOIBasic", 65535)
continue;
}
}
+ if (strcmp(arg, "-scanbatch") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_scanbatch = atoi(argv[0]);
+ continue;
+ }
+ }
if (strcmp(arg, "-scanpar") == 0) {
if (++argv, --argc > 0) {
g_opt.m_scanpar = atoi(argv[0]);
diff --git a/ndb/test/ndbapi/testTimeout.cpp b/ndb/test/ndbapi/testTimeout.cpp
index 36fb34a50e2..e719cdf03e9 100644
--- a/ndb/test/ndbapi/testTimeout.cpp
+++ b/ndb/test/ndbapi/testTimeout.cpp
@@ -388,6 +388,45 @@ int runBuddyTransNoTimeout(NDBT_Context* ctx, NDBT_Step* step){
return result;
}
+int runBuddyTransTimeout(NDBT_Context* ctx, NDBT_Step* step){
+ int result = NDBT_OK;
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int stepNo = step->getStepNo();
+ ndbout << "TransactionInactiveTimeout="<< TIMEOUT <<endl;
+
+ HugoOperations hugoOps(*ctx->getTab());
+ Ndb* pNdb = GETNDB(step);
+
+ for (int l = 1; l < loops && result == NDBT_OK; l++){
+
+ NdbTransaction* pTrans = 0;
+ do{
+ pTrans = pNdb->startTransaction();
+ NdbScanOperation* pOp = pTrans->getNdbScanOperation(ctx->getTab());
+ CHECK(pOp->readTuples(NdbOperation::LM_Read, 0, 0, 1) == 0);
+ CHECK(pTrans->execute(NoCommit) == 0);
+
+ int sleep = 2 * TIMEOUT;
+ ndbout << "Sleeping for " << sleep << " milliseconds" << endl;
+ NdbSleep_MilliSleep(sleep);
+
+ int res = 0;
+ while((res = pOp->nextResult()) == 0);
+ ndbout_c("res: %d", res);
+ CHECK(res == -1);
+
+ } while(false);
+
+ if (pTrans)
+ {
+ pTrans->close();
+ }
+ }
+
+ return result;
+}
+
int
runError4012(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
@@ -495,6 +534,15 @@ TESTCASE("BuddyTransNoTimeout5",
FINALIZER(resetTransactionTimeout);
FINALIZER(runClearTable);
}
+TESTCASE("BuddyTransTimeout1",
+ "Start a scan and check that it gets aborted"){
+ INITIALIZER(runLoadTable);
+ INITIALIZER(setTransactionTimeout);
+ STEPS(runBuddyTransTimeout, 1);
+ FINALIZER(resetTransactionTimeout);
+ FINALIZER(runClearTable);
+}
+#if 0
TESTCASE("Error4012", ""){
TC_PROPERTY("TransactionDeadlockTimeout", 120000);
INITIALIZER(runLoadTable);
@@ -503,7 +551,7 @@ TESTCASE("Error4012", ""){
STEPS(runError4012, 2);
FINALIZER(runClearTable);
}
-
+#endif
NDBT_TESTSUITE_END(testTimeout);
int main(int argc, const char** argv){
diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt
index a2edc568426..a544355abd6 100644
--- a/ndb/test/run-test/daily-basic-tests.txt
+++ b/ndb/test/run-test/daily-basic-tests.txt
@@ -607,7 +607,15 @@ args:
max-time: 5000
cmd: testOIBasic
-args:
+args: -case abcdefz
+
+max-time: 2000
+cmd: testOIBasic
+args: -case gz
+
+max-time: 2000
+cmd: testOIBasic
+args: -case hz
max-time: 2500
cmd: testBitfield
diff --git a/ndb/tools/delete_all.cpp b/ndb/tools/delete_all.cpp
index 6aea9f87aaa..a3d9ff4ccee 100644
--- a/ndb/tools/delete_all.cpp
+++ b/ndb/tools/delete_all.cpp
@@ -27,6 +27,8 @@ static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab,
NDB_STD_OPTS_VARS;
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
static const char* _dbname = "TEST_DB";
static my_bool _transactional = false;
static struct my_option my_long_options[] =
@@ -46,13 +48,14 @@ static void usage()
"tabname\n"\
"This program will delete all records in the specified table using scan delete.\n";
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
#ifndef DBUG_OFF
diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp
index 74cd740f2ae..934394e4d31 100644
--- a/ndb/tools/desc.cpp
+++ b/ndb/tools/desc.cpp
@@ -24,6 +24,9 @@ NDB_STD_OPTS_VARS;
static const char* _dbname = "TEST_DB";
static int _unqualified = 0;
static int _partinfo = 0;
+
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
@@ -45,6 +48,8 @@ static void usage()
"This program list all properties of table(s) in NDB Cluster.\n"\
" ex: desc T1 T2 T4\n";
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
@@ -53,7 +58,6 @@ static void print_part_info(Ndb* pNdb, NDBT_Table* pTab);
int main(int argc, char** argv){
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
#ifndef DBUG_OFF
diff --git a/ndb/tools/drop_index.cpp b/ndb/tools/drop_index.cpp
index 24116f22784..c10211a9108 100644
--- a/ndb/tools/drop_index.cpp
+++ b/ndb/tools/drop_index.cpp
@@ -24,6 +24,9 @@
NDB_STD_OPTS_VARS;
static const char* _dbname = "TEST_DB";
+
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
@@ -38,18 +41,16 @@ static void usage()
"[<table> <index>]+\n"\
"This program will drop index(es) in Ndb\n";
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
-#ifndef DBUG_OFF
- "d:t:O,/tmp/ndb_drop_index.trace";
-#endif
if ((ho_error=handle_options(&argc, &argv, my_long_options,
ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
diff --git a/ndb/tools/drop_tab.cpp b/ndb/tools/drop_tab.cpp
index 991e1505486..61df4ee9b34 100644
--- a/ndb/tools/drop_tab.cpp
+++ b/ndb/tools/drop_tab.cpp
@@ -24,6 +24,9 @@
NDB_STD_OPTS_VARS;
static const char* _dbname = "TEST_DB";
+
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
@@ -37,19 +40,17 @@ static void usage()
char desc[] =
"tabname\n"\
"This program will drop one table in Ndb\n";
- ndb_std_print_version();
+ ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
-#ifndef DBUG_OFF
- "d:t:O,/tmp/ndb_drop_table.trace";
-#endif
if ((ho_error=handle_options(&argc, &argv, my_long_options,
ndb_std_get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
diff --git a/ndb/tools/listTables.cpp b/ndb/tools/listTables.cpp
index fa078f7d351..8cc4e65586a 100644
--- a/ndb/tools/listTables.cpp
+++ b/ndb/tools/listTables.cpp
@@ -32,6 +32,8 @@ static Ndb* ndb = 0;
static const NdbDictionary::Dictionary * dic = 0;
static int _unqualified = 0;
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
static void
fatal(char const* fmt, ...)
{
@@ -196,6 +198,8 @@ static void usage()
"To show all indexes for a table write table name as final argument\n"\
" ex: ndb_show_tables T1\n";
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
@@ -203,7 +207,6 @@ static void usage()
int main(int argc, char** argv){
NDB_INIT(argv[0]);
const char* _tabname;
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
#ifndef DBUG_OFF
diff --git a/ndb/tools/ndb_config.cpp b/ndb/tools/ndb_config.cpp
index 135bec7ef72..049e4599447 100644
--- a/ndb/tools/ndb_config.cpp
+++ b/ndb/tools/ndb_config.cpp
@@ -19,6 +19,8 @@
*/
#include <ndb_global.h>
+#include <ndb_opts.h>
+
#include <my_sys.h>
#include <my_getopt.h>
#include <mysql_version.h>
@@ -29,6 +31,7 @@
#include <mgmapi.h>
#include <mgmapi_configuration.hpp>
#include <ConfigInfo.hpp>
+#include <NdbAutoPtr.hpp>
static int g_verbose = 0;
static int try_reconnect = 3;
@@ -45,34 +48,17 @@ static const char * g_row_delimiter=" ";
static const char * g_config_file = 0;
static int g_mycnf = 0;
-int g_print_full_config, opt_ndb_shm;
-my_bool opt_core;
+const char *load_default_groups[]= { "mysql_cluster",0 };
-typedef ndb_mgm_configuration_iterator Iter;
+NDB_STD_OPTS_VARS;
-static void ndb_std_print_version()
-{
- printf("MySQL distrib %s, for %s (%s)\n",
- MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
-}
+int g_print_full_config;
+
+typedef ndb_mgm_configuration_iterator Iter;
static struct my_option my_long_options[] =
{
- { "usage", '?', "Display this help and exit.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
- { "help", '?', "Display this help and exit.",
- 0, 0, 0, GET_NO_ARG, NO_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 },
- { "ndb-connectstring", 256,
- "Set connect string for connecting to ndb_mgmd. "
- "Syntax: \"[nodeid=<id>;][host=]<hostname>[:<port>]\". "
- "Overides specifying entries in NDB_CONNECTSTRING and Ndb.cfg",
- (gptr*) &g_connectstring, (gptr*) &g_connectstring,
- 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
- { "ndb-shm", 256, "Print nodes",
- (gptr*) &opt_ndb_shm, (gptr*) &opt_ndb_shm,
- 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ NDB_STD_OPTS("ndb_config"),
{ "nodes", 256, "Print nodes",
(gptr*) &g_nodes, (gptr*) &g_nodes,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -114,24 +100,11 @@ static void usage()
char desc[] =
"This program will retreive config options for a ndb cluster\n";
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
-static my_bool
-ndb_std_get_one_option(int optid,
- const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- switch (optid) {
- case 'V':
- ndb_std_print_version();
- exit(0);
- case '?':
- usage();
- exit(0);
- }
- return 0;
-}
/**
* Match/Apply framework
@@ -141,6 +114,7 @@ struct Match
int m_key;
BaseString m_value;
virtual int eval(const Iter&);
+ virtual ~Match() {}
};
struct HostMatch : public Match
@@ -154,6 +128,7 @@ struct Apply
Apply(int val) { m_key = val;}
int m_key;
virtual int apply(const Iter&);
+ virtual ~Apply() {}
};
struct NodeTypeApply : public Apply
@@ -176,7 +151,6 @@ static ndb_mgm_configuration* load_configuration();
int
main(int argc, char** argv){
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
if ((ho_error=handle_options(&argc, &argv, my_long_options,
@@ -408,28 +382,36 @@ HostMatch::eval(const Iter& iter)
if(iter.get(m_key, &valc) == 0)
{
- struct hostent *h1, *h2;
+ struct hostent *h1, *h2, copy1;
+ char *addr1;
h1 = gethostbyname(m_value.c_str());
if (h1 == NULL) {
return 0;
}
+ // gethostbyname returns a pointer to a static structure
+ // so we need to copy the results before doing the next call
+ memcpy(&copy1, h1, sizeof(struct hostent));
+ addr1 = (char *)malloc(copy1.h_length);
+ NdbAutoPtr<char> tmp_aptr(addr1);
+ memcpy(addr1, h1->h_addr, copy1.h_length);
+
h2 = gethostbyname(valc);
if (h2 == NULL) {
return 0;
}
- if (h1->h_addrtype != h2->h_addrtype) {
+ if (copy1.h_addrtype != h2->h_addrtype) {
return 0;
}
- if (h1->h_length != h2->h_length)
+ if (copy1.h_length != h2->h_length)
{
return 0;
}
- return 0 == memcmp(h1->h_addr, h2->h_addr, h1->h_length);
+ return 0 == memcmp(addr1, h2->h_addr, copy1.h_length);
}
return 0;
diff --git a/ndb/tools/ndb_size.pl b/ndb/tools/ndb_size.pl
index c285a7590fd..3d1ea3f4231 100644
--- a/ndb/tools/ndb_size.pl
+++ b/ndb/tools/ndb_size.pl
@@ -57,7 +57,7 @@ if(@ARGV < 3 || $ARGV[0] eq '--usage' || $ARGV[0] eq '--help')
$template->param(dsn => $dsn);
}
-my @releases = ({rel=>'4.1'},{rel=>'5.0'},{rel=>'5.1'});
+my @releases = ({rel=>'4.1'},{rel=>'5.0'},{rel=>'5.1'}); #,{rel=>'5.1-dd'});
$template->param(releases => \@releases);
my $tables = $dbh->selectall_arrayref("show tables");
@@ -81,25 +81,29 @@ sub align {
return @aligned;
}
-foreach(@{$tables})
-{
- my $table= @{$_}[0];
+sub do_table {
+ my $table= shift;
+ my $info= shift;
+ my %indexes= %{$_[0]};
+ my @count= @{$_[1]};
+
my @columns;
- my $info= $dbh->selectall_hashref('describe `'.$table.'`',"Field");
- my @count = $dbh->selectrow_array('select count(*) from `'.$table.'`');
my %columnsize; # used for index calculations
-
# We now work out the DataMemory usage
- # sizes for 4.1, 5.0, 5.1
- my @totalsize= (0,0,0);
+ # sizes for 4.1, 5.0, 5.1 and 5.1-dd
+ my @totalsize= (0,0,0,0);
+ @totalsize= @totalsize[0..$#releases]; # limit to releases we're outputting
+ my $nrvarsize= 0;
foreach(keys %$info)
{
- my @realsize = (0,0,0);
+ my @realsize = (0,0,0,0);
+ my @varsize = (0,0,0,0);
my $type;
my $size;
my $name= $_;
+ my $is_varsize= 0;
if($$info{$_}{Type} =~ /^(.*?)\((\d+)\)/)
{
@@ -112,54 +116,86 @@ foreach(@{$tables})
}
if($type =~ /tinyint/)
- {@realsize=(1,1,1)}
+ {@realsize=(1,1,1,1)}
elsif($type =~ /smallint/)
- {@realsize=(2,2,2)}
+ {@realsize=(2,2,2,2)}
elsif($type =~ /mediumint/)
- {@realsize=(3,3,3)}
+ {@realsize=(3,3,3,3)}
elsif($type =~ /bigint/)
- {@realsize=(8,8,8)}
+ {@realsize=(8,8,8,8)}
elsif($type =~ /int/)
- {@realsize=(4,4,4)}
+ {@realsize=(4,4,4,4)}
elsif($type =~ /float/)
{
if($size<=24)
- {@realsize=(4,4,4)}
+ {@realsize=(4,4,4,4)}
else
- {@realsize=(8,8,8)}
+ {@realsize=(8,8,8,8)}
}
elsif($type =~ /double/ || $type =~ /real/)
- {@realsize=(8,8,8)}
+ {@realsize=(8,8,8,8)}
elsif($type =~ /bit/)
{
my $a=($size+7)/8;
- @realsize = ($a,$a,$a);
+ @realsize = ($a,$a,$a,$a);
}
elsif($type =~ /datetime/)
- {@realsize=(8,8,8)}
+ {@realsize=(8,8,8,8)}
elsif($type =~ /timestamp/)
- {@realsize=(4,4,4)}
+ {@realsize=(4,4,4,4)}
elsif($type =~ /date/ || $type =~ /time/)
- {@realsize=(3,3,3)}
+ {@realsize=(3,3,3,3)}
elsif($type =~ /year/)
- {@realsize=(1,1,1)}
+ {@realsize=(1,1,1,1)}
elsif($type =~ /varchar/ || $type =~ /varbinary/)
{
- my $fixed= 1+$size;
+ my $fixed=$size+ceil($size/256);
my @dynamic=$dbh->selectrow_array("select avg(length(`"
.$name
."`)) from `".$table.'`');
$dynamic[0]=0 if !$dynamic[0];
- @realsize= ($fixed,$fixed,ceil($dynamic[0]));
+ $dynamic[0]+=ceil($dynamic[0]/256); # size bit
+ $nrvarsize++;
+ $is_varsize= 1;
+ $varsize[3]= ceil($dynamic[0]);
+ @realsize= ($fixed,$fixed,ceil($dynamic[0]),$fixed);
}
elsif($type =~ /binary/ || $type =~ /char/)
- {@realsize=($size,$size,$size)}
+ {@realsize=($size,$size,$size,$size)}
elsif($type =~ /text/ || $type =~ /blob/)
{
- @realsize=(256,256,1);
- $NoOfTables[$_]{val} += 1 foreach 0..$#releases; # blob uses table
- } # FIXME check if 5.1 is correct
+ @realsize=(8+256,8+256,8+256,8+256);
+
+ my $blobhunk= 2000;
+ $blobhunk= 8000 if $type=~ /longblob/;
+ $blobhunk= 4000 if $type=~ /mediumblob/;
+
+ my @blobsize=$dbh->selectrow_array("select SUM(CEILING(".
+ "length(`$name`)/$blobhunk))".
+ "from `".$table."`");
+ $blobsize[0]=0 if !defined($blobsize[0]);
+ #$NoOfTables[$_]{val} += 1 foreach 0..$#releases; # blob uses table
+ do_table($table."\$BLOB_$name",
+ {'PK'=>{Type=>'int'},
+ 'DIST'=>{Type=>'int'},
+ 'PART'=>{Type=>'int'},
+ 'DATA'=>{Type=>"binary($blobhunk)"}
+ },
+ {'PRIMARY' => {
+ 'unique' => 1,
+ 'comment' => '',
+ 'columns' => [
+ 'PK',
+ 'DIST',
+ 'PART',
+ ],
+ 'type' => 'HASH'
+ }
+ },
+ \@blobsize);
+ }
+ @realsize= @realsize[0..$#releases];
@realsize= align(4,@realsize);
$totalsize[$_]+=$realsize[$_] foreach 0..$#totalsize;
@@ -170,6 +206,7 @@ foreach(@{$tables})
push @columns, {
name=>$name,
type=>$type,
+ is_varsize=>$is_varsize,
size=>$size,
key=>$$info{$_}{Key},
datamemory=>\@realout,
@@ -183,24 +220,10 @@ foreach(@{$tables})
# Firstly, we assemble some information about the indexes.
# We use SHOW INDEX instead of using INFORMATION_SCHEMA so
# we can still connect to pre-5.0 mysqlds.
- my %indexes;
- {
- my $sth= $dbh->prepare("show index from `".$table.'`');
- $sth->execute;
- while(my $i = $sth->fetchrow_hashref)
- {
- $indexes{${%$i}{Key_name}}= {
- type=>${%$i}{Index_type},
- unique=>!${%$i}{Non_unique},
- comment=>${%$i}{Comment},
- } if !defined($indexes{${%$i}{Key_name}});
-
- $indexes{${%$i}{Key_name}}{columns}[${%$i}{Seq_in_index}-1]=
- ${%$i}{Column_name};
- }
- }
if(!defined($indexes{PRIMARY})) {
+ my @usage= ({val=>8},{val=>8},{val=>8},{val=>8});
+ @usage= @usage[0..$#releases];
$indexes{PRIMARY}= {
type=>'BTREE',
unique=>1,
@@ -212,20 +235,22 @@ foreach(@{$tables})
type=>'bigint',
size=>8,
key=>'PRI',
- datamemory=>[{val=>8},{val=>8},{val=>8}],
+ datamemory=>\@usage,
};
$columnsize{'HIDDEN_NDB_PKEY'}= [8,8,8];
}
- my @IndexDataMemory= ({val=>0},{val=>0},{val=>0});
- my @RowIndexMemory= ({val=>0},{val=>0},{val=>0});
+ my @IndexDataMemory= ({val=>0},{val=>0},{val=>0},{val=>0});
+ my @RowIndexMemory= ({val=>0},{val=>0},{val=>0},{val=>0});
+ @IndexDataMemory= @IndexDataMemory[0..$#releases];
+ @RowIndexMemory= @RowIndexMemory[0..$#releases];
my @indexes;
foreach my $index (keys %indexes) {
my $im41= 25;
$im41+=$columnsize{$_}[0] foreach @{$indexes{$index}{columns}};
- my @im = ({val=>$im41},{val=>25},{val=>25});
- my @dm = ({val=>10},{val=>10},{val=>10});
+ my @im = ({val=>$im41},{val=>25},{val=>25}); #,{val=>25});
+ my @dm = ({val=>10},{val=>10},{val=>10}); #,{val=>10});
push @indexes, {
name=>$index,
type=>$indexes{$index}{type},
@@ -233,13 +258,22 @@ foreach(@{$tables})
indexmemory=>\@im,
datamemory=>\@dm,
};
- $IndexDataMemory[$_]{val}+=$dm[$_]{val} foreach 0..2;
- $RowIndexMemory[$_]{val}+=$im[$_]{val} foreach 0..2;
+ $IndexDataMemory[$_]{val}+=$dm[$_]{val} foreach 0..$#releases;
+ $RowIndexMemory[$_]{val}+=$im[$_]{val} foreach 0..$#releases;
}
# total size + 16 bytes overhead
my @TotalDataMemory;
- $TotalDataMemory[$_]{val}=$IndexDataMemory[$_]{val}+$totalsize[$_]+16 foreach 0..2;
+ my @RowOverhead = ({val=>16},{val=>16},{val=>16}); #,{val=>24});
+ # 5.1 has ptr to varsize page, and per-varsize overhead
+ my @nrvarsize_mem= ({val=>0},{val=>0},
+ {val=>8}); #,{val=>0});
+ {
+ my @a= align(4,$nrvarsize*2);
+ $nrvarsize_mem[2]{val}+=$a[0]+$nrvarsize*4;
+ }
+
+ $TotalDataMemory[$_]{val}=$IndexDataMemory[$_]{val}+$totalsize[$_]+$RowOverhead[$_]{val}+$nrvarsize_mem[$_]{val} foreach 0..$#releases;
my @RowDataMemory;
push @RowDataMemory,{val=>$_} foreach @totalsize;
@@ -260,12 +294,18 @@ foreach(@{$tables})
my @counts;
$counts[$_]{val}= $count foreach 0..$#releases;
+ my @nrvarsize_rel= ({val=>0},{val=>0},
+ {val=>$nrvarsize}); #,{val=>0});
+
push @table_size, {
table=>$table,
indexes=>\@indexes,
columns=>\@columns,
count=>\@counts,
+ RowOverhead=>\@RowOverhead,
RowDataMemory=>\@RowDataMemory,
+ nrvarsize=>\@nrvarsize_rel,
+ nrvarsize_mem=>\@nrvarsize_mem,
releases=>\@releases,
IndexDataMemory=>\@IndexDataMemory,
TotalDataMemory=>\@TotalDataMemory,
@@ -283,6 +323,31 @@ foreach(@{$tables})
$NoOfIndexes[$_]{val} += @indexes foreach 0..$#releases;
}
+foreach(@{$tables})
+{
+ my $table= @{$_}[0];
+ my $info= $dbh->selectall_hashref('describe `'.$table.'`',"Field");
+ my @count = $dbh->selectrow_array('select count(*) from `'.$table.'`');
+
+ my %indexes;
+ {
+ my $sth= $dbh->prepare("show index from `".$table.'`');
+ $sth->execute;
+ while(my $i = $sth->fetchrow_hashref)
+ {
+ $indexes{${%$i}{Key_name}}= {
+ type=>${%$i}{Index_type},
+ unique=>!${%$i}{Non_unique},
+ comment=>${%$i}{Comment},
+ } if !defined($indexes{${%$i}{Key_name}});
+
+ $indexes{${%$i}{Key_name}}{columns}[${%$i}{Seq_in_index}-1]=
+ ${%$i}{Column_name};
+ }
+ }
+ do_table($table, $info, \%indexes, \@count);
+}
+
my @NoOfTriggers;
# for unique hash indexes
$NoOfTriggers[$_]{val} += $NoOfIndexes[$_]{val}*3 foreach 0..$#releases;
diff --git a/ndb/tools/ndb_size.tmpl b/ndb/tools/ndb_size.tmpl
index dc02b5a5970..1e19ea132ba 100644
--- a/ndb/tools/ndb_size.tmpl
+++ b/ndb/tools/ndb_size.tmpl
@@ -15,6 +15,8 @@ td,th { border: 1px solid black }
<p>This information should be valid for MySQL 4.1 and 5.0. Since 5.1 is not a final release yet, the numbers should be used as a guide only.</p>
+<p>5.1-dd is for tables stored on disk. The ndb_size.pl estimates are <b>experimental</b> and should not be trusted. Notably we don't take into account indexed columns being in DataMemory versus non-indexed on disk.</p>
+
<h2>Parameter Settings</h2>
<p><b>NOTE</b> the configuration parameters below do not take into account system tables and other requirements.</p>
<table>
@@ -69,6 +71,7 @@ td,th { border: 1px solid black }
<tr>
<th>Column</th>
<th>Type</th>
+ <th>VARSIZE</th>
<th>Size</th>
<th>Key</th>
<TMPL_LOOP NAME=releases>
@@ -79,6 +82,7 @@ td,th { border: 1px solid black }
<tr>
<td><TMPL_VAR NAME=name></td>
<td><TMPL_VAR NAME=type></td>
+ <td><TMPL_IF NAME=is_varsize>YES<TMPL_ELSE>&nbsp;</TMPL_IF></td>
<td><TMPL_VAR NAME=size></td>
<td><TMPL_VAR NAME=key></td>
<TMPL_LOOP NAME=datamemory>
@@ -129,9 +133,21 @@ td,th { border: 1px solid black }
</TMPL_LOOP>
</tr>
<tr>
+ <th>Nr Varsized Attributes</th>
+ <TMPL_LOOP NAME=nrvarsize>
+ <td><TMPL_VAR NAME=val></td>
+ </TMPL_LOOP>
+</tr>
+<tr>
<th>Row Overhead</th>
- <TMPL_LOOP NAME=releases>
- <td>16</td>
+ <TMPL_LOOP NAME=RowOverhead>
+ <td><TMPL_VAR NAME=val></td>
+ </TMPL_LOOP>
+</tr>
+<tr>
+ <th>Varsized Overhead</th>
+ <TMPL_LOOP NAME=nrvarsize_mem>
+ <td><TMPL_VAR NAME=val></td>
</TMPL_LOOP>
</tr>
<tr>
diff --git a/ndb/tools/restore/consumer.hpp b/ndb/tools/restore/consumer.hpp
index 692c814159f..6a8ef29e295 100644
--- a/ndb/tools/restore/consumer.hpp
+++ b/ndb/tools/restore/consumer.hpp
@@ -31,6 +31,7 @@ public:
virtual void logEntry(const LogEntry &){}
virtual void endOfLogEntrys(){}
virtual bool finalize_table(const TableS &){return true;}
+ virtual bool has_temp_error() {return false;}
};
#endif
diff --git a/ndb/tools/restore/consumer_restore.cpp b/ndb/tools/restore/consumer_restore.cpp
index dc1399e73b2..d67ed139f52 100644
--- a/ndb/tools/restore/consumer_restore.cpp
+++ b/ndb/tools/restore/consumer_restore.cpp
@@ -180,6 +180,11 @@ BackupRestore::finalize_table(const TableS & table){
}
bool
+BackupRestore::has_temp_error(){
+ return m_temp_error;
+}
+
+bool
BackupRestore::table(const TableS & table){
if (!m_restore && !m_restore_meta)
return true;
@@ -485,6 +490,7 @@ bool BackupRestore::errorHandler(restore_callback_t *cb)
case NdbError::TemporaryError:
err << "Temporary error: " << error << endl;
+ m_temp_error = true;
NdbSleep_MilliSleep(sleepTime);
return true;
// RETRY
diff --git a/ndb/tools/restore/consumer_restore.hpp b/ndb/tools/restore/consumer_restore.hpp
index 1bf6d89a912..d1a9678b5ef 100644
--- a/ndb/tools/restore/consumer_restore.hpp
+++ b/ndb/tools/restore/consumer_restore.hpp
@@ -42,6 +42,7 @@ public:
m_parallelism = parallelism;
m_callback = 0;
m_free_callback = 0;
+ m_temp_error = false;
m_transactions = 0;
m_cache.m_old_table = 0;
}
@@ -61,6 +62,7 @@ public:
virtual void logEntry(const LogEntry &);
virtual void endOfLogEntrys();
virtual bool finalize_table(const TableS &);
+ virtual bool has_temp_error();
void connectToMysql();
Ndb * m_ndb;
Ndb_cluster_connection * m_cluster_connection;
@@ -74,6 +76,7 @@ public:
restore_callback_t *m_callback;
restore_callback_t *m_free_callback;
+ bool m_temp_error;
/**
* m_new_table_ids[X] = Y;
diff --git a/ndb/tools/restore/restore_main.cpp b/ndb/tools/restore/restore_main.cpp
index c2e0697b9c5..eb0a8b8d139 100644
--- a/ndb/tools/restore/restore_main.cpp
+++ b/ndb/tools/restore/restore_main.cpp
@@ -52,6 +52,8 @@ static int _restore_data = 0;
static int _restore_meta = 0;
BaseString g_options("ndb_restore");
+const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 };
+
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_restore"),
@@ -104,6 +106,8 @@ static void usage()
{
short_usage_sub();
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
@@ -136,7 +140,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
bool
readArguments(int *pargc, char*** pargv)
{
- const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 };
load_defaults("my",load_default_groups,pargc,pargv);
if (handle_options(pargc, pargv, my_long_options, get_one_option))
{
@@ -430,6 +433,17 @@ main(int argc, char** argv)
}
}
}
+ for(Uint32 i= 0; i < g_consumers.size(); i++)
+ {
+ if (g_consumers[i]->has_temp_error())
+ {
+ clearConsumers();
+ ndbout_c("\nRestore successful, but encountered temporary error, "
+ "please look at configuration.");
+ return NDBT_ProgramExit(NDBT_TEMPORARY);
+ }
+ }
+
clearConsumers();
return NDBT_ProgramExit(NDBT_OK);
} // main
diff --git a/ndb/tools/select_all.cpp b/ndb/tools/select_all.cpp
index baa18db1ebd..7bb3557d1ba 100644
--- a/ndb/tools/select_all.cpp
+++ b/ndb/tools/select_all.cpp
@@ -43,6 +43,8 @@ static const char* _delimiter = "\t";
static int _unqualified, _header, _parallelism, _useHexFormat, _lock,
_order, _descending;
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
@@ -82,13 +84,14 @@ static void usage()
"It can also be used to dump the content of a table to file \n"\
" ex: select_all --no-header --delimiter=';' T4 > T4.data\n";
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
const char* _tabname;
int ho_error;
diff --git a/ndb/tools/select_count.cpp b/ndb/tools/select_count.cpp
index 6fa3c77f15a..0d5d4684878 100644
--- a/ndb/tools/select_count.cpp
+++ b/ndb/tools/select_count.cpp
@@ -37,6 +37,9 @@ NDB_STD_OPTS_VARS;
static const char* _dbname = "TEST_DB";
static int _parallelism = 240;
static int _lock = 0;
+
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
@@ -57,13 +60,14 @@ static void usage()
"tabname1 ... tabnameN\n"\
"This program will count the number of records in tables\n";
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
int ho_error;
#ifndef DBUG_OFF
diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp
index cb02d5e7c36..2a29d3612ba 100644
--- a/ndb/tools/waiter.cpp
+++ b/ndb/tools/waiter.cpp
@@ -38,6 +38,9 @@ NDB_STD_OPTS_VARS;
static int _no_contact = 0;
static int _not_started = 0;
static int _timeout = 120;
+
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
static struct my_option my_long_options[] =
{
NDB_STD_OPTS("ndb_desc"),
@@ -56,13 +59,14 @@ static struct my_option my_long_options[] =
static void usage()
{
ndb_std_print_version();
+ print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
+ puts("");
my_print_help(my_long_options);
my_print_variables(my_long_options);
}
int main(int argc, char** argv){
NDB_INIT(argv[0]);
- const char *load_default_groups[]= { "mysql_cluster",0 };
load_defaults("my",load_default_groups,&argc,&argv);
const char* _hostName = NULL;
int ho_error;
diff --git a/netware/BUILD/compile-netware-END b/netware/BUILD/compile-netware-END
index c5c08cea908..6c531ab5c7c 100755
--- a/netware/BUILD/compile-netware-END
+++ b/netware/BUILD/compile-netware-END
@@ -15,11 +15,16 @@ if test -e "Makefile"; then make -k clean; fi
rm -f */.deps/*.P
rm -rf Makefile.in.bk
-# Metrowerks enviornment
+# Setup Metrowerks environment
. $path/mwenv
-# run auto tools
-. $path/compile-AUTOTOOLS
+# Temporary hack to allow building from source dist
+if [ ! "$USER"=pushbuild ]
+then
+ # Run autotools(use BUILD/autorun.sh)
+ echo "Running autotools again(BUILD/autorun.sh)"
+ . BUILD/autorun.sh
+fi
# configure
./configure $base_configs $extra_configs
diff --git a/netware/BUILD/compile-netware-max b/netware/BUILD/compile-netware-max
index ec737d4615c..3286c3c693b 100644..100755
--- a/netware/BUILD/compile-netware-max
+++ b/netware/BUILD/compile-netware-max
@@ -15,7 +15,7 @@ suffix="max"
extra_configs=" \
--with-innodb \
--with-embedded-server \
- --with-openssl \
+ --with-yassl \
"
. $path/compile-netware-END
diff --git a/netware/BUILD/compile-netware-max-debug b/netware/BUILD/compile-netware-max-debug
index ea3553ae6e1..e3155cbd7d7 100644..100755
--- a/netware/BUILD/compile-netware-max-debug
+++ b/netware/BUILD/compile-netware-max-debug
@@ -15,7 +15,7 @@ extra_configs=" \
--with-innodb \
--with-debug=full \
--with-embedded-server \
- --with-openssl \
+ --with-yassl \
"
. $path/compile-netware-END
diff --git a/netware/BUILD/compile-netware-src b/netware/BUILD/compile-netware-src
index f4e8a53ffea..f4e8a53ffea 100644..100755
--- a/netware/BUILD/compile-netware-src
+++ b/netware/BUILD/compile-netware-src
diff --git a/netware/BUILD/mwenv b/netware/BUILD/mwenv
index d8d53293b2c..a8d31949736 100755
--- a/netware/BUILD/mwenv
+++ b/netware/BUILD/mwenv
@@ -26,8 +26,17 @@ WINE_BUILD_DIR=`echo "$BUILD_DIR" | sed 's_'$base_unix_part'/__'`
WINE_BUILD_DIR="$base/$WINE_BUILD_DIR"
echo "WINE_BUILD_DIR: $WINE_BUILD_DIR"
-export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.2.3;$WINE_BUILD_DIR/include;$MYDEV"
-export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.2.3;$MYDEV/openssl;$WINE_BUILD_DIR/netware/BUILD"
+# Look for libc, MySQL 5.0.x uses libc-2003 by default
+libc_dir="$MYDEV/libc-2003"
+if [ ! -d `winepath $libc_dir` ]
+then
+ # The libcdir didn't exist, set default
+ libc_dir="$MYDEV/libc"
+fi
+echo "Using libc in $libc_dir";
+
+export MWCNWx86Includes="$libc_dir/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.2.3;$WINE_BUILD_DIR/include;$MYDEV"
+export MWNWx86Libraries="$libc_dir/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.2.3;$MYDEV/openssl;$WINE_BUILD_DIR/netware/BUILD"
export MWNWx86LibraryFiles="libcpre.o;libc.imp;netware.imp;mwcrtl.lib;mwcpp.lib;libz.a;neb.imp;zPublics.imp;knetware.imp"
export WINEPATH="$MYDEV/mw/bin"
@@ -46,3 +55,21 @@ export LD='mwldnlm'
export LDFLAGS='-entry _LibCPrelude -exit _LibCPostlude -map -flags pseudopreemption'
export RANLIB=:
export STRIP=:
+
+#
+# Check that TERM has been set to avoid problem "Error opening
+# terminal: unknown" when the script is executed using non interactive ssh
+#
+if test -z "$TERM" -o "$TERM"=dumb
+then
+ export TERM=linux
+fi
+
+# Temporary hack to allow building from source dist
+if [ "$USER"=pushbuild ]
+then
+ export ARFLAGS=$AR_FLAGS
+fi
+
+# Print all env. variables
+export
diff --git a/netware/BUILD/mwldnlm b/netware/BUILD/mwldnlm
index cc8c9e63c6e..b1822827b59 100755
--- a/netware/BUILD/mwldnlm
+++ b/netware/BUILD/mwldnlm
@@ -3,6 +3,13 @@
# stop on errors
set -e
+# If libtool passes "x" as the first argument to this script
+# it's an indication that libtool is trying to unpack .la's
+# so they can be added to a new library
+# This step does not work on Netware and we avoid it by
+# replacing the .la library with the path to the .a library
+# in Makefile.in
+
args=" $*"
# NOTE: Option 'pipefail' is not standard sh
diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap
index 48ff2a49667..e0c0b926619 100755
--- a/netware/BUILD/nwbootstrap
+++ b/netware/BUILD/nwbootstrap
@@ -25,7 +25,7 @@ revision=""
rev=""
build=""
suffix=""
-mwenv=""
+#obsolete mwenv=""
# show usage
show_usage()
@@ -151,14 +151,14 @@ echo "making files writable..."
cd $target_dir
chmod -R u+rw,g+rw .
-# edit the mvenv file
-echo "updating the mwenv environment file..."
-mwenv="./netware/BUILD/mwenv"
-mv -f $mwenv $mwenv.org
-sed -e "s;WINE_BUILD_DIR;$wine_build_dir;g" \
- -e "s;BUILD_DIR;$build_dir;g" \
- -e "s;VERSION;$version;g" $mwenv.org > $mwenv
-chmod +rwx $mwenv
+#obsolete # edit the mvenv file
+#obsolete echo "updating the mwenv environment file..."
+#obsolete mwenv="./netware/BUILD/mwenv"
+#obsolete mv -f $mwenv $mwenv.org
+#obsolete sed -e "s;WINE_BUILD_DIR;$wine_build_dir;g" \
+#obsolete -e "s;BUILD_DIR;$build_dir;g" \
+#obsolete -e "s;VERSION;$version;g" $mwenv.org > $mwenv
+#obsolete chmod +rwx $mwenv
# edit the def file versions
echo "updating *.def file versions..."
diff --git a/netware/Makefile.am b/netware/Makefile.am
index 648ce79c484..de39376f6a1 100644
--- a/netware/Makefile.am
+++ b/netware/Makefile.am
@@ -30,6 +30,8 @@ netware_build_files = client/mysql.def client/mysqladmin.def \
client/mysqlbinlog.def client/mysqlcheck.def \
client/mysqldump.def client/mysqlimport.def \
client/mysqlshow.def client/mysqltest.def \
+ client/mysql_upgrade.def \
+ tests/mysql_client_test.def \
extra/my_print_defaults.def \
extra/perror.def extra/replace.def \
extra/resolveip.def extra/comp_err.def \
@@ -69,7 +71,8 @@ EXTRA_DIST= $(BUILT_SOURCES) comp_err.def init_db.sql install_test_db.ncf \
mysql_test_run.def mysql_waitpid.def mysqladmin.def \
mysqlbinlog.def mysqlcheck.def mysqld.def \
mysqld_safe.c mysqld_safe.def mysqldump.def mysqlimport.def \
- mysqlshow.def mysqltest.def perror.def \
+ mysqlshow.def mysqltest.def mysql_upgrade.def perror.def \
+ mysql_client_test.def \
replace.def resolve_stack_dump.def resolveip.def test_db.sql \
static_init_db.sql \
BUILD/apply-patch BUILD/compile-AUTOTOOLS \
diff --git a/netware/comp_err.def b/netware/comp_err.def
index f27b40c7b78..f5b18bbdb9a 100644
--- a/netware/comp_err.def
+++ b/netware/comp_err.def
@@ -5,6 +5,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Error File Compiler"
VERSION 4, 0
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/isamchk.def b/netware/isamchk.def
index 31cf3fc569a..8ae2c0ca96c 100644
--- a/netware/isamchk.def
+++ b/netware/isamchk.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL ISAM Table Check Tool"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL ISAM Table Check Tool"
VERSION 4, 0
-STACKSIZE 65536
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/isamlog.def b/netware/isamlog.def
index 52f9de0d928..777d73a7835 100644
--- a/netware/isamlog.def
+++ b/netware/isamlog.def
@@ -5,6 +5,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL ISAM Table Log Tool"
VERSION 4, 0
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/libmysql.def b/netware/libmysql.def
index 8a34754e092..d9d4c752612 100644
--- a/netware/libmysql.def
+++ b/netware/libmysql.def
@@ -7,6 +7,6 @@ COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Res
DESCRIPTION "MySQL Client Library"
VERSION 4, 0
AUTOUNLOAD
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/my_print_defaults.def b/netware/my_print_defaults.def
index 778a5204ebd..acba6c81b49 100644
--- a/netware/my_print_defaults.def
+++ b/netware/my_print_defaults.def
@@ -5,7 +5,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Print Defaults Tool"
VERSION 5, 0, 17
-STACKSIZE 32767
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/myisam_ftdump.def b/netware/myisam_ftdump.def
index 9639404b53b..78123537a54 100644
--- a/netware/myisam_ftdump.def
+++ b/netware/myisam_ftdump.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL MyISAM Table Dump Tool"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL MyISAM Table Dump Tool"
VERSION 4, 0
-STACKSIZE 65536
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/myisamchk.def b/netware/myisamchk.def
index b7ec5ac9474..9805eb4ec1b 100644
--- a/netware/myisamchk.def
+++ b/netware/myisamchk.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL MyISAM Table Check Tool[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL MyISAM Table Check Tool"
VERSION 4, 0
-STACKSIZE 65536
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/myisamlog.def b/netware/myisamlog.def
index 553a818a2ae..925650eac7b 100644
--- a/netware/myisamlog.def
+++ b/netware/myisamlog.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL MyISAM Table Log Tool"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL MyISAM Table Log Tool"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/myisampack.def b/netware/myisampack.def
index d1f85fe03f8..877a143fd2e 100644
--- a/netware/myisampack.def
+++ b/netware/myisampack.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL MyISAM Table Pack Tool"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL MyISAM Table Pack Tool"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysql.def b/netware/mysql.def
index 16acc7babe1..4e44f4882d1 100644
--- a/netware/mysql.def
+++ b/netware/mysql.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL Monitor[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Monitor"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
MULTIPLE
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysql_client_test.def b/netware/mysql_client_test.def
new file mode 100644
index 00000000000..9a6f63ec4d7
--- /dev/null
+++ b/netware/mysql_client_test.def
@@ -0,0 +1,10 @@
+#------------------------------------------------------------------------------
+# MySQL Test
+#------------------------------------------------------------------------------
+MODULE libc.nlm
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+DESCRIPTION "MySQL Client Test"
+VERSION 4, 0
+STACKSIZE 131072
+XDCDATA ../netware/mysql.xdc
+#DEBUG
diff --git a/netware/mysql_install_db.def b/netware/mysql_install_db.def
index 372bbf15570..e3dc57fe44c 100644
--- a/netware/mysql_install_db.def
+++ b/netware/mysql_install_db.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL Install"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Initial Database Installer"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysql_test_run.def b/netware/mysql_test_run.def
index d4d4baee168..c8afd305978 100644
--- a/netware/mysql_test_run.def
+++ b/netware/mysql_test_run.def
@@ -2,10 +2,10 @@
# MySQL Test Run
#------------------------------------------------------------------------------
MODULE libc.nlm
-STACKSIZE 65536
SCREENNAME "MySQL Test Run"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Test Run"
VERSION 4, 0
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysql_upgrade.def b/netware/mysql_upgrade.def
new file mode 100644
index 00000000000..7b5718ffb1b
--- /dev/null
+++ b/netware/mysql_upgrade.def
@@ -0,0 +1,11 @@
+#------------------------------------------------------------------------------
+# MySQL Admin
+#------------------------------------------------------------------------------
+MODULE libc.nlm
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+DESCRIPTION "MySQL Upgrade Tool"
+VERSION 4, 0
+STACKSIZE 131072
+XDCDATA ../netware/mysql.xdc
+#DEBUG
+
diff --git a/netware/mysql_waitpid.def b/netware/mysql_waitpid.def
index da0884ccba3..6e9cc76f139 100644
--- a/netware/mysql_waitpid.def
+++ b/netware/mysql_waitpid.def
@@ -6,7 +6,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Tool - Wait for a Program to Terminate"
VERSION 4, 0
-STACKSIZE 65536
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqladmin.def b/netware/mysqladmin.def
index 6532cab84a0..03f15dfdd08 100644
--- a/netware/mysqladmin.def
+++ b/netware/mysqladmin.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL Admin[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Admin Tool"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqlbinlog.def b/netware/mysqlbinlog.def
index aced63429c5..88024acc318 100644
--- a/netware/mysqlbinlog.def
+++ b/netware/mysqlbinlog.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL Binary Log Dump Tool[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Binary Log Dump Tool"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqlcheck.def b/netware/mysqlcheck.def
index 1b90b2a1dbe..b9028c237d1 100644
--- a/netware/mysqlcheck.def
+++ b/netware/mysqlcheck.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL Check Tool[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Check Tool"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqld.def b/netware/mysqld.def
index 42c2d176a1b..bb7b8129983 100644
--- a/netware/mysqld.def
+++ b/netware/mysqld.def
@@ -6,7 +6,7 @@ COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Res
DESCRIPTION "MySQL Database Server"
VERSION 4, 0
MULTIPLE
-STACKSIZE 65536
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqld_safe.def b/netware/mysqld_safe.def
index ff3f1924906..5c436cc97ca 100644
--- a/netware/mysqld_safe.def
+++ b/netware/mysqld_safe.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL Database Server"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Database Server Monitor"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
MULTIPLE
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqldump.def b/netware/mysqldump.def
index 5d7999c789f..2e745492cf3 100644
--- a/netware/mysqldump.def
+++ b/netware/mysqldump.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL Dump Tool[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Dump Tool"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqlimport.def b/netware/mysqlimport.def
index f98d8021a73..5db6b940ce7 100644
--- a/netware/mysqlimport.def
+++ b/netware/mysqlimport.def
@@ -6,7 +6,7 @@ SCREENNAME "MySQL Import[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Import Tool"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqlshow.def b/netware/mysqlshow.def
index b7b84a94067..386cb98c091 100644
--- a/netware/mysqlshow.def
+++ b/netware/mysqlshow.def
@@ -6,6 +6,7 @@ SCREENNAME "MySQL Show[scrollable]"
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Show Tool"
VERSION 4, 0
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/mysqltest.def b/netware/mysqltest.def
index e134acede07..f0ee5f7e6a4 100644
--- a/netware/mysqltest.def
+++ b/netware/mysqltest.def
@@ -5,6 +5,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Test Case Tool"
VERSION 4, 0
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/pack_isam.def b/netware/pack_isam.def
index 9ea72a4f2e7..514b57b04bd 100644
--- a/netware/pack_isam.def
+++ b/netware/pack_isam.def
@@ -7,6 +7,7 @@ COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Res
DESCRIPTION "MySQL ISAM Table Pack Tool"
SCREENNAME "MySQL ISAM Table Pack Tool"
VERSION 4, 0
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/perror.def b/netware/perror.def
index d67bd6191b4..fc95de3476a 100644
--- a/netware/perror.def
+++ b/netware/perror.def
@@ -5,7 +5,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Error Code Description Tool"
VERSION 4, 0
-STACKSIZE 32768
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/replace.def b/netware/replace.def
index 19348ee4245..7feccdbff41 100644
--- a/netware/replace.def
+++ b/netware/replace.def
@@ -5,6 +5,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Text Replacement Tool"
VERSION 4, 0
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/resolve_stack_dump.def b/netware/resolve_stack_dump.def
index 01042699d61..20098c1b4e0 100644
--- a/netware/resolve_stack_dump.def
+++ b/netware/resolve_stack_dump.def
@@ -6,7 +6,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Stack Dump Resolve Tool"
VERSION 4, 0
-STACKSIZE 65536
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/netware/resolveip.def b/netware/resolveip.def
index 244f52bb969..1962d61be53 100644
--- a/netware/resolveip.def
+++ b/netware/resolveip.def
@@ -5,6 +5,7 @@ MODULE libc.nlm
COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL IP/Hostname Resolve Tool"
VERSION 4, 0
+STACKSIZE 131072
XDCDATA ../netware/mysql.xdc
#DEBUG
diff --git a/regex/regexec.c b/regex/regexec.c
index 88bcc02323d..338c1bfa7fe 100644
--- a/regex/regexec.c
+++ b/regex/regexec.c
@@ -15,7 +15,8 @@
#include "utils.h"
#include "regex2.h"
-static int nope = 0; /* for use in asserts; shuts lint up */
+/* for use in asserts */
+#define nope 0
/* macros for manipulating states, small version */
#define states long
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index d9e3ea27895..a6a2f1e3b49 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -121,7 +121,7 @@ copyfileto()
copyfileto $BASE/docs ChangeLog Docs/mysql.info
copyfileto $BASE COPYING COPYING.LIB README Docs/INSTALL-BINARY \
- EXCEPTIONS-CLIENT MySQLEULA.txt LICENSE.doc README.NW
+ EXCEPTIONS-CLIENT LICENSE.mysql
# Non platform-specific bin dir files:
BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \
@@ -240,6 +240,7 @@ $CP mysql-test/lib/*.pl $BASE/mysql-test/lib
$CP mysql-test/lib/*.sql $BASE/mysql-test/lib
$CP mysql-test/t/*.def $BASE/mysql-test/t
$CP mysql-test/include/*.inc $BASE/mysql-test/include
+$CP mysql-test/include/*.test $BASE/mysql-test/include
$CP mysql-test/t/*.def $BASE/mysql-test/t
$CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \
mysql-test/std_data/*.pem mysql-test/std_data/Moscow_leap \
@@ -303,10 +304,7 @@ if [ $BASE_SYSTEM = "netware" ] ; then
$BASE/support-files/build-tags \
$BASE/support-files/MySQL-shared-compat.spec \
$BASE/support-files/ndb-config-2-node.ini \
- $BASE/INSTALL-BINARY \
- $BASE/MySQLEULA.txt
-else
- rm -f $BASE/README.NW
+ $BASE/INSTALL-BINARY
fi
# Make safe_mysqld a symlink to mysqld_safe for backwards portability
diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist
index cc75245e5d9..38e7ab88f22 100755
--- a/scripts/make_win_bin_dist
+++ b/scripts/make_win_bin_dist
@@ -144,8 +144,6 @@ fi
# Copy data directory, readme files etc
# ----------------------------------------------------------------------
-cp COPYING EXCEPTIONS-CLIENT $DESTDIR/
-
# FIXME is there ever a data directory to copy?
if [ -d win/data ] ; then
cp -pR win/data $DESTDIR/data
@@ -159,9 +157,13 @@ mkdir $DESTDIR/Docs
cp Docs/INSTALL-BINARY $DESTDIR/Docs/
cp Docs/manual.chm $DESTDIR/Docs/ || /bin/true
cp ChangeLog $DESTDIR/Docs/ || /bin/true
-cp COPYING $DESTDIR/Docs/
cp support-files/my-*.ini $DESTDIR/
+if [ -f COPYING ] ; then
+ cp COPYING EXCEPTIONS-CLIENT $DESTDIR/
+ cp COPYING $DESTDIR/Docs/
+fi
+
# ----------------------------------------------------------------------
# These will be filled in when we enable embedded. Note that if no
# argument is given, it is copied if exists, else a check is done.
@@ -170,7 +172,8 @@ cp support-files/my-*.ini $DESTDIR/
copy_embedded()
{
mkdir -p $DESTDIR/Embedded/DLL/release \
- $DESTDIR/Embedded/static/release
+ $DESTDIR/Embedded/static/release \
+ $DESTDIR/include
cp libmysqld/libmysqld.def $DESTDIR/include/
cp libmysqld/$TARGET/mysqlserver.lib $DESTDIR/Embedded/static/release/
cp libmysqld/$TARGET/libmysqld.dll $DESTDIR/Embedded/DLL/release/
@@ -211,6 +214,9 @@ fi
mkdir -p $DESTDIR/examples/tests
cp tests/*.res tests/*.tst tests/*.pl tests/*.c $DESTDIR/examples/tests/
+mkdir -p $DESTDIR/examples/udf_example
+cp sql/udf_example.def sql/udf_example.vcproj sql/udf_example.c $DESTDIR/examples/udf_example/
+
# ----------------------------------------------------------------------
# FIXME why not copy it all in "include"?!
# ----------------------------------------------------------------------
@@ -228,6 +234,7 @@ cp include/conf*.h \
include/m_string.h \
include/m_ctype.h \
include/my_global.h \
+ include/raid.h \
include/typelib.h $DESTDIR/include/
cp libmysql/libmysql.def $DESTDIR/include/
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index 5d7933e5277..e43b586054e 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -33,6 +33,7 @@ parse_arguments() {
case "$arg" in
--force) force=1 ;;
--basedir=*) basedir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
+ --srcdir=*) srcdir=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--ldata=*|--datadir=*) ldata=`echo "$arg" | sed -e 's/^[^=]*=//'` ;;
--user=*)
# Note that the user will be passed to mysqld so that it runs
@@ -78,6 +79,7 @@ ldata=
execdir=
bindir=
basedir=
+srcdir=
force=0
verbose=0
fill_help_tables=""
@@ -106,18 +108,24 @@ else
fi
# find fill_help_tables.sh
-for i in $basedir/support-files $basedir/share $basedir/share/mysql $basedir/scripts `pwd` `pwd`/scripts @pkgdatadir@
-do
- if test -f $i/fill_help_tables.sql
- then
- pkgdatadir=$i
- fi
-done
-
-if test -f $pkgdatadir/fill_help_tables.sql
+if test -n "$srcdir"
then
- fill_help_tables=$pkgdatadir/fill_help_tables.sql
+ fill_help_tables=$srcdir/scripts/fill_help_tables.sql
else
+ for i in $basedir/support-files $basedir/share $basedir/share/mysql \
+ $basedir/scripts `pwd` `pwd`/scripts @pkgdatadir@
+ do
+ if test -f $i/fill_help_tables.sql
+ then
+ pkgdatadir=$i
+ fi
+ done
+
+ fill_help_tables=$pkgdatadir/fill_help_tables.sql
+fi
+
+if test ! -f $fill_help_tables
+then
echo "Could not find help file 'fill_help_tables.sql' in @pkgdatadir@ or inside $basedir".
exit 1;
fi
@@ -130,7 +138,13 @@ scriptdir=$bindir
if test "$windows" = 1
then
mysqld="./sql/mysqld"
- mysqld_opt="--language=./sql/share/english"
+ if test -n "$srcdir" -a -f $srcdir/sql/share/english/errmsg.sys
+ then
+ langdir=$srcdir/sql/share/english
+ else
+ langdir=./sql/share/english
+ fi
+ mysqld_opt="--language=$langdir"
scriptdir="./scripts"
fi
diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc
index e2142c97f33..0a037b5b98a 100644
--- a/server-tools/instance-manager/guardian.cc
+++ b/server-tools/instance-manager/guardian.cc
@@ -66,11 +66,11 @@ Guardian_thread::~Guardian_thread()
}
-void Guardian_thread::request_shutdown(bool stop_instances_arg)
+void Guardian_thread::request_shutdown()
{
pthread_mutex_lock(&LOCK_guardian);
/* stop instances or just clean up Guardian repository */
- stop_instances(stop_instances_arg);
+ stop_instances();
shutdown_requested= TRUE;
pthread_mutex_unlock(&LOCK_guardian);
}
@@ -118,11 +118,11 @@ void Guardian_thread::process_instance(Instance *instance,
{
/* Pid file not created yet, don't go to STARTED state yet */
}
- else
+ else if (current_node->state != STARTED)
{
/* clear status fields */
- log_info("guardian: instance %s is running, set state to STARTED",
- instance->options.instance_name);
+ log_info("guardian: instance '%s' is running, set state to STARTED.",
+ (const char *) instance->options.instance_name);
current_node->restart_counter= 0;
current_node->crash_moment= 0;
current_node->state= STARTED;
@@ -132,8 +132,8 @@ void Guardian_thread::process_instance(Instance *instance,
{
switch (current_node->state) {
case NOT_STARTED:
- log_info("guardian: starting instance %s",
- instance->options.instance_name);
+ log_info("guardian: starting instance '%s'...",
+ (const char *) instance->options.instance_name);
/* NOTE, set state to STARTING _before_ start() is called */
current_node->state= STARTING;
@@ -157,8 +157,8 @@ void Guardian_thread::process_instance(Instance *instance,
if (instance->is_crashed())
{
instance->start();
- log_info("guardian: starting instance %s",
- instance->options.instance_name);
+ log_info("guardian: starting instance '%s'...",
+ (const char *) instance->options.instance_name);
}
}
else
@@ -175,8 +175,8 @@ void Guardian_thread::process_instance(Instance *instance,
instance->start();
current_node->last_checked= current_time;
current_node->restart_counter++;
- log_info("guardian: restarting instance %s",
- instance->options.instance_name);
+ log_info("guardian: restarting instance '%s'...",
+ (const char *) instance->options.instance_name);
}
}
else
@@ -222,8 +222,6 @@ void Guardian_thread::run()
while (node != NULL)
{
- struct timespec timeout;
-
GUARD_NODE *current_node= (GUARD_NODE *) node->data;
instance= ((GUARD_NODE *) node->data)->instance;
process_instance(instance, current_node, &guarded_instances, node);
@@ -382,12 +380,11 @@ int Guardian_thread::stop_guard(Instance *instance)
SYNOPSYS
stop_instances()
- stop_instances_arg whether we should stop instances at shutdown
DESCRIPTION
Loops through the guarded_instances list and prepares them for shutdown.
- If stop_instances was requested, we need to issue a stop command and change
- the state accordingly. Otherwise we simply delete an entry.
+ For each instance we issue a stop command and change the state
+ accordingly.
NOTE
Guardian object should be locked by the calling function.
@@ -397,42 +394,29 @@ int Guardian_thread::stop_guard(Instance *instance)
1 - error occured
*/
-int Guardian_thread::stop_instances(bool stop_instances_arg)
+int Guardian_thread::stop_instances()
{
LIST *node;
node= guarded_instances;
while (node != NULL)
{
- if (!stop_instances_arg)
+ GUARD_NODE *current_node= (GUARD_NODE *) node->data;
+ /*
+ If instance is running or was running (and now probably hanging),
+ request stop.
+ */
+ if (current_node->instance->is_running() ||
+ (current_node->state == STARTED))
{
- /* just forget about an instance */
- guarded_instances= list_delete(guarded_instances, node);
- /*
- This should still work fine, as we have only removed the
- node from the list. The pointer to the next one is still valid
- */
- node= node->next;
+ current_node->state= STOPPING;
+ current_node->last_checked= time(NULL);
}
else
- {
- GUARD_NODE *current_node= (GUARD_NODE *) node->data;
- /*
- If instance is running or was running (and now probably hanging),
- request stop.
- */
- if (current_node->instance->is_running() ||
- (current_node->state == STARTED))
- {
- current_node->state= STOPPING;
- current_node->last_checked= time(NULL);
- }
- else
- /* otherwise remove it from the list */
- guarded_instances= list_delete(guarded_instances, node);
- /* But try to kill it anyway. Just in case */
- current_node->instance->kill_instance(SIGTERM);
- node= node->next;
- }
+ /* otherwise remove it from the list */
+ guarded_instances= list_delete(guarded_instances, node);
+ /* But try to kill it anyway. Just in case */
+ current_node->instance->kill_instance(SIGTERM);
+ node= node->next;
}
return 0;
}
@@ -440,7 +424,7 @@ int Guardian_thread::stop_instances(bool stop_instances_arg)
void Guardian_thread::lock()
{
- pthread_mutex_lock(&LOCK_guardian);
+ pthread_mutex_lock(&LOCK_guardian);
}
diff --git a/server-tools/instance-manager/guardian.h b/server-tools/instance-manager/guardian.h
index 16b4c373c91..f1c54262c12 100644
--- a/server-tools/instance-manager/guardian.h
+++ b/server-tools/instance-manager/guardian.h
@@ -89,7 +89,7 @@ public:
/* Initialize or refresh the list of guarded instances */
int init();
/* Request guardian shutdown. Stop instances if needed */
- void request_shutdown(bool stop_instances);
+ void request_shutdown();
/* Start instance protection */
int guard(Instance *instance, bool nolock= FALSE);
/* Stop instance protection */
@@ -104,7 +104,7 @@ public:
private:
/* Prepares Guardian shutdown. Stops instances is needed */
- int stop_instances(bool stop_instances_arg);
+ int stop_instances();
/* check instance state and act accordingly */
void process_instance(Instance *instance, GUARD_NODE *current_node,
LIST **guarded_instances, LIST *elem);
diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc
index b792d132da0..daa8082ef2f 100644
--- a/server-tools/instance-manager/instance.cc
+++ b/server-tools/instance-manager/instance.cc
@@ -156,8 +156,8 @@ static int start_process(Instance_options *instance_options,
/* exec never returns */
exit(1);
case -1:
- log_info("cannot create a new process to start instance %s",
- instance_options->instance_name);
+ log_info("cannot create a new process to start instance '%s'.",
+ (const char *) instance_options->instance_name);
return 1;
}
return 0;
@@ -252,7 +252,8 @@ static void start_and_monitor_instance(Instance_options *old_instance_options,
MAX_INSTANCE_NAME_LEN - 1);
instance_name_len= old_instance_options->instance_name_len;
- log_info("starting instance %s", instance_name_buff);
+ log_info("starting instance '%s'...",
+ (const char *) instance_name_buff);
if (start_process(old_instance_options, &process_info))
{
@@ -286,9 +287,9 @@ void Instance::remove_pid()
int pid;
if ((pid= options.get_pid()) != 0) /* check the pidfile */
if (options.unlink_pidfile()) /* remove stalled pidfile */
- log_error("cannot remove pidfile for instance %i, this might be \
+ log_error("cannot remove pidfile for instance '%s', this might be \
since IM lacks permmissions or hasn't found the pidifle",
- options.instance_name);
+ (const char *) options.instance_name);
}
@@ -435,9 +436,9 @@ bool Instance::is_running()
We have successfully connected to the server using fake
username/password. Write a warning to the logfile.
*/
- log_info("The Instance Manager was able to log into you server \
- with faked compiled-in password while checking server status. \
- Looks like something is wrong.");
+ log_info("The Instance Manager was able to log into you server "
+ "with faked compiled-in password while checking server status. "
+ "Looks like something is wrong.");
pthread_mutex_unlock(&LOCK_instance);
return_val= TRUE; /* server is alive */
}
@@ -577,10 +578,10 @@ void Instance::kill_instance(int signum)
/* Kill suceeded */
if (signum == SIGKILL) /* really killed instance with SIGKILL */
{
- log_error("The instance %s is being stopped forcibly. Normally" \
- "it should not happen. Probably the instance has been" \
+ log_error("The instance '%s' is being stopped forcibly. Normally"
+ "it should not happen. Probably the instance has been"
"hanging. You should also check your IM setup",
- options.instance_name);
+ (const char *) options.instance_name);
/* After sucessful hard kill the pidfile need to be removed */
options.unlink_pidfile();
}
diff --git a/server-tools/instance-manager/instance_map.cc b/server-tools/instance-manager/instance_map.cc
index 3b7f58d8a09..f6662847440 100644
--- a/server-tools/instance-manager/instance_map.cc
+++ b/server-tools/instance-manager/instance_map.cc
@@ -215,7 +215,9 @@ int Instance_map::flush_instances()
hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
get_instance_key, delete_instance, 0);
rc= load();
- guardian->init(); // TODO: check error status.
+ /* don't init guardian if we failed to load instances */
+ if (!rc)
+ guardian->init(); // TODO: check error status.
pthread_mutex_unlock(&LOCK_instance_map);
guardian->unlock();
return rc;
diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc
index 58a4093dd05..3f60c2cc74a 100644
--- a/server-tools/instance-manager/listener.cc
+++ b/server-tools/instance-manager/listener.cc
@@ -280,7 +280,7 @@ int Listener_thread::create_tcp_socket()
FD_SET(ip_socket, &read_fds);
sockets[num_sockets++]= ip_socket;
- log_info("accepting connections on ip socket");
+ log_info("accepting connections on ip socket (port: %d)", (int) im_port);
return 0;
}
@@ -334,7 +334,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address)
/* make sure that instances won't be listening our sockets */
set_no_inherit(unix_socket);
- log_info("accepting connections on unix socket %s",
+ log_info("accepting connections on unix socket '%s'",
unix_socket_address.sun_path);
sockets[num_sockets++]= unix_socket;
FD_SET(unix_socket, &read_fds);
diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc
index 353dfcf64dc..ec22e5c4fbb 100644
--- a/server-tools/instance-manager/manager.cc
+++ b/server-tools/instance-manager/manager.cc
@@ -104,6 +104,19 @@ int my_sigwait(const sigset_t *set, int *sig)
#endif
+void stop_all(Guardian_thread *guardian, Thread_registry *registry)
+{
+ /*
+ Let guardian thread know that it should break it's processing cycle,
+ once it wakes up.
+ */
+ guardian->request_shutdown();
+ /* wake guardian */
+ pthread_cond_signal(&guardian->COND_guardian);
+ /* stop all threads */
+ registry->deliver_shutdown();
+}
+
/*
manager - entry point to the main instance manager process: start
listener thread, write pid file and enter into signal handling.
@@ -210,7 +223,8 @@ void manager(const Options &options)
log_error("Cannot init instances repository. This might be caused by "
"the wrong config file options. For instance, missing mysqld "
"binary. Aborting.");
- return;
+ stop_all(&guardian_thread, &thread_registry);
+ goto err;
}
/* create the listener */
@@ -227,6 +241,7 @@ void manager(const Options &options)
if (rc)
{
log_error("manager(): set_stacksize_n_create_thread(listener) failed");
+ stop_all(&guardian_thread, &thread_registry);
goto err;
}
@@ -245,6 +260,7 @@ void manager(const Options &options)
if ((status= my_sigwait(&mask, &signo)) != 0)
{
log_error("sigwait() failed");
+ stop_all(&guardian_thread, &thread_registry);
goto err;
}
@@ -266,8 +282,7 @@ void manager(const Options &options)
{
if (!guardian_thread.is_stopped())
{
- bool stop_instances= true;
- guardian_thread.request_shutdown(stop_instances);
+ guardian_thread.request_shutdown();
pthread_cond_signal(&guardian_thread.COND_guardian);
}
else
diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc
index bf39c843f0a..a19914dfdd2 100644
--- a/server-tools/instance-manager/mysql_connection.cc
+++ b/server-tools/instance-manager/mysql_connection.cc
@@ -163,7 +163,7 @@ Mysql_connection_thread::~Mysql_connection_thread()
void Mysql_connection_thread::run()
{
- log_info("accepted mysql connection %d", connection_id);
+ log_info("accepted mysql connection %lu", connection_id);
my_thread_init();
@@ -173,7 +173,7 @@ void Mysql_connection_thread::run()
return;
}
- log_info("connection %d is checked successfully", connection_id);
+ log_info("connection %lu is checked successfully", connection_id);
vio_keepalive(vio, TRUE);
@@ -312,7 +312,7 @@ int Mysql_connection_thread::do_command()
packet= (char*) net.read_pos;
enum enum_server_command command= (enum enum_server_command)
(uchar) *packet;
- log_info("connection %d: packet_length=%d, command=%d",
+ log_info("connection %lu: packet_length=%lu, command=%d",
connection_id, packet_length, command);
return dispatch_command(command, packet + 1, packet_length - 1);
}
@@ -323,27 +323,27 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
{
switch (command) {
case COM_QUIT: // client exit
- log_info("query for connection %d received quit command", connection_id);
+ log_info("query for connection %lu received quit command", connection_id);
return 1;
case COM_PING:
- log_info("query for connection %d received ping command", connection_id);
+ log_info("query for connection %lu received ping command", connection_id);
net_send_ok(&net, connection_id, NULL);
break;
case COM_QUERY:
{
- log_info("query for connection %d : ----\n%s\n-------------------------",
+ log_info("query for connection %lu : ----\n%s\n-------------------------",
connection_id,packet);
if (Command *command= parse_command(&instance_map, packet))
{
int res= 0;
- log_info("query for connection %d successefully parsed",connection_id);
+ log_info("query for connection %lu successefully parsed",connection_id);
res= command->execute(&net, connection_id);
delete command;
if (!res)
- log_info("query for connection %d executed ok",connection_id);
+ log_info("query for connection %lu executed ok",connection_id);
else
{
- log_info("query for connection %d executed err=%d",connection_id,res);
+ log_info("query for connection %lu executed err=%d",connection_id,res);
net_send_error(&net, res);
return 0;
}
@@ -356,7 +356,7 @@ int Mysql_connection_thread::dispatch_command(enum enum_server_command command,
break;
}
default:
- log_info("query for connection %d received unknown command",connection_id);
+ log_info("query for connection %lu received unknown command",connection_id);
net_send_error(&net, ER_UNKNOWN_COM_ERROR);
break;
}
diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc
index a98c0e291be..c6c709295bc 100644
--- a/server-tools/instance-manager/options.cc
+++ b/server-tools/instance-manager/options.cc
@@ -45,10 +45,10 @@ const char *default_password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME);
const char *default_log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
const char *Options::config_file= QUOTE(DEFAULT_CONFIG_FILE);
const char *Options::angel_pid_file_name= NULL;
+const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
#endif
const char *Options::log_file_name= default_log_file_name;
const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
-const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
const char *Options::password_file_name= default_password_file_name;
const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
const char *Options::bind_address= 0; /* No default value */
@@ -106,11 +106,11 @@ static struct my_option my_long_options[] =
(gptr *) &Options::angel_pid_file_name,
(gptr *) &Options::angel_pid_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
-#endif
{ "socket", OPT_SOCKET, "Socket file to use for connection.",
(gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+#endif
{ "passwd", 'P', "Prepare entry for passwd file and exit.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
diff --git a/server-tools/instance-manager/options.h b/server-tools/instance-manager/options.h
index ad3458869b6..f32e106bd7a 100644
--- a/server-tools/instance-manager/options.h
+++ b/server-tools/instance-manager/options.h
@@ -36,11 +36,11 @@ struct Options
static char run_as_service; /* handle_options doesn't support bool */
static const char *user;
static const char *angel_pid_file_name;
+ static const char *socket_file_name;
#endif
static bool is_forced_default_file;
static const char *log_file_name;
static const char *pid_file_name;
- static const char *socket_file_name;
static const char *password_file_name;
static const char *default_mysqld_path;
/* the option which should be passed to process_default_option_files */
diff --git a/server-tools/instance-manager/portability.h b/server-tools/instance-manager/portability.h
index 23a5a5bd14c..7992a06c336 100644
--- a/server-tools/instance-manager/portability.h
+++ b/server-tools/instance-manager/portability.h
@@ -15,7 +15,6 @@
#define snprintf _snprintf
#define SIGKILL 9
-#define SHUT_RDWR 0x2
/*TODO: fix this */
#define PROTOCOL_VERSION 10
diff --git a/sql-common/client.c b/sql-common/client.c
index cfd53fb1012..c8984e29a34 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -598,7 +598,7 @@ cli_safe_read(MYSQL *mysql)
if (len == packet_error || len == 0)
{
- DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d",
+ DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %lu",
vio_description(net->vio),len));
#ifdef MYSQL_SERVER
if (net->vio && vio_was_interrupted(net->vio))
@@ -753,6 +753,29 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
DBUG_VOID_RETURN;
}
+
+static void set_mysql_extended_error(MYSQL *mysql, int errcode,
+ const char *sqlstate,
+ const char *format, ...)
+{
+ NET *net;
+ va_list args;
+ DBUG_ENTER("set_mysql_extended_error");
+ DBUG_PRINT("enter", ("error :%d '%s'", errcode, format));
+ DBUG_ASSERT(mysql != 0);
+
+ net= &mysql->net;
+ net->last_errno= errcode;
+ va_start(args, format);
+ my_vsnprintf(net->last_error, sizeof(net->last_error)-1,
+ format, args);
+ va_end(args);
+ strmov(net->sqlstate, sqlstate);
+
+ DBUG_VOID_RETURN;
+}
+
+
/*
Flush result set sent from server
*/
@@ -850,6 +873,7 @@ static int check_license(MYSQL *mysql)
void end_server(MYSQL *mysql)
{
+ int save_errno= errno;
DBUG_ENTER("end_server");
if (mysql->net.vio != 0)
{
@@ -862,6 +886,7 @@ void end_server(MYSQL *mysql)
}
net_end(&mysql->net);
free_old_query(mysql);
+ errno= save_errno;
DBUG_VOID_RETURN;
}
@@ -870,7 +895,7 @@ void STDCALL
mysql_free_result(MYSQL_RES *result)
{
DBUG_ENTER("mysql_free_result");
- DBUG_PRINT("enter",("mysql_res: %lx",result));
+ DBUG_PRINT("enter",("mysql_res: 0x%lx", (long) result));
if (result)
{
MYSQL *mysql= result->handle;
@@ -1191,6 +1216,8 @@ unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
for (row=data->data; row ; row = row->next,field++)
{
uchar *pos;
+ /* fields count may be wrong */
+ DBUG_ASSERT((uint) (field - result) < fields);
cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
field->catalog = strdup_root(alloc,(char*) row->data[0]);
field->db = strdup_root(alloc,(char*) row->data[1]);
@@ -1366,7 +1393,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
DBUG_PRINT("info",("status: %u warning_count: %u",
mysql->server_status, mysql->warning_count));
}
- DBUG_PRINT("exit",("Got %d rows",result->rows));
+ DBUG_PRINT("exit", ("Got %lu rows", (ulong) result->rows));
DBUG_RETURN(result);
}
@@ -2031,7 +2058,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
if (mysql->options.connect_timeout &&
vio_poll_read(net->vio, mysql->options.connect_timeout))
{
- set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "waiting for initial communication packet",
+ errno);
goto error;
}
@@ -2040,8 +2070,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
*/
if ((pkt_length=cli_safe_read(mysql)) == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading initial communication packet",
+ errno);
goto error;
-
+ }
/* Check if version of protocol matches current one */
mysql->protocol_version= net->read_pos[0];
@@ -2175,7 +2211,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
*/
if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net))
{
- set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending connection information to server",
+ errno);
goto error;
}
@@ -2254,7 +2293,10 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
/* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
{
- set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending authentication information",
+ errno);
goto error;
}
@@ -2264,7 +2306,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
*/
if ((pkt_length=cli_safe_read(mysql)) == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading authorization packet",
+ errno);
goto error;
+ }
if (pkt_length == 1 && net->read_pos[0] == 254 &&
mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
@@ -2276,12 +2325,22 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
scramble_323(buff, mysql->scramble, passwd);
if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
{
- set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "sending password information",
+ errno);
goto error;
}
/* Read what server thinks about out new auth message report */
if (cli_safe_read(mysql) == packet_error)
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "reading final connect information",
+ errno);
goto error;
+ }
}
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
@@ -2292,8 +2351,15 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
goto error;
#endif
- if (db && mysql_select_db(mysql,db))
+ if (db && mysql_select_db(mysql, db))
+ {
+ if (mysql->net.last_errno == CR_SERVER_LOST)
+ set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
+ ER(CR_SERVER_LOST_EXTENDED),
+ "Setting intital database",
+ errno);
goto error;
+ }
if (mysql->options.init_commands)
{
@@ -2324,7 +2390,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
goto error;
#endif
- DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
+ DBUG_PRINT("exit", ("Mysql handler: 0x%lx", (long) mysql));
reset_sigpipe(mysql);
DBUG_RETURN(mysql);
@@ -2369,6 +2435,8 @@ my_bool mysql_reconnect(MYSQL *mysql)
{
MYSQL tmp_mysql;
DBUG_ENTER("mysql_reconnect");
+ DBUG_ASSERT(mysql);
+ DBUG_PRINT("enter", ("mysql->reconnect: %d", mysql->reconnect));
if (!mysql->reconnect ||
(mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
@@ -2695,7 +2763,7 @@ int STDCALL
mysql_real_query(MYSQL *mysql, const char *query, ulong length)
{
DBUG_ENTER("mysql_real_query");
- DBUG_PRINT("enter",("handle: %lx",mysql));
+ DBUG_PRINT("enter",("handle: 0x%lx", (long) mysql));
DBUG_PRINT("query",("Query = '%-.4096s'",query));
if (mysql_send_query(mysql,query,length))
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index eea36adcaf3..40bc9c79b63 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -429,7 +429,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
goto err;
}
- if (check_date(l_time, not_zero_date, flags, was_cut))
+ if (check_date(l_time, not_zero_date != 0, flags, was_cut))
goto err;
l_time->time_type= (number_of_fields <= 3 ?
@@ -465,8 +465,10 @@ err:
There may be an optional [.second_part] after seconds
length Length of str
l_time Store result here
- was_cut Set to 1 if value was cut during conversion or to 0
- otherwise.
+ warning Set MYSQL_TIME_WARN_TRUNCATED flag if the input string
+ was cut during conversion, and/or
+ MYSQL_TIME_WARN_OUT_OF_RANGE flag, if the value is
+ out of range.
NOTES
Because of the extra days argument, this function can only
@@ -478,15 +480,16 @@ err:
*/
my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
- int *was_cut)
+ int *warning)
{
- long date[5],value;
+ ulong date[5];
+ ulonglong value;
const char *end=str+length, *end_of_days;
my_bool found_days,found_hours;
uint state;
l_time->neg=0;
- *was_cut= 0;
+ *warning= 0;
for (; str != end && my_isspace(&my_charset_latin1,*str) ; str++)
length--;
if (str != end && *str == '-')
@@ -501,13 +504,16 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
/* Check first if this is a full TIMESTAMP */
if (length >= 12)
{ /* Probably full timestamp */
+ int was_cut;
enum enum_mysql_timestamp_type
res= str_to_datetime(str, length, l_time,
- (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), was_cut);
+ (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut);
if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR)
+ {
+ if (was_cut)
+ *warning|= MYSQL_TIME_WARN_TRUNCATED;
return res == MYSQL_TIMESTAMP_ERROR;
- /* We need to restore was_cut flag since str_to_datetime can modify it */
- *was_cut= 0;
+ }
}
/* Not a timestamp. Try to get this as a DAYS_TO_SECOND string */
@@ -524,15 +530,15 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
if ((uint) (end-str) > 1 && str != end_of_days &&
my_isdigit(&my_charset_latin1, *str))
{ /* Found days part */
- date[0]= value;
+ date[0]= (ulong) value;
state= 1; /* Assume next is hours */
found_days= 1;
}
else if ((end-str) > 1 && *str == time_separator &&
my_isdigit(&my_charset_latin1, str[1]))
{
- date[0]=0; /* Assume we found hours */
- date[1]=value;
+ date[0]= 0; /* Assume we found hours */
+ date[1]= (ulong) value;
state=2;
found_hours=1;
str++; /* skip ':' */
@@ -541,9 +547,9 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
{
/* String given as one number; assume HHMMSS format */
date[0]= 0;
- date[1]= value/10000;
- date[2]= value/100 % 100;
- date[3]= value % 100;
+ date[1]= (ulong) (value/10000);
+ date[2]= (ulong) (value/100 % 100);
+ date[3]= (ulong) (value % 100);
state=4;
goto fractional;
}
@@ -553,7 +559,7 @@ my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
{
for (value=0; str != end && my_isdigit(&my_charset_latin1,*str) ; str++)
value=value*10L + (long) (*str - '0');
- date[state++]=value;
+ date[state++]= (ulong) value;
if (state == 4 || (end-str) < 2 || *str != time_separator ||
!my_isdigit(&my_charset_latin1,str[1]))
break;
@@ -587,8 +593,8 @@ fractional:
if (field_length > 0)
value*= (long) log_10_int[field_length];
else if (field_length < 0)
- *was_cut= 1;
- date[4]=value;
+ *warning|= MYSQL_TIME_WARN_TRUNCATED;
+ date[4]= (ulong) value;
}
else
date[4]=0;
@@ -601,10 +607,7 @@ fractional:
((str[1] == '-' || str[1] == '+') &&
(end - str) > 2 &&
my_isdigit(&my_charset_latin1, str[2]))))
- {
- *was_cut= 1;
return 1;
- }
if (internal_format_positions[7] != 255)
{
@@ -623,12 +626,12 @@ fractional:
}
}
- /* Some simple checks */
- if (date[2] >= 60 || date[3] >= 60)
- {
- *was_cut= 1;
+ /* Integer overflow checks */
+ if (date[0] > UINT_MAX || date[1] > UINT_MAX ||
+ date[2] > UINT_MAX || date[3] > UINT_MAX ||
+ date[4] > UINT_MAX)
return 1;
- }
+
l_time->year= 0; /* For protocol::store_time */
l_time->month= 0;
l_time->day= date[0];
@@ -638,6 +641,10 @@ fractional:
l_time->second_part= date[4];
l_time->time_type= MYSQL_TIMESTAMP_TIME;
+ /* Check if the value is valid and fits into TIME range */
+ if (check_time_range(l_time, warning))
+ return 1;
+
/* Check if there is garbage at end of the TIME specification */
if (str != end)
{
@@ -645,7 +652,7 @@ fractional:
{
if (!my_isspace(&my_charset_latin1,*str))
{
- *was_cut= 1;
+ *warning|= MYSQL_TIME_WARN_TRUNCATED;
break;
}
} while (++str != end);
@@ -655,6 +662,47 @@ fractional:
/*
+ Check 'time' value to lie in the TIME range
+
+ SYNOPSIS:
+ check_time_range()
+ time pointer to TIME value
+ warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
+
+ DESCRIPTION
+ If the time value lies outside of the range [-838:59:59, 838:59:59],
+ set it to the closest endpoint of the range and set
+ MYSQL_TIME_WARN_OUT_OF_RANGE flag in the 'warning' variable.
+
+ RETURN
+ 0 time value is valid, but was possibly truncated
+ 1 time value is invalid
+*/
+
+int check_time_range(struct st_mysql_time *time, int *warning)
+{
+ longlong hour;
+
+ if (time->minute >= 60 || time->second >= 60)
+ return 1;
+
+ hour= time->hour + (24*time->day);
+ if (hour <= TIME_MAX_HOUR &&
+ (hour != TIME_MAX_HOUR || time->minute != TIME_MAX_MINUTE ||
+ time->second != TIME_MAX_SECOND || !time->second_part))
+ return 0;
+
+ time->day= 0;
+ time->hour= TIME_MAX_HOUR;
+ time->minute= TIME_MAX_MINUTE;
+ time->second= TIME_MAX_SECOND;
+ time->second_part= 0;
+ *warning|= MYSQL_TIME_WARN_OUT_OF_RANGE;
+ return 0;
+}
+
+
+/*
Prepare offset of system time zone from UTC for my_system_gmt_sec() func.
SYNOPSIS
@@ -730,16 +778,28 @@ long calc_daynr(uint year,uint month,uint day)
RETURN VALUE
Time in UTC seconds since Unix Epoch representation.
*/
-my_time_t
-my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone,
+my_time_t
+my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone,
my_bool *in_dst_time_gap)
{
uint loop;
- time_t tmp;
+ time_t tmp= 0;
+ int shift= 0;
+ MYSQL_TIME tmp_time;
+ MYSQL_TIME *t= &tmp_time;
struct tm *l_time,tm_tmp;
long diff, current_timezone;
/*
+ Use temp variable to avoid trashing input data, which could happen in
+ case of shift required for boundary dates processing.
+ */
+ memcpy(&tmp_time, t_src, sizeof(MYSQL_TIME));
+
+ if (!validate_timestamp_range(t))
+ return 0;
+
+ /*
Calculate the gmt time based on current time and timezone
The -1 on the end is to ensure that if have a date that exists twice
(like 2002-10-27 02:00:0 MET), we will find the initial date.
@@ -752,13 +812,89 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone,
Note: this code assumes that our time_t estimation is not too far away
from real value (we assume that localtime_r(tmp) will return something
within 24 hrs from t) which is probably true for all current time zones.
+
+ Note2: For the dates, which have time_t representation close to
+ MAX_INT32 (efficient time_t limit for supported platforms), we should
+ do a small trick to avoid overflow. That is, convert the date, which is
+ two days earlier, and then add these days to the final value.
+
+ The same trick is done for the values close to 0 in time_t
+ representation for platfroms with unsigned time_t (QNX).
+
+ To be more verbose, here is a sample (extracted from the code below):
+ (calc_daynr(2038, 1, 19) - (long) days_at_timestart)*86400L + 4*3600L
+ would return -2147480896 because of the long type overflow. In result
+ we would get 1901 year in localtime_r(), which is an obvious error.
+
+ Alike problem raises with the dates close to Epoch. E.g.
+ (calc_daynr(1969, 12, 31) - (long) days_at_timestart)*86400L + 23*3600L
+ will give -3600.
+
+ On some platforms, (E.g. on QNX) time_t is unsigned and localtime(-3600)
+ wil give us a date around 2106 year. Which is no good.
+
+ Theoreticaly, there could be problems with the latter conversion:
+ there are at least two timezones, which had time switches near 1 Jan
+ of 1970 (because of political reasons). These are America/Hermosillo and
+ America/Mazatlan time zones. They changed their offset on
+ 1970-01-01 08:00:00 UTC from UTC-8 to UTC-7. For these zones
+ the code below will give incorrect results for dates close to
+ 1970-01-01, in the case OS takes into account these historical switches.
+ Luckily, it seems that we support only one platform with unsigned
+ time_t. It's QNX. And QNX does not support historical timezone data at all.
+ E.g. there are no /usr/share/zoneinfo/ files or any other mean to supply
+ historical information for localtime_r() etc. That is, the problem is not
+ relevant to QNX.
+
+ We are safe with shifts close to MAX_INT32, as there are no known
+ time switches on Jan 2038 yet :)
*/
- tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
- (long) days_at_timestart)*86400L + (long) t->hour*3600L +
- (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
- 3600);
- current_timezone= my_time_zone;
+ if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && (t->day > 4))
+ {
+ /*
+ Below we will pass (uint) (t->day - shift) to calc_daynr.
+ As we don't want to get an overflow here, we will shift
+ only safe dates. That's why we have (t->day > 4) above.
+ */
+ t->day-= 2;
+ shift= 2;
+ }
+#ifdef TIME_T_UNSIGNED
+ else
+ {
+ /*
+ We can get 0 in time_t representaion only on 1969, 31 of Dec or on
+ 1970, 1 of Jan. For both dates we use shift, which is added
+ to t->day in order to step out a bit from the border.
+ This is required for platforms, where time_t is unsigned.
+ As far as I know, among the platforms we support it's only QNX.
+ Note: the order of below if-statements is significant.
+ */
+ if ((t->year == TIMESTAMP_MIN_YEAR + 1) && (t->month == 1)
+ && (t->day <= 10))
+ {
+ t->day+= 2;
+ shift= -2;
+ }
+
+ if ((t->year == TIMESTAMP_MIN_YEAR) && (t->month == 12)
+ && (t->day == 31))
+ {
+ t->year++;
+ t->month= 1;
+ t->day= 2;
+ shift= -2;
+ }
+ }
+#endif
+
+ tmp= (time_t) (((calc_daynr((uint) t->year, (uint) t->month, (uint) t->day) -
+ (long) days_at_timestart)*86400L + (long) t->hour*3600L +
+ (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
+ 3600);
+
+ current_timezone= my_time_zone;
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
for (loop=0;
@@ -810,7 +946,24 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone,
*in_dst_time_gap= 1;
}
*my_timezone= current_timezone;
-
+
+
+ /* shift back, if we were dealing with boundary dates */
+ tmp+= shift*86400L;
+
+ /*
+ This is possible for dates, which slightly exceed boundaries.
+ Conversion will pass ok for them, but we don't allow them.
+ First check will pass for platforms with signed time_t.
+ instruction above (tmp+= shift*86400L) could exceed
+ MAX_INT32 (== TIMESTAMP_MAX_VALUE) and overflow will happen.
+ So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms
+ with unsigned time_t tmp+= shift*86400L might result in a number,
+ larger then TIMESTAMP_MAX_VALUE, so another check will work.
+ */
+ if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE))
+ tmp= 0;
+
return (my_time_t) tmp;
} /* my_system_gmt_sec */
@@ -840,7 +993,7 @@ void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
{
uint extra_hours= 0;
- return my_sprintf(to, (to, "%s%02d:%02d:%02d",
+ return my_sprintf(to, (to, "%s%02u:%02u:%02u",
(l_time->neg ? "-" : ""),
extra_hours+ l_time->hour,
l_time->minute,
@@ -849,7 +1002,7 @@ int my_time_to_str(const MYSQL_TIME *l_time, char *to)
int my_date_to_str(const MYSQL_TIME *l_time, char *to)
{
- return my_sprintf(to, (to, "%04d-%02d-%02d",
+ return my_sprintf(to, (to, "%04u-%02u-%02u",
l_time->year,
l_time->month,
l_time->day));
@@ -857,7 +1010,7 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to)
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to)
{
- return my_sprintf(to, (to, "%04d-%02d-%02d %02d:%02d:%02d",
+ return my_sprintf(to, (to, "%04u-%02u-%02u %02u:%02u:%02u",
l_time->year,
l_time->month,
l_time->day,
diff --git a/sql/Makefile.am b/sql/Makefile.am
index d9cea960915..cbb87f16d80 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -148,10 +148,15 @@ mysql_tzinfo_to_sql.o: $(mysql_tzinfo_to_sql_SOURCES)
sql_yacc.cc: sql_yacc.yy
sql_yacc.h: sql_yacc.yy
+# Be careful here, note that we use VPATH and might or might not have
+# a pregenerated "sql_yacc.cc" in $(srcdir) or one we just built in
+# $(builddir). And it has to work if $(srcdir) == $(builddir).
sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS)
+ @SED@ -e 's/__attribute__ ((__unused__))//' $< > sql_yacc.cc-new
+ @MV@ sql_yacc.cc-new sql_yacc.cc
@echo "Note: The following compile may take a long time."
@echo "If it fails, re-run configure with --with-low-memory"
- $(CXXCOMPILE) $(LM_CFLAGS) -c $<
+ $(CXXCOMPILE) $(LM_CFLAGS) -c sql_yacc.cc
# This generates lex_hash.h
# NOTE Built sources should depend on their sources not the tool
diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc
index 471ece77490..92e5469a832 100644
--- a/sql/examples/ha_example.cc
+++ b/sql/examples/ha_example.cc
@@ -523,10 +523,10 @@ int ha_example::rnd_pos(byte * buf, byte *pos)
sql_update.cc
*/
-void ha_example::info(uint flag)
+int ha_example::info(uint flag)
{
DBUG_ENTER("ha_example::info");
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
diff --git a/sql/examples/ha_example.h b/sql/examples/ha_example.h
index 37f38fe5210..f18063f6c32 100644
--- a/sql/examples/ha_example.h
+++ b/sql/examples/ha_example.h
@@ -136,7 +136,7 @@ public:
int rnd_next(byte *buf); //required
int rnd_pos(byte * buf, byte *pos); //required
void position(const byte *record); //required
- void info(uint); //required
+ int info(uint); //required
int extra(enum ha_extra_function operation);
int reset(void);
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index f727cefc6d0..7fb2de9ca30 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -792,13 +792,13 @@ int ha_tina::rnd_pos(byte * buf, byte *pos)
Currently this table handler doesn't implement most of the fields
really needed. SHOW also makes use of this data
*/
-void ha_tina::info(uint flag)
+int ha_tina::info(uint flag)
{
DBUG_ENTER("ha_tina::info");
/* This is a lie, but you don't want the optimizer to see zero or 1 */
if (!records_is_known && records < 2)
records= 2;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
/*
diff --git a/sql/examples/ha_tina.h b/sql/examples/ha_tina.h
index 97659f99dd9..3bd6405b3f8 100644
--- a/sql/examples/ha_tina.h
+++ b/sql/examples/ha_tina.h
@@ -105,7 +105,7 @@ public:
int rnd_pos(byte * buf, byte *pos);
int rnd_end();
void position(const byte *record);
- void info(uint);
+ int info(uint);
int extra(enum ha_extra_function operation);
int reset(void);
int external_lock(THD *thd, int lock_type);
diff --git a/sql/field.cc b/sql/field.cc
index 61bbea5e615..590246c51b2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -47,6 +47,8 @@ uchar Field_null::null[1]={1};
const char field_separator=',';
#define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320
+#define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128
+#define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128
#define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \
((ulong) ((LL(1) << min(arg, 4) * 8) - LL(1)))
@@ -1399,6 +1401,7 @@ Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
field_charset=charset;
if (charset->state & MY_CS_BINSORT)
flags|=BINARY_FLAG;
+ field_derivation= DERIVATION_IMPLICIT;
}
@@ -1566,10 +1569,11 @@ void Field_null::sql_type(String &res) const
This is an number stored as a pre-space (or pre-zero) string
****************************************************************************/
-void
+int
Field_decimal::reset(void)
{
Field_decimal::store(STRING_WITH_LEN("0"),&my_charset_bin);
+ return 0;
}
void Field_decimal::overflow(bool negative)
@@ -2214,9 +2218,10 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg,
}
-void Field_new_decimal::reset(void)
+int Field_new_decimal::reset(void)
{
store_value(&decimal_zero);
+ return 0;
}
@@ -4769,9 +4774,10 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
{
TIME ltime;
long tmp;
- int error;
+ int error= 0;
+ int warning;
- if (str_to_time(from, len, &ltime, &error))
+ if (str_to_time(from, len, &ltime, &warning))
{
tmp=0L;
error= 2;
@@ -4780,29 +4786,27 @@ int Field_time::store(const char *from,uint len,CHARSET_INFO *cs)
}
else
{
- if (error)
+ if (warning & MYSQL_TIME_WARN_TRUNCATED)
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED,
from, len, MYSQL_TIMESTAMP_TIME, 1);
-
- if (ltime.month)
- ltime.day=0;
- tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
- if (tmp > 8385959)
+ if (warning & MYSQL_TIME_WARN_OUT_OF_RANGE)
{
- tmp=8385959;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
from, len, MYSQL_TIMESTAMP_TIME, !error);
error= 1;
}
+ if (ltime.month)
+ ltime.day=0;
+ tmp=(ltime.day*24L+ltime.hour)*10000L+(ltime.minute*100+ltime.second);
if (error > 1)
error= 2;
}
if (ltime.neg)
tmp= -tmp;
- error |= Field_time::store((longlong) tmp, FALSE);
+ int3store(ptr,tmp);
return error;
}
@@ -4813,7 +4817,7 @@ int Field_time::store_time(TIME *ltime, timestamp_type type)
(ltime->minute * 100 + ltime->second);
if (ltime->neg)
tmp= -tmp;
- return Field_time::store((longlong) tmp);
+ return Field_time::store((longlong) tmp, FALSE);
}
@@ -4821,16 +4825,16 @@ int Field_time::store(double nr)
{
long tmp;
int error= 0;
- if (nr > 8385959.0)
+ if (nr > (double)TIME_MAX_VALUE)
{
- tmp=8385959L;
+ tmp= TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
error= 1;
}
- else if (nr < -8385959.0)
+ else if (nr < (double)-TIME_MAX_VALUE)
{
- tmp= -8385959L;
+ tmp= -TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr, MYSQL_TIMESTAMP_TIME);
error= 1;
@@ -4858,17 +4862,17 @@ int Field_time::store(longlong nr, bool unsigned_val)
{
long tmp;
int error= 0;
- if (nr < (longlong) -8385959L && !unsigned_val)
+ if (nr < (longlong) -TIME_MAX_VALUE && !unsigned_val)
{
- tmp= -8385959L;
+ tmp= -TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr,
MYSQL_TIMESTAMP_TIME, 1);
error= 1;
}
- else if (nr > (longlong) 8385959 || nr < 0 && unsigned_val)
+ else if (nr > (longlong) TIME_MAX_VALUE || nr < 0 && unsigned_val)
{
- tmp=8385959L;
+ tmp= TIME_MAX_VALUE;
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE, nr,
MYSQL_TIMESTAMP_TIME, 1);
@@ -5409,11 +5413,11 @@ int Field_newdate::store_time(TIME *ltime,timestamp_type type)
if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME)
{
tmp=ltime->year*16*32+ltime->month*32+ltime->day;
- if ((my_bool)check_date(ltime, tmp,
- (TIME_FUZZY_DATE |
- (current_thd->variables.sql_mode &
- (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
- MODE_INVALID_DATES))), &error))
+ if (check_date(ltime, tmp != 0,
+ (TIME_FUZZY_DATE |
+ (current_thd->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES))), &error))
{
char buff[12];
String str(buff, sizeof(buff), &my_charset_latin1);
@@ -5633,11 +5637,11 @@ int Field_datetime::store_time(TIME *ltime,timestamp_type type)
{
tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*LL(1000000)+
(ltime->hour*10000L+ltime->minute*100+ltime->second));
- if ((my_bool)check_date(ltime, tmp,
- (TIME_FUZZY_DATE |
- (current_thd->variables.sql_mode &
- (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
- MODE_INVALID_DATES))), &error))
+ if (check_date(ltime, tmp != 0,
+ (TIME_FUZZY_DATE |
+ (current_thd->variables.sql_mode &
+ (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
+ MODE_INVALID_DATES))), &error))
{
char buff[19];
String str(buff, sizeof(buff), &my_charset_latin1);
@@ -5819,37 +5823,148 @@ void Field_datetime::sql_type(String &res) const
** A string may be varchar or binary
****************************************************************************/
+/*
+ Report "not well formed" or "cannot convert" error
+ after storing a character string info a field.
+
+ SYNOPSIS
+ check_string_copy_error()
+ field - Field
+ well_formed_error_pos - where not well formed data was first met
+ cannot_convert_error_pos - where a not-convertable character was first met
+ end - end of the string
+
+ NOTES
+ As of version 5.0 both cases return the same error:
+
+ "Invalid string value: 'xxx' for column 't' at row 1"
+
+ Future versions will possibly introduce a new error message:
+
+ "Cannot convert character string: 'xxx' for column 't' at row 1"
+
+ RETURN
+ FALSE - If errors didn't happen
+ TRUE - If an error happened
+*/
+
+static bool
+check_string_copy_error(Field_str *field,
+ const char *well_formed_error_pos,
+ const char *cannot_convert_error_pos,
+ const char *end)
+{
+ const char *pos, *end_orig;
+ char tmp[64], *t;
+
+ if (!(pos= well_formed_error_pos) &&
+ !(pos= cannot_convert_error_pos))
+ return FALSE;
+
+ end_orig= end;
+ set_if_smaller(end, pos + 6);
+
+ for (t= tmp; pos < end; pos++)
+ {
+ if (((unsigned char) *pos) >= 0x20 &&
+ ((unsigned char) *pos) <= 0x7F)
+ {
+ *t++= *pos;
+ }
+ else
+ {
+ *t++= '\\';
+ *t++= 'x';
+ *t++= _dig_vec_upper[((unsigned char) *pos) >> 4];
+ *t++= _dig_vec_upper[((unsigned char) *pos) & 15];
+ }
+ }
+ if (end_orig > end)
+ {
+ *t++= '.';
+ *t++= '.';
+ *t++= '.';
+ }
+ *t= '\0';
+ push_warning_printf(field->table->in_use,
+ field->table->in_use->abort_on_warning ?
+ MYSQL_ERROR::WARN_LEVEL_ERROR :
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ 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);
+ return TRUE;
+}
+
+
+
+/*
+ Send a truncation warning or a truncation error
+ after storing a too long character string info a field.
+
+ SYNOPSIS
+ report_data_too_long()
+ field - Field
+
+ RETURN
+ N/A
+*/
+
+inline void
+report_data_too_long(Field_str *field)
+{
+ if (field->table->in_use->abort_on_warning)
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
+ else
+ field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+}
+
+
+/*
+ Test if the given string contains important data:
+ not spaces for character string,
+ or any data for binary string.
+
+ SYNOPSIS
+ test_if_important_data()
+ cs Character set
+ str String to test
+ strend String end
+
+ RETURN
+ FALSE - If string does not have important data
+ TRUE - If string has some important data
+*/
+
+static bool
+test_if_important_data(CHARSET_INFO *cs, const char *str, const char *strend)
+{
+ if (cs != &my_charset_bin)
+ str+= cs->cset->scan(cs, str, strend, MY_SEQ_SPACES);
+ return (str < strend);
+}
+
+
/* Copy a string and fill with space */
int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
- int error= 0, well_formed_error;
- uint32 not_used;
- char buff[STRING_BUFFER_USUAL_SIZE];
- String tmpstr(buff,sizeof(buff), &my_charset_bin);
uint copy_length;
+ const char *well_formed_error_pos;
+ const char *cannot_convert_error_pos;
+ const char *from_end_pos;
/* See the comment for Field_long::store(long long) */
DBUG_ASSERT(table->in_use == current_thd);
- /* Convert character set if necessary */
- if (String::needs_conversion(length, cs, field_charset, &not_used))
- {
- uint conv_errors;
- tmpstr.copy(from, length, cs, field_charset, &conv_errors);
- from= tmpstr.ptr();
- length= tmpstr.length();
- if (conv_errors)
- error= 2;
- }
-
- /* Make sure we don't break a multibyte sequence or copy malformed data. */
- copy_length= field_charset->cset->well_formed_len(field_charset,
- from,from+length,
- field_length/
- field_charset->mbmaxlen,
- &well_formed_error);
- memmove(ptr, from, copy_length);
+ copy_length= well_formed_copy_nchars(field_charset,
+ ptr, field_length,
+ cs, from, length,
+ field_length / field_charset->mbmaxlen,
+ &well_formed_error_pos,
+ &cannot_convert_error_pos,
+ &from_end_pos);
/* Append spaces if the string was shorter than the field. */
if (copy_length < field_length)
@@ -5857,32 +5972,23 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
field_length-copy_length,
field_charset->pad_char);
+ if (check_string_copy_error(this, well_formed_error_pos,
+ cannot_convert_error_pos, from + length))
+ return 2;
+
/*
Check if we lost any important data (anything in a binary string,
or any non-space in others).
*/
- if ((copy_length < length) && table->in_use->count_cuted_fields)
+ if ((from_end_pos < from + length) && table->in_use->count_cuted_fields)
{
- if (binary())
- error= 2;
- else
+ if (test_if_important_data(field_charset, from_end_pos, from + length))
{
- const char *end=from+length;
- from+= copy_length;
- from+= field_charset->cset->scan(field_charset, from, end,
- MY_SEQ_SPACES);
- if (from != end)
- error= 2;
+ report_data_too_long(this);
+ return 2;
}
}
- if (error)
- {
- if (table->in_use->abort_on_warning)
- set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
- else
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
- }
- return error;
+ return 0;
}
@@ -5954,19 +6060,49 @@ int Field_longstr::store_decimal(const my_decimal *d)
double Field_string::val_real(void)
{
- int not_used;
- char *end_not_used;
+ int error;
+ char *end;
CHARSET_INFO *cs= charset();
- return my_strntod(cs,ptr,field_length,&end_not_used,&not_used);
+ double result;
+
+ result= my_strntod(cs,ptr,field_length,&end,&error);
+ if (!table->in_use->no_errors &&
+ (error || (field_length != (uint32)(end - ptr) &&
+ !check_if_only_end_space(cs, end, ptr + field_length))))
+ {
+ char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
+ String tmp(buf, sizeof(buf), cs);
+ tmp.copy(ptr, field_length, cs);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE),
+ "DOUBLE", tmp.c_ptr());
+ }
+ return result;
}
longlong Field_string::val_int(void)
{
- int not_used;
- char *end_not_used;
- CHARSET_INFO *cs=charset();
- return my_strntoll(cs,ptr,field_length,10,&end_not_used,&not_used);
+ int error;
+ char *end;
+ CHARSET_INFO *cs= charset();
+ longlong result;
+
+ result= my_strntoll(cs,ptr,field_length,10,&end,&error);
+ if (!table->in_use->no_errors &&
+ (error || (field_length != (uint32)(end - ptr) &&
+ !check_if_only_end_space(cs, end, ptr + field_length))))
+ {
+ char buf[LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE];
+ String tmp(buf, sizeof(buf), cs);
+ tmp.copy(ptr, field_length, cs);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE),
+ "INTEGER", tmp.c_ptr());
+ }
+ return result;
}
@@ -5983,8 +6119,20 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
my_decimal *Field_string::val_decimal(my_decimal *decimal_value)
{
- str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(),
+ int err= str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(),
decimal_value);
+ if (!table->in_use->no_errors && err)
+ {
+ char buf[DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE];
+ CHARSET_INFO *cs= charset();
+ String tmp(buf, sizeof(buf), cs);
+ tmp.copy(ptr, field_length, cs);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER(ER_TRUNCATED_WRONG_VALUE),
+ "DECIMAL", tmp.c_ptr());
+ }
+
return decimal_value;
}
@@ -6215,58 +6363,35 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
- uint32 not_used, copy_length;
- char buff[STRING_BUFFER_USUAL_SIZE];
- String tmpstr(buff,sizeof(buff), &my_charset_bin);
- int error_code= 0, well_formed_error;
- enum MYSQL_ERROR::enum_warning_level level= MYSQL_ERROR::WARN_LEVEL_WARN;
+ uint copy_length;
+ const char *well_formed_error_pos;
+ const char *cannot_convert_error_pos;
+ const char *from_end_pos;
+
+ copy_length= well_formed_copy_nchars(field_charset,
+ ptr + length_bytes, field_length,
+ cs, from, length,
+ field_length / field_charset->mbmaxlen,
+ &well_formed_error_pos,
+ &cannot_convert_error_pos,
+ &from_end_pos);
- /* Convert character set if necessary */
- if (String::needs_conversion(length, cs, field_charset, &not_used))
- {
- uint conv_errors;
- tmpstr.copy(from, length, cs, field_charset, &conv_errors);
- from= tmpstr.ptr();
- length= tmpstr.length();
- if (conv_errors)
- error_code= WARN_DATA_TRUNCATED;
- }
- /*
- Make sure we don't break a multibyte sequence
- as well as don't copy a malformed data.
- */
- copy_length= field_charset->cset->well_formed_len(field_charset,
- from,from+length,
- field_length/
- field_charset->mbmaxlen,
- &well_formed_error);
- memmove(ptr + length_bytes, from, copy_length);
if (length_bytes == 1)
*ptr= (uchar) copy_length;
else
int2store(ptr, copy_length);
+ if (check_string_copy_error(this, well_formed_error_pos,
+ cannot_convert_error_pos, from + length))
+ return 2;
+
// Check if we lost something other than just trailing spaces
- if ((copy_length < length) && table->in_use->count_cuted_fields &&
- !error_code)
+ if ((from_end_pos < from + length) && table->in_use->count_cuted_fields)
{
- if (!binary())
- {
- const char *end= from + length;
- from+= copy_length;
- from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES);
- /* If we lost only spaces then produce a NOTE, not a WARNING */
- if (from == end)
- level= MYSQL_ERROR::WARN_LEVEL_NOTE;
- }
- error_code= WARN_DATA_TRUNCATED;
- }
- if (error_code)
- {
- if (level == MYSQL_ERROR::WARN_LEVEL_WARN &&
- table->in_use->abort_on_warning)
- error_code= ER_DATA_TOO_LONG;
- set_warning(level, error_code, 1);
+ if (test_if_important_data(field_charset, from_end_pos, from + length))
+ report_data_too_long(this);
+ else /* If we lost only spaces then produce a NOTE, not a WARNING */
+ set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
return 2;
}
return 0;
@@ -6848,68 +6973,70 @@ void Field_blob::put_length(char *pos, uint32 length)
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
{
- int error= 0, well_formed_error;
+ uint copy_length, new_length;
+ const char *well_formed_error_pos;
+ const char *cannot_convert_error_pos;
+ const char *from_end_pos, *tmp;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmpstr(buff,sizeof(buff), &my_charset_bin);
+
if (!length)
{
bzero(ptr,Field_blob::pack_length());
+ return 0;
}
- else
- {
- bool was_conversion;
- char buff[STRING_BUFFER_USUAL_SIZE];
- String tmpstr(buff,sizeof(buff), &my_charset_bin);
- uint copy_length;
- uint32 not_used;
- /* Convert character set if necessary */
- if ((was_conversion= String::needs_conversion(length, cs, field_charset,
- &not_used)))
- {
- uint conv_errors;
- if (tmpstr.copy(from, length, cs, field_charset, &conv_errors))
- {
- /* Fatal OOM error */
- bzero(ptr,Field_blob::pack_length());
- return -1;
- }
- from= tmpstr.ptr();
- length= tmpstr.length();
- if (conv_errors)
- error= 2;
- }
-
- copy_length= max_data_length();
- /*
- copy_length is OK as last argument to well_formed_len as this is never
- used to limit the length of the data. The cut of long data is done with
- the 'min()' call below.
- */
- copy_length= field_charset->cset->well_formed_len(field_charset,
- from,from +
- min(length, copy_length),
- copy_length,
- &well_formed_error);
- if (copy_length < length)
- error= 2;
- Field_blob::store_length(copy_length);
- if (was_conversion || table->copy_blobs || copy_length <= MAX_FIELD_WIDTH)
- { // Must make a copy
- if (from != value.ptr()) // For valgrind
- {
- value.copy(from,copy_length,charset());
- from=value.ptr();
- }
+ if (from == value.ptr())
+ {
+ uint32 dummy_offset;
+ if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
+ {
+ Field_blob::store_length(length);
+ bmove(ptr+packlength,(char*) &from,sizeof(char*));
+ return 0;
}
- bmove(ptr+packlength,(char*) &from,sizeof(char*));
+ if (tmpstr.copy(from, length, cs))
+ goto oom_error;
+ from= tmpstr.ptr();
}
- if (error)
+
+ new_length= min(max_data_length(), field_charset->mbmaxlen * length);
+ if (value.alloc(new_length))
+ goto oom_error;
+
+ /*
+ "length" is OK as "nchars" argument to well_formed_copy_nchars as this
+ is never used to limit the length of the data. The cut of long data
+ is done with the new_length value.
+ */
+ copy_length= well_formed_copy_nchars(field_charset,
+ (char*) value.ptr(), new_length,
+ cs, from, length,
+ length,
+ &well_formed_error_pos,
+ &cannot_convert_error_pos,
+ &from_end_pos);
+
+ Field_blob::store_length(copy_length);
+ tmp= value.ptr();
+ bmove(ptr+packlength,(char*) &tmp,sizeof(char*));
+
+ if (check_string_copy_error(this, well_formed_error_pos,
+ cannot_convert_error_pos, from + length))
+ return 2;
+
+ if (copy_length < length)
{
- if (table->in_use->abort_on_warning)
- set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
- else
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
+ report_data_too_long(this);
+ return 2;
}
+
return 0;
+
+oom_error:
+ /* Fatal OOM error */
+ bzero(ptr,Field_blob::pack_length());
+ return -1;
}
@@ -7995,7 +8122,7 @@ int Field_bit::store_decimal(const my_decimal *val)
{
int err= 0;
longlong i= convert_decimal2longlong(val, 1, &err);
- return test(err | store(i));
+ return test(err | store(i, TRUE));
}
@@ -8148,7 +8275,7 @@ Field_bit_as_char::Field_bit_as_char(char *ptr_arg, uint32 len_arg,
int Field_bit_as_char::store(const char *from, uint length, CHARSET_INFO *cs)
{
int delta;
- uchar bits= field_length & 7;
+ uchar bits= (uchar) (field_length & 7);
for (; length && !*from; from++, length--); // skip left 0's
delta= bytes_in_rec - length;
diff --git a/sql/field.h b/sql/field.h
index 8b22424265d..279917d7447 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -150,7 +150,7 @@ public:
*/
virtual uint32 data_length(const char *from) { return pack_length(); }
virtual uint32 sort_length() const { return pack_length(); }
- virtual void reset(void) { bzero(ptr,pack_length()); }
+ virtual int reset(void) { bzero(ptr,pack_length()); return 0; }
virtual void reset_fields() {}
virtual void set_default()
{
@@ -302,6 +302,9 @@ public:
virtual CHARSET_INFO *sort_charset(void) const { return charset(); }
virtual bool has_charset(void) const { return FALSE; }
virtual void set_charset(CHARSET_INFO *charset) { }
+ virtual enum Derivation derivation(void) const
+ { return DERIVATION_IMPLICIT; }
+ virtual void set_derivation(enum Derivation derivation) { }
bool set_warning(MYSQL_ERROR::enum_warning_level, unsigned int code,
int cuted_increment);
bool check_int(const char *str, int length, const char *int_end,
@@ -373,6 +376,7 @@ public:
class Field_str :public Field {
protected:
CHARSET_INFO *field_charset;
+ enum Derivation field_derivation;
public:
Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg,
@@ -387,6 +391,9 @@ public:
uint size_of() const { return sizeof(*this); }
CHARSET_INFO *charset(void) const { return field_charset; }
void set_charset(CHARSET_INFO *charset) { field_charset=charset; }
+ enum Derivation derivation(void) const { return field_derivation; }
+ virtual void set_derivation(enum Derivation derivation_arg)
+ { field_derivation= derivation_arg; }
bool binary() const { return field_charset == &my_charset_bin; }
uint32 max_length() { return field_length; }
friend class create_field;
@@ -443,10 +450,10 @@ public:
enum_field_types type() const { return FIELD_TYPE_DECIMAL;}
enum ha_base_keytype key_type() const
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
- void reset(void);
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
+ int reset(void);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -483,7 +490,7 @@ public:
enum_field_types type() const { return FIELD_TYPE_NEWDECIMAL;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; }
Item_result result_type () const { return DECIMAL_RESULT; }
- void reset(void);
+ int reset(void);
bool store_value(const my_decimal *decimal_value);
void set_value_on_overflow(my_decimal *decimal_value, bool sign);
int store(const char *to, uint length, CHARSET_INFO *charset);
@@ -520,10 +527,10 @@ public:
enum_field_types type() const { return FIELD_TYPE_TINY;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_BINARY : HA_KEYTYPE_INT8; }
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
- void reset(void) { ptr[0]=0; }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int reset(void) { ptr[0]=0; return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -556,10 +563,10 @@ public:
enum_field_types type() const { return FIELD_TYPE_SHORT;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_USHORT_INT : HA_KEYTYPE_SHORT_INT;}
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
- void reset(void) { ptr[0]=ptr[1]=0; }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int reset(void) { ptr[0]=ptr[1]=0; return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -587,10 +594,10 @@ public:
enum_field_types type() const { return FIELD_TYPE_INT24;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_UINT24 : HA_KEYTYPE_INT24; }
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
int store(longlong nr, bool unsigned_val);
- void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
+ int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -623,10 +630,10 @@ public:
enum_field_types type() const { return FIELD_TYPE_LONG;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONG_INT : HA_KEYTYPE_LONG_INT; }
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
- void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
double val_real(void);
longlong val_int(void);
bool send_binary(Protocol *protocol);
@@ -661,10 +668,14 @@ public:
enum_field_types type() const { return FIELD_TYPE_LONGLONG;}
enum ha_base_keytype key_type() const
{ return unsigned_flag ? HA_KEYTYPE_ULONGLONG : HA_KEYTYPE_LONGLONG; }
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
- void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int reset(void)
+ {
+ ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0;
+ return 0;
+ }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -697,10 +708,10 @@ public:
{}
enum_field_types type() const { return FIELD_TYPE_FLOAT;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_FLOAT; }
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
- void reset(void) { bzero(ptr,sizeof(float)); }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int reset(void) { bzero(ptr,sizeof(float)); return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -734,7 +745,7 @@ public:
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr, bool unsigned_val);
- void reset(void) { bzero(ptr,sizeof(double)); }
+ int reset(void) { bzero(ptr,sizeof(double)); return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -761,10 +772,10 @@ public:
enum_field_types type() const { return FIELD_TYPE_NULL;}
int store(const char *to, uint length, CHARSET_INFO *cs)
{ null[0]=1; return 0; }
- int store(double nr) { null[0]=1; return 0; }
- int store(longlong nr, bool unsigned_val) { null[0]=1; return 0; }
- int store_decimal(const my_decimal *d) { null[0]=1; return 0; }
- void reset(void) {}
+ int store(double nr) { null[0]=1; return 0; }
+ int store(longlong nr, bool unsigned_val) { null[0]=1; return 0; }
+ int store_decimal(const my_decimal *d) { null[0]=1; return 0; }
+ int reset(void) { return 0; }
double val_real(void) { return 0.0;}
longlong val_int(void) { return 0;}
my_decimal *val_decimal(my_decimal *) { return 0; }
@@ -794,7 +805,7 @@ public:
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr, bool unsigned_val);
- void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
+ int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -870,10 +881,10 @@ public:
enum_field_types type() const { return FIELD_TYPE_DATE;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
enum Item_result cmp_type () const { return INT_RESULT; }
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
- void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -902,7 +913,7 @@ public:
int store(double nr);
int store(longlong nr, bool unsigned_val);
int store_time(TIME *ltime, timestamp_type type);
- void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
+ int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -934,10 +945,10 @@ public:
enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; }
enum Item_result cmp_type () const { return INT_RESULT; }
int store_time(TIME *ltime, timestamp_type type);
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(double nr);
- int store(longlong nr, bool unsigned_val);
- void reset(void) { ptr[0]=ptr[1]=ptr[2]=0; }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(double nr);
+ int store(longlong nr, bool unsigned_val);
+ int reset(void) { ptr[0]=ptr[1]=ptr[2]=0; return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -975,7 +986,11 @@ public:
int store(double nr);
int store(longlong nr, bool unsigned_val);
int store_time(TIME *ltime, timestamp_type type);
- void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0; }
+ int reset(void)
+ {
+ ptr[0]=ptr[1]=ptr[2]=ptr[3]=ptr[4]=ptr[5]=ptr[6]=ptr[7]=0;
+ return 0;
+ }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -1018,9 +1033,13 @@ public:
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
bool zero_pack() const { return 0; }
- void reset(void) { charset()->cset->fill(charset(),ptr,field_length,' '); }
- int store(const char *to,uint length,CHARSET_INFO *charset);
- int store(longlong nr, bool unsigned_val);
+ int reset(void)
+ {
+ charset()->cset->fill(charset(),ptr,field_length,' ');
+ return 0;
+ }
+ int store(const char *to,uint length,CHARSET_INFO *charset);
+ int store(longlong nr, bool unsigned_val);
int store(double nr) { return Field_str::store(nr); } /* QQ: To be deleted */
double val_real(void);
longlong val_int(void);
@@ -1075,7 +1094,7 @@ public:
enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
enum ha_base_keytype key_type() const;
bool zero_pack() const { return 0; }
- void reset(void) { bzero(ptr,field_length+length_bytes); }
+ int reset(void) { bzero(ptr,field_length+length_bytes); return 0; }
uint32 pack_length() const { return (uint32) field_length+length_bytes; }
uint32 key_length() const { return (uint32) field_length; }
uint32 sort_length() const
@@ -1176,7 +1195,7 @@ public:
{
return (uint32) (((ulonglong) 1 << (packlength*8)) -1);
}
- void reset(void) { bzero(ptr, packlength+sizeof(char*)); }
+ int reset(void) { bzero(ptr, packlength+sizeof(char*)); return 0; }
void reset_fields() { bzero((char*) &value,sizeof(value)); }
void store_length(uint32 number);
inline uint32 get_length(uint row_offset=0)
@@ -1257,6 +1276,7 @@ public:
int store_decimal(const my_decimal *);
void get_key_image(char *buff,uint length,imagetype type);
uint size_of() const { return sizeof(*this); }
+ int reset(void) { return !maybe_null(); }
};
#endif /*HAVE_SPATIAL*/
@@ -1285,7 +1305,7 @@ public:
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr, bool unsigned_val);
- void reset() { bzero(ptr,packlength); }
+ int reset() { bzero(ptr,packlength); return 0; }
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
@@ -1346,7 +1366,7 @@ public:
uint32 max_length() { return field_length; }
uint size_of() const { return sizeof(*this); }
Item_result result_type () const { return INT_RESULT; }
- void reset(void) { bzero(ptr, bytes_in_rec); }
+ int reset(void) { bzero(ptr, bytes_in_rec); return 0; }
int store(const char *to, uint length, CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr, bool unsigned_val);
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 12b17846fe4..38c941b30f4 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -309,7 +309,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
DBUG_POP(); /* Ok to DBUG */
#endif
memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
- DBUG_PRINT("exit",("records: %ld",records));
+ DBUG_PRINT("exit",("records: %ld", (long) records));
DBUG_RETURN(error ? HA_POS_ERROR : records);
} /* filesort */
@@ -974,7 +974,7 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
Put all room used by freed buffer to use in adjacent buffer. Note, that
we can't simply distribute memory evenly between all buffers, because
new areas must not overlap with old ones.
- SYNOPSYS
+ SYNOPSIS
reuse_freed_buff()
queue IN list of non-empty buffers, without freed buffer
reuse IN empty buffer
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 5a8bd48d699..2674b2e65f7 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -206,9 +206,10 @@ void insert_symbols()
void insert_sql_functions()
{
- size_t i= 0;
+ int i= 0;
SYMBOL *cur;
- for (cur= sql_functions; i<array_elements(sql_functions); cur++, i++){
+ for (cur= sql_functions; i < (int) array_elements(sql_functions); cur++, i++)
+ {
hash_lex_struct *root=
get_hash_struct_by_len(&root_by_len,cur->length,&max_len);
insert_into_hash(root,cur->name,0,-i-1,1);
diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc
index bc3c819c4ed..e3f979952e0 100644
--- a/sql/ha_archive.cc
+++ b/sql/ha_archive.cc
@@ -211,7 +211,7 @@ bool archive_db_init()
max_zfile_size= INT_MAX16;
break;
case 8:
- max_zfile_size= LONGLONG_MAX;
+ max_zfile_size= (z_off_t) LONGLONG_MAX;
break;
case 4:
default:
@@ -327,8 +327,8 @@ int ha_archive::read_meta_file(File meta_file, ha_rows *rows)
DBUG_PRINT("ha_archive::read_meta_file", ("Check %d", (uint)meta_buffer[0]));
DBUG_PRINT("ha_archive::read_meta_file", ("Version %d", (uint)meta_buffer[1]));
- DBUG_PRINT("ha_archive::read_meta_file", ("Rows %lld", *rows));
- DBUG_PRINT("ha_archive::read_meta_file", ("Checkpoint %lld", check_point));
+ DBUG_PRINT("ha_archive::read_meta_file", ("Rows %lu", (ulong) *rows));
+ DBUG_PRINT("ha_archive::read_meta_file", ("Checkpoint %lu", (ulong) check_point));
DBUG_PRINT("ha_archive::read_meta_file", ("Dirty %d", (int)meta_buffer[18]));
if ((meta_buffer[0] != (uchar)ARCHIVE_CHECK_HEADER) ||
@@ -359,8 +359,8 @@ int ha_archive::write_meta_file(File meta_file, ha_rows rows, bool dirty)
*(meta_buffer + 18)= (uchar)dirty;
DBUG_PRINT("ha_archive::write_meta_file", ("Check %d", (uint)ARCHIVE_CHECK_HEADER));
DBUG_PRINT("ha_archive::write_meta_file", ("Version %d", (uint)ARCHIVE_VERSION));
- DBUG_PRINT("ha_archive::write_meta_file", ("Rows %llu", (ulonglong)rows));
- DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %llu", check_point));
+ DBUG_PRINT("ha_archive::write_meta_file", ("Rows %lu", (ulong)rows));
+ DBUG_PRINT("ha_archive::write_meta_file", ("Checkpoint %lu", (ulong) check_point));
DBUG_PRINT("ha_archive::write_meta_file", ("Dirty %d", (uint)dirty));
VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
@@ -495,7 +495,7 @@ int ha_archive::init_archive_writer()
}
share->archive_write_open= TRUE;
info(HA_STATUS_TIME);
- share->approx_file_size= data_file_length;
+ share->approx_file_size= (ulong) data_file_length;
DBUG_RETURN(0);
}
@@ -676,13 +676,14 @@ int ha_archive::real_write_row(byte *buf, gzFile writer)
if (share->approx_file_size > max_zfile_size - total_row_length)
{
info(HA_STATUS_TIME);
- share->approx_file_size= data_file_length;
+ share->approx_file_size= (ulong) data_file_length;
if (share->approx_file_size > max_zfile_size - total_row_length)
DBUG_RETURN(HA_ERR_RECORD_FILE_FULL);
}
share->approx_file_size+= total_row_length;
written= gzwrite(writer, buf, table->s->reclength);
- DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength));
+ DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %lu", (int) written,
+ table->s->reclength));
if (!delayed_insert || !bulk_insert)
share->dirty= TRUE;
@@ -782,7 +783,7 @@ int ha_archive::rnd_init(bool scan)
if (scan)
{
scan_rows= share->rows_recorded;
- DBUG_PRINT("info", ("archive will retrieve %llu rows", scan_rows));
+ DBUG_PRINT("info", ("archive will retrieve %lu rows", (ulong) scan_rows));
records= 0;
/*
@@ -822,7 +823,8 @@ int ha_archive::get_row(gzFile file_to_read, byte *buf)
DBUG_ENTER("ha_archive::get_row");
read= gzread(file_to_read, buf, table->s->reclength);
- DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %d", read, table->s->reclength));
+ DBUG_PRINT("ha_archive::get_row", ("Read %d bytes expected %lu", (int) read,
+ table->s->reclength));
if (read == Z_STREAM_ERROR)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
@@ -1017,7 +1019,8 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
share->rows_recorded++;
}
}
- DBUG_PRINT("info", ("recovered %llu archive rows", share->rows_recorded));
+ DBUG_PRINT("info", ("recovered %lu archive rows",
+ (ulong) share->rows_recorded));
my_free((char*)buf, MYF(0));
if (rc && rc != HA_ERR_END_OF_FILE)
@@ -1115,7 +1118,7 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
/*
Hints for optimizer, see ha_tina for more information
*/
-void ha_archive::info(uint flag)
+int ha_archive::info(uint flag)
{
DBUG_ENTER("ha_archive::info");
/*
@@ -1140,7 +1143,7 @@ void ha_archive::info(uint flag)
delete_length= 0;
index_file_length=0;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
diff --git a/sql/ha_archive.h b/sql/ha_archive.h
index 564b9f03bf5..6c6b587dd2a 100644
--- a/sql/ha_archive.h
+++ b/sql/ha_archive.h
@@ -94,7 +94,7 @@ public:
int read_data_header(gzFile file_to_read);
int write_data_header(gzFile file_to_write);
void position(const byte *record);
- void info(uint);
+ int info(uint);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
int repair(THD* thd, HA_CHECK_OPT* check_opt);
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 4209bc93d30..ac3625157cf 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -1756,7 +1756,7 @@ void ha_berkeley::position(const byte *record)
}
-void ha_berkeley::info(uint flag)
+int ha_berkeley::info(uint flag)
{
DBUG_ENTER("ha_berkeley::info");
if (flag & HA_STATUS_VARIABLE)
@@ -1776,7 +1776,7 @@ void ha_berkeley::info(uint flag)
/* Don't return key if we got an error for the internal primary key */
if (flag & HA_STATUS_ERRKEY && last_dup_key < table->s->keys)
errkey= last_dup_key;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 16e4db59c10..2ff0a7cf044 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -123,7 +123,7 @@ class ha_berkeley: public handler
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
- void info(uint);
+ int info(uint);
int extra(enum ha_extra_function operation);
int reset(void);
int external_lock(THD *thd, int lock_type);
diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc
index 2505919af39..6aabcb4e7cd 100644
--- a/sql/ha_blackhole.cc
+++ b/sql/ha_blackhole.cc
@@ -138,7 +138,7 @@ void ha_blackhole::position(const byte *record)
}
-void ha_blackhole::info(uint flag)
+int ha_blackhole::info(uint flag)
{
DBUG_ENTER("ha_blackhole::info");
@@ -152,7 +152,7 @@ void ha_blackhole::info(uint flag)
delete_length= 0;
if (flag & HA_STATUS_AUTO)
auto_increment_value= 1;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
int ha_blackhole::external_lock(THD *thd, int lock_type)
diff --git a/sql/ha_blackhole.h b/sql/ha_blackhole.h
index 7238147a06a..05cb1c66b39 100644
--- a/sql/ha_blackhole.h
+++ b/sql/ha_blackhole.h
@@ -76,7 +76,7 @@ public:
int index_first(byte * buf);
int index_last(byte * buf);
void position(const byte *record);
- void info(uint flag);
+ int info(uint flag);
int external_lock(THD *thd, int lock_type);
uint lock_count(void) const;
int create(const char *name, TABLE *table_arg,
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index 7919519cdce..9abfcdc61c6 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -557,8 +557,8 @@ static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num)
if (share->scheme)
{
DBUG_PRINT("info",
- ("error: parse_url. Returning error code %d \
- freeing share->scheme %lx", error_num, share->scheme));
+ ("error: parse_url. Returning error code %d freeing share->scheme 0x%lx",
+ error_num, (long) share->scheme));
my_free((gptr) share->scheme, MYF(0));
share->scheme= 0;
}
@@ -624,7 +624,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
MYF(0));
share->connect_string_length= table->s->connect_string.length;
- DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme));
+ DBUG_PRINT("info",("parse_url alloced share->scheme 0x%lx", (long) share->scheme));
/*
remove addition of null terminator and store length
@@ -1249,7 +1249,6 @@ bool ha_federated::create_where_from_key(String *to,
if (tmp.append(FEDERATED_CLOSEPAREN))
DBUG_RETURN(1);
-next_loop:
if (store_length >= length)
break;
DBUG_PRINT("info", ("remainder %d", remainder));
@@ -1664,7 +1663,7 @@ void ha_federated::update_auto_increment(void)
DBUG_ENTER("ha_federated::update_auto_increment");
thd->insert_id(mysql->last_used_con->insert_id);
- DBUG_PRINT("info",("last_insert_id %d", auto_increment_value));
+ DBUG_PRINT("info",("last_insert_id: %ld", (long) auto_increment_value));
DBUG_VOID_RETURN;
}
@@ -1914,11 +1913,11 @@ int ha_federated::delete_row(const byte *buf)
{
DBUG_RETURN(stash_remote_error());
}
- deleted+= mysql->affected_rows;
- records-= mysql->affected_rows;
+ deleted+= (ha_rows) mysql->affected_rows;
+ records-= (ha_rows) mysql->affected_rows;
DBUG_PRINT("info",
- ("rows deleted %d rows deleted for all time %d",
- int(mysql->affected_rows), deleted));
+ ("rows deleted %ld rows deleted for all time %ld",
+ (long) mysql->affected_rows, (long) deleted));
DBUG_RETURN(0);
}
@@ -2270,7 +2269,6 @@ int ha_federated::rnd_next(byte *buf)
int ha_federated::read_next(byte *buf, MYSQL_RES *result)
{
int retval;
- my_ulonglong num_rows;
MYSQL_ROW row;
DBUG_ENTER("ha_federated::read_next");
@@ -2385,7 +2383,7 @@ int ha_federated::rnd_pos(byte *buf, byte *pos)
*/
-void ha_federated::info(uint flag)
+int ha_federated::info(uint flag)
{
char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char status_buf[FEDERATED_QUERY_BUFFER_SIZE];
@@ -2463,7 +2461,7 @@ void ha_federated::info(uint flag)
if (result)
mysql_free_result(result);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
error:
if (result)
@@ -2472,7 +2470,7 @@ error:
my_sprintf(error_buffer, (error_buffer, ": %d : %s",
mysql_errno(mysql), mysql_error(mysql)));
my_error(error_code, MYF(0), error_buffer);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(error_code);
}
diff --git a/sql/ha_federated.h b/sql/ha_federated.h
index 61f5af686a3..c04ce09e75d 100644
--- a/sql/ha_federated.h
+++ b/sql/ha_federated.h
@@ -232,8 +232,7 @@ public:
*/
double scan_time()
{
- DBUG_PRINT("info",
- ("records %d", records));
+ DBUG_PRINT("info", ("records %ld", (long) records));
return (double)(records*1000);
}
/*
@@ -285,7 +284,7 @@ public:
int rnd_next(byte *buf); //required
int rnd_pos(byte *buf, byte *pos); //required
void position(const byte *record); //required
- void info(uint); //required
+ int info(uint); //required
void update_auto_increment(void);
int repair(THD* thd, HA_CHECK_OPT* check_opt);
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 3aaa0287098..3cf7593bd8a 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -332,7 +332,7 @@ void ha_heap::position(const byte *record)
*(HEAP_PTR*) ref= heap_position(file); // Ref is aligned
}
-void ha_heap::info(uint flag)
+int ha_heap::info(uint flag)
{
HEAPINFO info;
(void) heap_info(file,&info,flag);
@@ -354,6 +354,7 @@ void ha_heap::info(uint flag)
*/
if (key_stat_version != file->s->key_stat_version)
update_key_stats();
+ return 0;
}
int ha_heap::extra(enum ha_extra_function operation)
@@ -630,7 +631,7 @@ int ha_heap::create(const char *name, TABLE *table_arg,
}
mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*));
max_rows = (ha_rows) (table->in_use->variables.max_heap_table_size /
- mem_per_row);
+ (ulonglong) mem_per_row);
if (table_arg->found_next_number_field)
{
keydef[share->next_number_index].flag|= HA_AUTO_KEY;
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index e2816abf0b6..a48428e9289 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -85,7 +85,7 @@ public:
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
- void info(uint);
+ int info(uint);
int extra(enum ha_extra_function operation);
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index e99d93784c9..5548cb66e7f 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -2739,7 +2739,6 @@ ha_innobase::store_key_val_for_row(
CHARSET_INFO* cs;
ulint key_len;
- ulint len;
ulint true_len;
int error=0;
ulint blob_len;
@@ -4215,7 +4214,7 @@ ha_innobase::rnd_pos(
}
if (error) {
- DBUG_PRINT("error", ("Got error: %ld", error));
+ DBUG_PRINT("error", ("Got error: %d", error));
DBUG_RETURN(error);
}
@@ -4225,7 +4224,7 @@ ha_innobase::rnd_pos(
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
if (error) {
- DBUG_PRINT("error", ("Got error: %ld", error));
+ DBUG_PRINT("error", ("Got error: %d", error));
}
change_active_index(keynr);
@@ -5258,7 +5257,7 @@ ha_innobase::read_time(
Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. */
-void
+int
ha_innobase::info(
/*==============*/
uint flag) /* in: what information MySQL requests */
@@ -5281,7 +5280,7 @@ ha_innobase::info(
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
- DBUG_VOID_RETURN;
+ DBUG_RETURN(HA_ERR_CRASHED);
}
/* We do not know if MySQL can call this function before calling
@@ -5476,7 +5475,7 @@ ha_innobase::info(
prebuilt->trx->op_info = (char*)"";
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
/**************************************************************************
@@ -6563,7 +6562,8 @@ ha_innobase::store_lock(
&& lock_type != TL_IGNORE)) {
/* The OR cases above are in this order:
- 1) MySQL is doing LOCK TABLES ... READ LOCAL, or
+ 1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
+ are processing a stored procedure or function, or
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
3) this is a SELECT ... IN SHARE MODE, or
4) we are doing a complex SQL statement like
@@ -6625,7 +6625,8 @@ ha_innobase::store_lock(
single transaction stored procedure call deterministic
(if it does not use a consistent read). */
- if (lock_type == TL_READ && thd->in_lock_tables) {
+ if (lock_type == TL_READ
+ && thd->lex->sql_command == SQLCOM_LOCK_TABLES) {
/* We come here if MySQL is processing LOCK TABLES
... READ LOCAL. MyISAM under that table lock type
reads the table as it was at the time the lock was
@@ -6684,8 +6685,7 @@ ha_innobase::store_lock(
(MySQL does have thd->in_lock_tables TRUE there). */
if (lock_type == TL_READ_NO_INSERT
- && (!thd->in_lock_tables
- || thd->lex->sql_command == SQLCOM_CALL)) {
+ && thd->lex->sql_command != SQLCOM_LOCK_TABLES) {
lock_type = TL_READ;
}
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 5dd6a92c4b0..95d7a9437ad 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -140,7 +140,7 @@ class ha_innobase: public handler
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
- void info(uint);
+ int info(uint);
int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int optimize(THD* thd,HA_CHECK_OPT* check_opt);
int discard_or_import_tablespace(my_bool discard);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index fc3bd3d3b08..19ec1b29da3 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -1299,7 +1299,7 @@ void ha_myisam::position(const byte* record)
my_store_ptr(ref, ref_length, position);
}
-void ha_myisam::info(uint flag)
+int ha_myisam::info(uint flag)
{
MI_ISAMINFO info;
char name_buff[FN_REFLEN];
@@ -1358,6 +1358,8 @@ void ha_myisam::info(uint flag)
update_time = info.update_time;
if (flag & HA_STATUS_AUTO)
auto_increment_value= info.auto_increment;
+
+ return 0;
}
@@ -1555,7 +1557,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
}
}
DBUG_PRINT("loop",("found: 0x%lx recpos: %d minpos: %d length: %d",
- found,recpos,minpos,length));
+ (long) found, recpos, minpos, length));
if (recpos != minpos)
{ // Reserved space (Null bits?)
bzero((char*) recinfo_pos,sizeof(*recinfo_pos));
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index 950817d42bd..f5c45333f50 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -95,7 +95,7 @@ class ha_myisam: public handler
int rnd_pos(byte * buf, byte *pos);
int restart_rnd_next(byte *buf, byte *pos);
void position(const byte *record);
- void info(uint);
+ int info(uint);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
int external_lock(THD *thd, int lock_type);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index a4f23cd3cf0..5e613a63303 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -108,7 +108,7 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
if (table->s->reclength != mean_rec_length && mean_rec_length)
{
- DBUG_PRINT("error",("reclength: %d mean_rec_length: %d",
+ DBUG_PRINT("error",("reclength: %lu mean_rec_length: %lu",
table->s->reclength, mean_rec_length));
goto err;
}
@@ -275,7 +275,7 @@ ha_rows ha_myisammrg::records_in_range(uint inx, key_range *min_key,
}
-void ha_myisammrg::info(uint flag)
+int ha_myisammrg::info(uint flag)
{
MYMERGE_INFO info;
(void) myrg_status(file,&info,flag);
@@ -343,6 +343,7 @@ void ha_myisammrg::info(uint flag)
min(file->keys, table->s->key_parts));
}
}
+ return 0;
}
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index a73f368c51d..e20214fa84f 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -72,7 +72,7 @@ class ha_myisammrg: public handler
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
- void info(uint);
+ int info(uint);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
int external_lock(THD *thd, int lock_type);
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 5448b08b74f..2ef16ddacbf 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -114,7 +114,7 @@ static int packfrm(const void *data, uint len, const void **pack_data, uint *pac
static int unpackfrm(const void **data, uint *len,
const void* pack_data);
-static int ndb_get_table_statistics(Ndb*, const char *,
+static int ndb_get_table_statistics(ha_ndbcluster*, bool, Ndb*, const char *,
struct Ndb_statistics *);
// Util thread variables
@@ -147,7 +147,7 @@ static long ndb_cluster_node_id= 0;
static const char * ndb_connected_host= 0;
static long ndb_connected_port= 0;
static long ndb_number_of_replicas= 0;
-static long ndb_number_of_storage_nodes= 0;
+static long ndb_number_of_data_nodes= 0;
static int update_status_variables(Ndb_cluster_connection *c)
{
@@ -155,7 +155,7 @@ static int update_status_variables(Ndb_cluster_connection *c)
ndb_connected_port= c->get_connected_port();
ndb_connected_host= c->get_connected_host();
ndb_number_of_replicas= 0;
- ndb_number_of_storage_nodes= c->no_db_nodes();
+ ndb_number_of_data_nodes= c->no_db_nodes();
return 0;
}
@@ -164,7 +164,7 @@ struct show_var_st ndb_status_variables[]= {
{"config_from_host", (char*) &ndb_connected_host, SHOW_CHAR_PTR},
{"config_from_port", (char*) &ndb_connected_port, SHOW_LONG},
// {"number_of_replicas", (char*) &ndb_number_of_replicas, SHOW_LONG},
- {"number_of_storage_nodes",(char*) &ndb_number_of_storage_nodes, SHOW_LONG},
+ {"number_of_data_nodes",(char*) &ndb_number_of_data_nodes, SHOW_LONG},
{NullS, NullS, SHOW_LONG}
};
@@ -355,11 +355,13 @@ void ha_ndbcluster::set_rec_per_key()
DBUG_VOID_RETURN;
}
-void ha_ndbcluster::records_update()
+int ha_ndbcluster::records_update()
{
if (m_ha_not_exact_count)
- return;
+ return 0;
DBUG_ENTER("ha_ndbcluster::records_update");
+ int result= 0;
+
struct Ndb_local_table_statistics *info=
(struct Ndb_local_table_statistics *)m_table_info;
DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
@@ -370,7 +372,9 @@ void ha_ndbcluster::records_update()
Ndb *ndb= get_ndb();
struct Ndb_statistics stat;
ndb->setDatabaseName(m_dbname);
- if (ndb_get_table_statistics(ndb, m_tabname, &stat) == 0){
+ result= ndb_get_table_statistics(this, true, ndb, m_tabname, &stat);
+ if (result == 0)
+ {
mean_rec_length= stat.row_size;
data_file_length= stat.fragment_memory;
info->records= stat.row_count;
@@ -381,8 +385,9 @@ void ha_ndbcluster::records_update()
if (get_thd_ndb(thd)->error)
info->no_uncommitted_rows_count= 0;
}
- records= info->records+ info->no_uncommitted_rows_count;
- DBUG_VOID_RETURN;
+ if(result==0)
+ records= info->records+ info->no_uncommitted_rows_count;
+ DBUG_RETURN(result);
}
void ha_ndbcluster::no_uncommitted_rows_execute_failure()
@@ -551,7 +556,14 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans)
if (res == HA_ERR_FOUND_DUPP_KEY)
{
if (m_rows_to_insert == 1)
- m_dupkey= table->s->primary_key;
+ {
+ /*
+ We can only distinguish between primary and non-primary
+ violations here, so we need to return MAX_KEY for non-primary
+ to signal that key is unknown
+ */
+ m_dupkey= err.code == 630 ? table->s->primary_key : MAX_KEY;
+ }
else
{
/* We are batching inserts, offending key is not available */
@@ -810,8 +822,8 @@ int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob,
{
char *buf= m_blobs_buffer + offset;
uint32 len= 0xffffffff; // Max uint32
- DBUG_PRINT("value", ("read blob ptr=%x len=%u",
- (UintPtr)buf, (uint)blob_len));
+ DBUG_PRINT("value", ("read blob ptr: 0x%lx len: %u",
+ (long)buf, (uint)blob_len));
if (ndb_blob->readData(buf, len) != 0)
DBUG_RETURN(-1);
DBUG_ASSERT(len == blob_len);
@@ -1593,7 +1605,9 @@ int ha_ndbcluster::peek_indexed_rows(const byte *record)
int res;
DBUG_ENTER("peek_indexed_rows");
- NdbOperation::LockMode lm= NdbOperation::LM_Read;
+ NdbOperation::LockMode lm=
+ (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
+
first= NULL;
if (table->s->primary_key != MAX_KEY)
{
@@ -1760,7 +1774,7 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
all pending update or delete operations should
be sent to NDB
*/
- DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending));
+ DBUG_PRINT("info", ("ops_pending: %ld", (long) m_ops_pending));
if (m_ops_pending)
{
if (m_transaction_on)
@@ -2962,7 +2976,7 @@ int ha_ndbcluster::close_scan()
Take over any pending transactions to the
deleteing/updating transaction before closing the scan
*/
- DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending));
+ DBUG_PRINT("info", ("ops_pending: %ld", (long) m_ops_pending));
if (execute_no_commit(this,trans,false) != 0) {
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
@@ -3086,8 +3100,9 @@ void ha_ndbcluster::position(const byte *record)
}
-void ha_ndbcluster::info(uint flag)
+int ha_ndbcluster::info(uint flag)
{
+ int result= 0;
DBUG_ENTER("info");
DBUG_PRINT("enter", ("flag: %d", flag));
@@ -3105,17 +3120,18 @@ void ha_ndbcluster::info(uint flag)
if (m_ha_not_exact_count)
records= 100;
else
- records_update();
+ result= records_update();
}
else
{
if ((my_errno= check_ndb_connection()))
- DBUG_VOID_RETURN;
+ DBUG_RETURN(my_errno);
Ndb *ndb= get_ndb();
struct Ndb_statistics stat;
ndb->setDatabaseName(m_dbname);
if (current_thd->variables.ndb_use_exact_count &&
- ndb_get_table_statistics(ndb, m_tabname, &stat) == 0)
+ (result= ndb_get_table_statistics(this, true, ndb, m_tabname, &stat))
+ == 0)
{
mean_rec_length= stat.row_size;
data_file_length= stat.fragment_memory;
@@ -3158,7 +3174,11 @@ void ha_ndbcluster::info(uint flag)
auto_increment_value= (ulonglong)auto_increment_value64;
}
}
- DBUG_VOID_RETURN;
+
+ if(result == -1)
+ result= HA_ERR_NO_CONNECTION;
+
+ DBUG_RETURN(result);
}
@@ -3522,8 +3542,8 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
Thd_ndb *thd_ndb= get_thd_ndb(thd);
Ndb *ndb= thd_ndb->ndb;
- DBUG_PRINT("enter", ("thd: %x, thd_ndb: %x, thd_ndb->lock_count: %d",
- thd, thd_ndb, thd_ndb->lock_count));
+ DBUG_PRINT("enter", ("thd: 0x%lx thd_ndb: 0x%lx thd_ndb->lock_count: %d",
+ (long) thd, (long) thd_ndb, thd_ndb->lock_count));
if (lock_type != F_UNLCK)
{
@@ -3827,7 +3847,8 @@ int ndbcluster_commit(THD *thd, bool all)
while ((share= it++))
{
pthread_mutex_lock(&share->mutex);
- DBUG_PRINT("info", ("Invalidate commit_count for %s, share->commit_count: %d ", share->table_name, share->commit_count));
+ DBUG_PRINT("info", ("Invalidate commit_count for %s, share->commit_count: %lu",
+ share->table_name, (ulong) share->commit_count));
share->commit_count= 0;
share->commit_count_lock++;
pthread_mutex_unlock(&share->mutex);
@@ -4261,7 +4282,7 @@ int ha_ndbcluster::create(const char *name,
if (packfrm(data, length, &pack_data, &pack_length))
DBUG_RETURN(2);
- DBUG_PRINT("info", ("setFrm data=%x, len=%d", pack_data, pack_length));
+ DBUG_PRINT("info", ("setFrm data: 0x%lx len: %d", (long) pack_data, pack_length));
tab.setFrm(pack_data, pack_length);
my_free((char*)data, MYF(0));
my_free((char*)pack_data, MYF(0));
@@ -4749,7 +4770,15 @@ int ha_ndbcluster::open(const char *name, int mode, uint test_if_locked)
res= get_metadata(name);
if (!res)
- info(HA_STATUS_VARIABLE | HA_STATUS_CONST);
+ {
+ Ndb *ndb= get_ndb();
+ ndb->setDatabaseName(m_dbname);
+ struct Ndb_statistics stat;
+ res= ndb_get_table_statistics(NULL, false, ndb, m_tabname, &stat);
+ records= stat.row_count;
+ if(!res)
+ res= info(HA_STATUS_CONST);
+ }
DBUG_RETURN(res);
}
@@ -5072,16 +5101,15 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
List<char> delete_list;
while ((file_name=it++))
{
+ bool file_on_disk= false;
DBUG_PRINT("info", ("%s", file_name));
if (hash_search(&ndb_tables, file_name, strlen(file_name)))
{
DBUG_PRINT("info", ("%s existed in NDB _and_ on disk ", file_name));
- // File existed in NDB and as frm file, put in ok_tables list
- my_hash_insert(&ok_tables, (byte*)file_name);
- continue;
+ file_on_disk= true;
}
- // File is not in NDB, check for .ndb file with this name
+ // Check for .ndb file with this name
(void)strxnmov(name, FN_REFLEN,
mysql_data_home,"/",db,"/",file_name,ha_ndb_ext,NullS);
DBUG_PRINT("info", ("Check access for %s", name));
@@ -5089,9 +5117,25 @@ int ndbcluster_find_files(THD *thd,const char *db,const char *path,
{
DBUG_PRINT("info", ("%s did not exist on disk", name));
// .ndb file did not exist on disk, another table type
+ if (file_on_disk)
+ {
+ // Ignore this ndb table
+ gptr record= hash_search(&ndb_tables, file_name, strlen(file_name));
+ DBUG_ASSERT(record);
+ hash_delete(&ndb_tables, record);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TABLE_EXISTS_ERROR,
+ "Local table %s.%s shadows ndb table",
+ db, file_name);
+ }
+ continue;
+ }
+ if (file_on_disk)
+ {
+ // File existed in NDB and as frm file, put in ok_tables list
+ my_hash_insert(&ok_tables, (byte*)file_name);
continue;
}
-
DBUG_PRINT("info", ("%s existed on disk", name));
// The .ndb file exists on disk, but it's not in list of tables in ndb
// Verify that handler agrees table is gone.
@@ -5194,7 +5238,7 @@ bool ndbcluster_init()
}
{
char buf[128];
- my_snprintf(buf, sizeof(buf), "mysqld --server-id=%d", server_id);
+ my_snprintf(buf, sizeof(buf), "mysqld --server-id=%lu", server_id);
g_ndb_cluster_connection->set_name(buf);
}
g_ndb_cluster_connection->set_optimized_node_selection
@@ -5562,7 +5606,7 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname,
pthread_mutex_unlock(&share->mutex);
struct Ndb_statistics stat;
- if (ndb_get_table_statistics(ndb, tabname, &stat))
+ if (ndb_get_table_statistics(NULL, false, ndb, tabname, &stat))
{
free_share(share);
DBUG_RETURN(1);
@@ -5770,9 +5814,9 @@ static NDB_SHARE* get_share(const char *table_name)
share->use_count++;
DBUG_PRINT("share",
- ("table_name: %s, length: %d, use_count: %d, commit_count: %d",
+ ("table_name: %s length: %d use_count: %d commit_count: %lu",
share->table_name, share->table_name_length, share->use_count,
- share->commit_count));
+ (ulong) share->commit_count));
pthread_mutex_unlock(&ndbcluster_mutex);
return share;
}
@@ -5819,14 +5863,14 @@ static int packfrm(const void *data, uint len,
uint blob_len;
frm_blob_struct* blob;
DBUG_ENTER("packfrm");
- DBUG_PRINT("enter", ("data: %x, len: %d", data, len));
+ DBUG_PRINT("enter", ("data: 0x%lx, len: %d", (long) data, len));
error= 1;
org_len= len;
if (my_compress((byte*)data, &org_len, &comp_len))
goto err;
- DBUG_PRINT("info", ("org_len: %d, comp_len: %d", org_len, comp_len));
+ DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", org_len, comp_len));
DBUG_DUMP("compressed", (char*)data, org_len);
error= 2;
@@ -5846,7 +5890,7 @@ static int packfrm(const void *data, uint len,
*pack_len= blob_len;
error= 0;
- DBUG_PRINT("exit", ("pack_data: %x, pack_len: %d", *pack_data, *pack_len));
+ DBUG_PRINT("exit", ("pack_data: 0x%lx, pack_len: %d", (long) *pack_data, *pack_len));
err:
DBUG_RETURN(error);
@@ -5860,13 +5904,13 @@ static int unpackfrm(const void **unpack_data, uint *unpack_len,
byte *data;
ulong complen, orglen, ver;
DBUG_ENTER("unpackfrm");
- DBUG_PRINT("enter", ("pack_data: %x", pack_data));
+ DBUG_PRINT("enter", ("pack_data: 0x%lx", (long) pack_data));
complen= uint4korr((char*)&blob->head.complen);
orglen= uint4korr((char*)&blob->head.orglen);
ver= uint4korr((char*)&blob->head.ver);
- DBUG_PRINT("blob",("ver: %d complen: %d orglen: %d",
+ DBUG_PRINT("blob",("ver: %lu complen: %lu orglen: %lu",
ver,complen,orglen));
DBUG_DUMP("blob->data", (char*) blob->data, complen);
@@ -5885,19 +5929,21 @@ static int unpackfrm(const void **unpack_data, uint *unpack_len,
*unpack_data= data;
*unpack_len= complen;
- DBUG_PRINT("exit", ("frmdata: %x, len: %d", *unpack_data, *unpack_len));
+ DBUG_PRINT("exit", ("frmdata: 0x%lx, len: %d", (long) *unpack_data, *unpack_len));
DBUG_RETURN(0);
}
static
int
-ndb_get_table_statistics(Ndb* ndb, const char * table,
+ndb_get_table_statistics(ha_ndbcluster* file, bool report_error, Ndb* ndb,
+ const char* table,
struct Ndb_statistics * ndbstat)
{
NdbTransaction* pTrans;
NdbError error;
int retries= 10;
+ int reterr= 0;
int retry_sleep= 30 * 1000; /* 30 milliseconds */
char buff[22], buff2[22], buff3[22], buff4[22];
DBUG_ENTER("ndb_get_table_statistics");
@@ -5988,6 +6034,22 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
DBUG_RETURN(0);
retry:
+ if(report_error)
+ {
+ if (file)
+ {
+ reterr= file->ndb_err(pTrans);
+ }
+ else
+ {
+ const NdbError& tmp= error;
+ ERR_PRINT(tmp);
+ reterr= ndb_to_mysql_error(&tmp);
+ }
+ }
+ else
+ reterr= error.code;
+
if (pTrans)
{
ndb->closeTransaction(pTrans);
@@ -6000,8 +6062,9 @@ retry:
}
break;
} while(1);
- DBUG_PRINT("exit", ("failed, error %u(%s)", error.code, error.message));
- ERR_RETURN(error);
+ DBUG_PRINT("exit", ("failed, reterr: %u, NdbError %u(%s)", reterr,
+ error.code, error.message));
+ DBUG_RETURN(reterr);
}
/*
@@ -6459,7 +6522,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
my_thread_init();
DBUG_ENTER("ndb_util_thread");
- DBUG_PRINT("enter", ("ndb_cache_check_time: %d", ndb_cache_check_time));
+ DBUG_PRINT("enter", ("ndb_cache_check_time: %lu", ndb_cache_check_time));
thd= new THD; /* note that contructor of THD uses DBUG_ */
THD_CHECK_SENTRY(thd);
@@ -6488,7 +6551,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
&abstime);
pthread_mutex_unlock(&LOCK_ndb_util_thread);
- DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %d",
+ DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %lu",
ndb_cache_check_time));
if (abort_loop)
@@ -6542,7 +6605,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused)))
lock= share->commit_count_lock;
pthread_mutex_unlock(&share->mutex);
- if (ndb_get_table_statistics(ndb, tabname, &stat) == 0)
+ if (ndb_get_table_statistics(NULL, false, ndb, tabname, &stat) == 0)
{
char buff[22], buff2[22];
DBUG_PRINT("ndb_util_thread",
@@ -6896,11 +6959,13 @@ void ndb_serialize_cond(const Item *item, void *arg)
DBUG_PRINT("info", ("FIELD_ITEM"));
DBUG_PRINT("info", ("table %s", tab->getName()));
DBUG_PRINT("info", ("column %s", field->field_name));
+ DBUG_PRINT("info", ("type %d", field->type()));
DBUG_PRINT("info", ("result type %d", field->result_type()));
// Check that we are expecting a field and with the correct
// result type
if (context->expecting(Item::FIELD_ITEM) &&
+ context->expecting_field_type(field->type()) &&
(context->expecting_field_result(field->result_type()) ||
// Date and year can be written as string or int
((type == MYSQL_TYPE_TIME ||
@@ -6923,7 +6988,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo());
context->dont_expect(Item::FIELD_ITEM);
context->expect_no_field_result();
- if (context->expect_mask)
+ if (! context->expecting_nothing())
{
// We have not seen second argument yet
if (type == MYSQL_TYPE_TIME ||
@@ -7120,6 +7185,9 @@ void ndb_serialize_cond(const Item *item, void *arg)
func_item);
context->expect(Item::STRING_ITEM);
context->expect(Item::FIELD_ITEM);
+ context->expect_only_field_type(MYSQL_TYPE_STRING);
+ context->expect_field_type(MYSQL_TYPE_VAR_STRING);
+ context->expect_field_type(MYSQL_TYPE_VARCHAR);
context->expect_field_result(STRING_RESULT);
context->expect(Item::FUNC_ITEM);
break;
@@ -7225,7 +7293,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::STRING_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
@@ -7255,7 +7323,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::REAL_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
@@ -7278,7 +7346,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::INT_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
@@ -7301,7 +7369,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::DECIMAL_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
@@ -7351,7 +7419,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::STRING_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
@@ -7380,11 +7448,11 @@ void ndb_serialize_cond(const Item *item, void *arg)
if (context->expecting(Item::INT_ITEM))
{
Item_int *int_item= (Item_int *) item;
- DBUG_PRINT("info", ("value %d", int_item->value));
+ DBUG_PRINT("info", ("value %ld", (long) int_item->value));
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::INT_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
@@ -7403,7 +7471,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->supported= FALSE;
break;
case Item::REAL_ITEM:
- DBUG_PRINT("info", ("REAL_ITEM %s"));
+ DBUG_PRINT("info", ("REAL_ITEM"));
if (context->expecting(Item::REAL_ITEM))
{
Item_float *float_item= (Item_float *) item;
@@ -7411,7 +7479,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::REAL_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
@@ -7434,7 +7502,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::VARBIN_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
@@ -7451,7 +7519,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
context->supported= FALSE;
break;
case Item::DECIMAL_ITEM:
- DBUG_PRINT("info", ("DECIMAL_ITEM %s"));
+ DBUG_PRINT("info", ("DECIMAL_ITEM"));
if (context->expecting(Item::DECIMAL_ITEM))
{
Item_decimal *decimal_item= (Item_decimal *) item;
@@ -7459,7 +7527,7 @@ void ndb_serialize_cond(const Item *item, void *arg)
NDB_ITEM_QUALIFICATION q;
q.value_type= Item::DECIMAL_ITEM;
curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
- if (context->expect_field_result_mask)
+ if (! context->expecting_no_field_result())
{
// We have not seen the field argument yet
context->expect_only(Item::FIELD_ITEM);
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index cfb12981b98..d0f7c020184 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -362,53 +362,95 @@ class Ndb_cond_traverse_context
Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack)
: table(tab), ndb_table(ndb_tab),
supported(TRUE), stack_ptr(stack), cond_ptr(NULL),
- expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL),
- rewrite_stack(NULL)
+ skip(0), collation(NULL), rewrite_stack(NULL)
{
+ // Allocate type checking bitmaps
+ bitmap_init(&expect_mask, 0, 512, FALSE);
+ bitmap_init(&expect_field_type_mask, 0, 512, FALSE);
+ bitmap_init(&expect_field_result_mask, 0, 512, FALSE);
+
if (stack)
cond_ptr= stack->ndb_cond;
};
~Ndb_cond_traverse_context()
{
+ bitmap_free(&expect_mask);
+ bitmap_free(&expect_field_type_mask);
+ bitmap_free(&expect_field_result_mask);
if (rewrite_stack) delete rewrite_stack;
}
void expect(Item::Type type)
{
- expect_mask|= (1 << type);
+ bitmap_set_bit(&expect_mask, (uint) type);
+ if (type == Item::FIELD_ITEM) expect_all_field_types();
};
void dont_expect(Item::Type type)
{
- expect_mask&= ~(1 << type);
+ bitmap_clear_bit(&expect_mask, (uint) type);
};
bool expecting(Item::Type type)
{
- return (expect_mask & (1 << type));
+ return bitmap_is_set(&expect_mask, (uint) type);
};
void expect_nothing()
{
- expect_mask= 0;
+ bitmap_clear_all(&expect_mask);
};
+ bool expecting_nothing()
+ {
+ return bitmap_is_clear_all(&expect_mask);
+ }
void expect_only(Item::Type type)
{
- expect_mask= 0;
+ expect_nothing();
expect(type);
};
+ void expect_field_type(enum_field_types type)
+ {
+ bitmap_set_bit(&expect_field_type_mask, (uint) type);
+ };
+ void expect_all_field_types()
+ {
+ bitmap_set_all(&expect_field_type_mask);
+ };
+ bool expecting_field_type(enum_field_types type)
+ {
+ return bitmap_is_set(&expect_field_type_mask, (uint) type);
+ };
+ void expect_no_field_type()
+ {
+ bitmap_clear_all(&expect_field_type_mask);
+ };
+ bool expecting_no_field_type()
+ {
+ return bitmap_is_clear_all(&expect_field_type_mask);
+ }
+ void expect_only_field_type(enum_field_types result)
+ {
+ expect_no_field_type();
+ expect_field_type(result);
+ };
+
void expect_field_result(Item_result result)
{
- expect_field_result_mask|= (1 << result);
+ bitmap_set_bit(&expect_field_result_mask, (uint) result);
};
bool expecting_field_result(Item_result result)
{
- return (expect_field_result_mask & (1 << result));
+ return bitmap_is_set(&expect_field_result_mask, (uint) result);
};
void expect_no_field_result()
{
- expect_field_result_mask= 0;
+ bitmap_clear_all(&expect_field_result_mask);
};
+ bool expecting_no_field_result()
+ {
+ return bitmap_is_clear_all(&expect_field_result_mask);
+ }
void expect_only_field_result(Item_result result)
{
- expect_field_result_mask= 0;
+ expect_no_field_result();
expect_field_result(result);
};
void expect_collation(CHARSET_INFO* col)
@@ -428,8 +470,9 @@ class Ndb_cond_traverse_context
bool supported;
Ndb_cond_stack* stack_ptr;
Ndb_cond* cond_ptr;
- uint expect_mask;
- uint expect_field_result_mask;
+ MY_BITMAP expect_mask;
+ MY_BITMAP expect_field_type_mask;
+ MY_BITMAP expect_field_result_mask;
uint skip;
CHARSET_INFO* collation;
Ndb_rewrite_context *rewrite_stack;
@@ -505,7 +548,7 @@ class ha_ndbcluster: public handler
int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
bool get_error_message(int error, String *buf);
- void info(uint);
+ int info(uint);
int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size);
int external_lock(THD *thd, int lock_type);
@@ -583,6 +626,12 @@ static void set_tabname(const char *pathname, char *tabname);
void cond_pop();
uint8 table_cache_type();
+
+ /*
+ * Internal to ha_ndbcluster, used by C functions
+ */
+ int ndb_err(NdbTransaction*);
+
my_bool register_query_cache_table(THD *thd, char *table_key,
uint key_length,
qc_engine_callback *engine_callback,
@@ -647,8 +696,8 @@ private:
ulonglong get_auto_increment();
void invalidate_dictionary_cache(bool global);
- int ndb_err(NdbTransaction*);
- bool uses_blob_value(bool all_fields);
+
+bool uses_blob_value(bool all_fields);
char *update_table_comment(const char * comment);
@@ -657,7 +706,7 @@ private:
int check_ndb_connection(THD* thd= current_thd);
void set_rec_per_key();
- void records_update();
+ int records_update();
void no_uncommitted_rows_execute_failure();
void no_uncommitted_rows_update(int);
void no_uncommitted_rows_init(THD *);
diff --git a/sql/handler.cc b/sql/handler.cc
index 3516b55feb5..ae314afb991 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -474,7 +474,6 @@ int ha_init()
{
int error= 0;
handlerton **types;
- show_table_alias_st *table_alias;
total_ha= savepoint_alloc_size= 0;
if (ha_init_errors())
@@ -885,8 +884,8 @@ int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
if ((*types)->state == SHOW_OPTION_YES && (*types)->recover)
{
if ((*(commit ? (*types)->commit_by_xid :
- (*types)->rollback_by_xid))(xid));
- res= 0;
+ (*types)->rollback_by_xid))(xid))
+ res= 0;
}
}
return res;
@@ -1533,7 +1532,7 @@ prev_insert_id(ulonglong nr, struct system_variables *variables)
*/
DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour "
"auto_increment_offset: %lu",
- nr, variables->auto_increment_offset));
+ (ulong) nr, variables->auto_increment_offset));
return nr;
}
if (variables->auto_increment_increment == 1)
@@ -1774,12 +1773,22 @@ void handler::print_error(int error, myf errflag)
/* Write the dupplicated key in the error message */
char key[MAX_KEY_LENGTH];
String str(key,sizeof(key),system_charset_info);
- key_unpack(&str,table,(uint) key_nr);
- uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
- if (str.length() >= max_length)
+
+ if (key_nr == MAX_KEY)
{
- str.length(max_length-4);
- str.append(STRING_WITH_LEN("..."));
+ /* Key is unknown */
+ str.copy("", 0, system_charset_info);
+ key_nr= (uint) -1;
+ }
+ else
+ {
+ key_unpack(&str,table,(uint) key_nr);
+ uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY));
+ if (str.length() >= max_length)
+ {
+ str.length(max_length-4);
+ str.append(STRING_WITH_LEN("..."));
+ }
}
my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), key_nr+1);
DBUG_VOID_RETURN;
diff --git a/sql/handler.h b/sql/handler.h
index 481a98be285..e474eac8cb1 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -682,7 +682,7 @@ public:
key_range *max_key)
{ return (ha_rows) 10; }
virtual void position(const byte *record)=0;
- virtual void info(uint)=0; // see my_base.h for full description
+ virtual int info(uint)=0; // see my_base.h for full description
virtual int extra(enum ha_extra_function operation)
{ return 0; }
virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
diff --git a/sql/item.cc b/sql/item.cc
index dc92edd651d..58c2bc75522 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -276,7 +276,6 @@ my_decimal *Item::val_decimal_from_date(my_decimal *decimal_value)
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- longlong date;
if (get_date(&ltime, TIME_FUZZY_DATE))
{
my_decimal_set_zero(decimal_value);
@@ -290,7 +289,6 @@ my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value)
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
- longlong date;
if (get_time(&ltime))
{
my_decimal_set_zero(decimal_value);
@@ -1691,7 +1689,7 @@ void Item_field::set_field(Field *field_par)
db_name= field_par->table->s->db;
alias_name_used= field_par->table->alias_name_used;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
- collation.set(field_par->charset(), DERIVATION_IMPLICIT);
+ collation.set(field_par->charset(), field_par->derivation());
fixed= 1;
}
@@ -2175,12 +2173,6 @@ void Item_string::print(String *str)
}
-inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str, char *end)
-{
- return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end;
-}
-
-
double Item_string::val_real()
{
DBUG_ASSERT(fixed == 1);
@@ -4202,6 +4194,10 @@ void Item_field::make_field(Send_field *tmp_field)
DBUG_ASSERT(tmp_field->table_name != 0);
if (name)
tmp_field->col_name=name; // Use user supplied name
+ if (table_name)
+ tmp_field->table_name= table_name;
+ if (db_name)
+ tmp_field->db_name= db_name;
}
@@ -4760,6 +4756,22 @@ bool Item_field::send(Protocol *protocol, String *buffer)
}
+void Item_field::update_null_value()
+{
+ /*
+ need to set no_errors to prevent warnings about type conversion
+ popping up.
+ */
+ THD *thd= field->table->in_use;
+ int no_errors;
+
+ no_errors= thd->no_errors;
+ thd->no_errors= 1;
+ Item::update_null_value();
+ thd->no_errors= no_errors;
+}
+
+
Item_ref::Item_ref(Name_resolution_context *context_arg,
Item **item, const char *table_name_arg,
const char *field_name_arg)
@@ -5642,7 +5654,7 @@ void Item_trigger_field::set_required_privilege(bool rw)
}
-bool Item_trigger_field::set_value(THD *thd, sp_rcontext */*ctx*/, Item **it)
+bool Item_trigger_field::set_value(THD *thd, sp_rcontext * /*ctx*/, Item **it)
{
Item *item= sp_prepare_func_item(thd, it);
@@ -6116,7 +6128,7 @@ bool Item_cache_row::null_inside()
}
else
{
- values[i]->val_int();
+ values[i]->update_null_value();
if (values[i]->null_value)
return 1;
}
diff --git a/sql/item.h b/sql/item.h
index c1a04e4281d..e0451febb1e 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -27,19 +27,7 @@ class Item_field;
/*
"Declared Type Collation"
A combination of collation and its derivation.
-*/
-
-enum Derivation
-{
- DERIVATION_IGNORABLE= 5,
- DERIVATION_COERCIBLE= 4,
- DERIVATION_SYSCONST= 3,
- DERIVATION_IMPLICIT= 2,
- DERIVATION_NONE= 1,
- DERIVATION_EXPLICIT= 0
-};
-/*
Flags for collation aggregation modes:
MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
@@ -716,6 +704,11 @@ public:
virtual bool is_null() { return 0; }
/*
+ Make sure the null_value member has a correct value.
+ */
+ virtual void update_null_value () { (void) val_int(); }
+
+ /*
Inform the item that there will be no distinction between its result
being FALSE or NULL.
@@ -1282,6 +1275,7 @@ public:
bool get_date_result(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); }
+ void update_null_value();
Item *get_tmp_table_item(THD *thd);
bool collect_item_field_processor(byte * arg);
bool find_item_in_field_list_processor(byte *arg);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 540f67ba0ee..29fa049b6c4 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -2228,7 +2228,7 @@ cmp_item* cmp_item_row::make_same()
cmp_item_row::~cmp_item_row()
{
DBUG_ENTER("~cmp_item_row");
- DBUG_PRINT("enter",("this: 0x%lx", this));
+ DBUG_PRINT("enter",("this: 0x%lx", (long) this));
if (comparators)
{
for (uint i= 0; i < n; i++)
@@ -2497,7 +2497,6 @@ void Item_func_in::fix_length_and_dec()
if (cmp_type == STRING_RESULT)
in_item->cmp_charset= cmp_collation.collation;
}
- maybe_null= args[0]->maybe_null;
max_length= 1;
}
@@ -3003,7 +3002,7 @@ longlong Item_is_not_null_test::val_int()
if (!used_tables_cache)
{
owner->was_null|= (!cached_value);
- DBUG_PRINT("info", ("cached :%d", cached_value));
+ DBUG_PRINT("info", ("cached :%ld", (long) cached_value));
DBUG_RETURN(cached_value);
}
if (args[0]->is_null())
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ca29fe14ab2..7047c874c2a 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -105,7 +105,7 @@ Item_func::Item_func(THD *thd, Item_func *item)
/*
- Resolve references to table column for a function and it's argument
+ Resolve references to table column for a function and its argument
SYNOPSIS:
fix_fields()
@@ -900,7 +900,8 @@ void Item_func_signed::print(String *str)
longlong Item_func_signed::val_int_from_str(int *error)
{
- char buff[MAX_FIELD_WIDTH], *end;
+ char buff[MAX_FIELD_WIDTH], *end, *start;
+ uint32 length;
String tmp(buff,sizeof(buff), &my_charset_bin), *res;
longlong value;
@@ -916,13 +917,21 @@ longlong Item_func_signed::val_int_from_str(int *error)
return 0;
}
null_value= 0;
- end= (char*) res->ptr()+ res->length();
- value= my_strtoll10(res->ptr(), &end, error);
- if (*error > 0 || end != res->ptr()+ res->length())
+ start= (char *)res->ptr();
+ length= res->length();
+
+ end= start + length;
+ value= my_strtoll10(start, &end, error);
+ if (*error > 0 || end != start+ length)
+ {
+ char err_buff[128];
+ String err_tmp(err_buff,(uint32) sizeof(err_buff), system_charset_info);
+ err_tmp.copy(start, length, system_charset_info);
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE,
ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
- res->c_ptr());
+ err_tmp.c_ptr());
+ }
return value;
}
@@ -964,7 +973,14 @@ longlong Item_func_unsigned::val_int()
longlong value;
int error;
- if (args[0]->cast_to_int_type() != STRING_RESULT)
+ if (args[0]->cast_to_int_type() == DECIMAL_RESULT)
+ {
+ my_decimal tmp, *dec= args[0]->val_decimal(&tmp);
+ if (!(null_value= args[0]->null_value))
+ my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value);
+ return value;
+ }
+ else if (args[0]->cast_to_int_type() != STRING_RESULT)
{
value= args[0]->val_int();
null_value= args[0]->null_value;
@@ -1377,6 +1393,13 @@ void Item_func_mod::result_precision()
}
+void Item_func_mod::fix_length_and_dec()
+{
+ Item_num_op::fix_length_and_dec();
+ maybe_null= 1;
+}
+
+
double Item_func_neg::real_op()
{
double value= args[0]->val_real();
@@ -2306,24 +2329,31 @@ longlong Item_func_locate::val_int()
return 0; /* purecov: inspected */
}
null_value=0;
- uint start=0;
- uint start0=0;
+ /* must be longlong to avoid truncation */
+ longlong start= 0;
+ longlong start0= 0;
my_match_t match;
if (arg_count == 3)
{
- start0= start =(uint) args[2]->val_int()-1;
- start=a->charpos(start);
-
- if (start > a->length() || start+b->length() > a->length())
+ start0= start= args[2]->val_int() - 1;
+
+ if ((start < 0) || (start > a->length()))
+ return 0;
+
+ /* start is now sufficiently valid to pass to charpos function */
+ start= a->charpos((int) start);
+
+ if (start + b->length() > a->length())
return 0;
}
if (!b->length()) // Found empty string at start
- return (longlong) (start+1);
+ return start + 1;
if (!cmp_collation.collation->coll->instr(cmp_collation.collation,
- a->ptr()+start, a->length()-start,
+ a->ptr()+start,
+ (uint) (a->length()-start),
b->ptr(), b->length(),
&match, 1))
return 0;
@@ -4272,7 +4302,7 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
bool Item_func_get_user_var::set_value(THD *thd,
- sp_rcontext */*ctx*/, Item **it)
+ sp_rcontext * /*ctx*/, Item **it)
{
Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it);
/*
@@ -4863,6 +4893,7 @@ Item_func_sp::cleanup()
result_field= NULL;
}
m_sp= NULL;
+ dummy_table->s= NULL;
Item_func::cleanup();
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 99f7d16855e..ca835177f18 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -157,7 +157,7 @@ public:
return (null_value=args[0]->get_time(ltime));
}
bool is_null() {
- (void) val_int(); /* Discard result. It sets null_value as side-effect. */
+ update_null_value();
return null_value;
}
void signal_divide_by_null();
@@ -241,7 +241,7 @@ public:
virtual double real_op()= 0;
virtual my_decimal *decimal_op(my_decimal *)= 0;
virtual String *str_op(String *)= 0;
- bool is_null() { (void) val_real(); return null_value; }
+ bool is_null() { update_null_value(); return null_value; }
};
/* function where type of result detected by first argument */
@@ -430,6 +430,7 @@ public:
my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "%"; }
void result_precision();
+ void fix_length_and_dec();
};
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index b973858b8e5..63700e9b53d 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -80,6 +80,20 @@ String *Item_str_func::check_well_formed_result(String *str)
}
+bool Item_str_func::fix_fields(THD *thd, Item **ref)
+{
+ bool res= Item_func::fix_fields(thd, ref);
+ /*
+ In Item_str_func::check_well_formed_result() we may set null_value
+ flag on the same condition as in test() below.
+ */
+ maybe_null= (maybe_null ||
+ test(thd->variables.sql_mode &
+ (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)));
+ return res;
+}
+
+
my_decimal *Item_str_func::val_decimal(my_decimal *decimal_value)
{
DBUG_ASSERT(fixed == 1);
@@ -951,24 +965,35 @@ String *Item_func_insert::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res,*res2;
- uint start,length;
+ longlong start, length; /* must be longlong to avoid truncation */
null_value=0;
res=args[0]->val_str(str);
res2=args[3]->val_str(&tmp_value);
- start=(uint) args[1]->val_int()-1;
- length=(uint) args[2]->val_int();
+ start= args[1]->val_int() - 1;
+ length= args[2]->val_int();
+
if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
args[3]->null_value)
goto null; /* purecov: inspected */
- start=res->charpos(start);
- length=res->charpos(length,start);
- if (start > res->length()+1)
- return res; // Wrong param; skip insert
- if (length > res->length()-start)
- length=res->length()-start;
- if (res->length() - length + res2->length() >
- current_thd->variables.max_allowed_packet)
+
+ if ((start < 0) || (start > res->length() + 1))
+ return res; // Wrong param; skip insert
+ if ((length < 0) || (length > res->length() + 1))
+ length= res->length() + 1;
+
+ /* start and length are now sufficiently valid to pass to charpos function */
+ start= res->charpos((int) start);
+ length= res->charpos((int) length, (uint32) start);
+
+ /* Re-testing with corrected params */
+ if (start > res->length() + 1)
+ return res; // Wrong param; skip insert
+ if (length > res->length() - start)
+ length= res->length() - start;
+
+ if ((ulonglong) (res->length() - length + res2->length()) >
+ (ulonglong) current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
@@ -977,7 +1002,7 @@ String *Item_func_insert::val_str(String *str)
goto null;
}
res=copy_if_not_alloced(str,res,res->length());
- res->replace(start,length,*res2);
+ res->replace((uint32) start,(uint32) length,*res2);
return res;
null:
null_value=1;
@@ -1039,16 +1064,21 @@ String *Item_str_conv::val_str(String *str)
String *Item_func_left::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- String *res =args[0]->val_str(str);
- long length =(long) args[1]->val_int();
+ String *res= args[0]->val_str(str);
+
+ /* must be longlong to avoid truncation */
+ longlong length= args[1]->val_int();
uint char_pos;
if ((null_value=(args[0]->null_value || args[1]->null_value)))
return 0;
- if (length <= 0)
+
+ /* if "unsigned_flag" is set, we have a *huge* positive number. */
+ if ((length <= 0) && (!args[1]->unsigned_flag))
return &my_empty_string;
- if (res->length() <= (uint) length ||
- res->length() <= (char_pos= res->charpos(length)))
+
+ if ((res->length() <= (ulonglong) length) ||
+ (res->length() <= (char_pos= res->charpos((int) length))))
return res;
tmp_value.set(*res, 0, char_pos);
@@ -1080,14 +1110,18 @@ void Item_func_left::fix_length_and_dec()
String *Item_func_right::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- String *res =args[0]->val_str(str);
- long length =(long) args[1]->val_int();
+ String *res= args[0]->val_str(str);
+ /* must be longlong to avoid truncation */
+ longlong length= args[1]->val_int();
if ((null_value=(args[0]->null_value || args[1]->null_value)))
return 0; /* purecov: inspected */
- if (length <= 0)
+
+ /* if "unsigned_flag" is set, we have a *huge* positive number. */
+ if ((length <= 0) && (!args[1]->unsigned_flag))
return &my_empty_string; /* purecov: inspected */
- if (res->length() <= (uint) length)
+
+ if (res->length() <= (ulonglong) length)
return res; /* purecov: inspected */
uint start=res->numchars();
@@ -1110,25 +1144,43 @@ String *Item_func_substr::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
- int32 start = (int32) args[1]->val_int();
- int32 length = arg_count == 3 ? (int32) args[2]->val_int() : INT_MAX32;
- int32 tmp_length;
+ /* must be longlong to avoid truncation */
+ longlong start= args[1]->val_int();
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ /* Limit so that code sees out-of-bound value properly. */
+ longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32;
+ longlong tmp_length;
if ((null_value=(args[0]->null_value || args[1]->null_value ||
(arg_count == 3 && args[2]->null_value))))
return 0; /* purecov: inspected */
- start= (int32)((start < 0) ? res->numchars() + start : start -1);
- start=res->charpos(start);
- length=res->charpos(length,start);
- if (start < 0 || (uint) start+1 > res->length() || length <= 0)
+
+ /* Negative length, will return empty string. */
+ if ((arg_count == 3) && (length <= 0) && !args[2]->unsigned_flag)
return &my_empty_string;
- tmp_length=(int32) res->length()-start;
- length=min(length,tmp_length);
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ /* Set here so that rest of code sees out-of-bound value as such. */
+ if ((length <= 0) || (length > INT_MAX32))
+ length= INT_MAX32;
+
+ /* if "unsigned_flag" is set, we have a *huge* positive number. */
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ if ((args[1]->unsigned_flag) || (start < INT_MIN32) || (start > INT_MAX32))
+ return &my_empty_string;
- if (!start && res->length() == (uint) length)
+ start= ((start < 0) ? res->numchars() + start : start - 1);
+ start= res->charpos((int) start);
+ if ((start < 0) || ((uint) start + 1 > res->length()))
+ return &my_empty_string;
+
+ length= res->charpos((int) length, (uint32) start);
+ tmp_length= res->length() - start;
+ length= min(length, tmp_length);
+
+ if (!start && (longlong) res->length() == length)
return res;
- tmp_value.set(*res,(uint) start,(uint) length);
+ tmp_value.set(*res, (uint32) start, (uint32) length);
return &tmp_value;
}
@@ -2146,8 +2198,15 @@ void Item_func_repeat::fix_length_and_dec()
collation.set(args[0]->collation);
if (args[1]->const_item())
{
- ulonglong max_result_length= ((ulonglong) args[0]->max_length *
- args[1]->val_int());
+ /* must be longlong to avoid truncation */
+ longlong count= args[1]->val_int();
+
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ /* Set here so that rest of code sees out-of-bound value as such. */
+ if (count > INT_MAX32)
+ count= INT_MAX32;
+
+ ulonglong max_result_length= (ulonglong) args[0]->max_length * count;
if (max_result_length >= MAX_BLOB_WIDTH)
{
max_result_length= MAX_BLOB_WIDTH;
@@ -2172,13 +2231,20 @@ String *Item_func_repeat::val_str(String *str)
DBUG_ASSERT(fixed == 1);
uint length,tot_length;
char *to;
- long count= (long) args[1]->val_int();
- String *res =args[0]->val_str(str);
+ /* must be longlong to avoid truncation */
+ longlong tmp_count= args[1]->val_int();
+ long count= (long) tmp_count;
+ String *res= args[0]->val_str(str);
+
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ /* Bounds check on count: If this is triggered, we will error. */
+ if ((tmp_count > INT_MAX32) || args[1]->unsigned_flag)
+ count= INT_MAX32;
if (args[0]->null_value || args[1]->null_value)
goto err; // string and/or delim are null
- null_value=0;
- if (count <= 0) // For nicer SQL code
+ null_value= 0;
+ if ((tmp_count <= 0) && !args[1]->unsigned_flag) // For nicer SQL code
return &my_empty_string;
if (count == 1) // To avoid reallocs
return res;
@@ -2217,8 +2283,20 @@ void Item_func_rpad::fix_length_and_dec()
return;
if (args[1]->const_item())
{
- ulonglong length= ((ulonglong) args[1]->val_int() *
- collation.collation->mbmaxlen);
+ ulonglong length= 0;
+
+ if (collation.collation->mbmaxlen > 0)
+ {
+ ulonglong temp= (ulonglong) args[1]->val_int();
+
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ /* Set here so that rest of code sees out-of-bound value as such. */
+ if (temp > INT_MAX32)
+ temp = INT_MAX32;
+
+ length= temp * collation.collation->mbmaxlen;
+ }
+
if (length >= MAX_BLOB_WIDTH)
{
length= MAX_BLOB_WIDTH;
@@ -2240,21 +2318,30 @@ String *Item_func_rpad::val_str(String *str)
uint32 res_byte_length,res_char_length,pad_char_length,pad_byte_length;
char *to;
const char *ptr_pad;
- int32 count= (int32) args[1]->val_int();
- int32 byte_count= count * collation.collation->mbmaxlen;
- String *res =args[0]->val_str(str);
- String *rpad = args[2]->val_str(&rpad_str);
+ /* must be longlong to avoid truncation */
+ longlong count= args[1]->val_int();
+ longlong byte_count;
+ String *res= args[0]->val_str(str);
+ String *rpad= args[2]->val_str(&rpad_str);
+
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ /* Set here so that rest of code sees out-of-bound value as such. */
+ if ((count > INT_MAX32) || args[1]->unsigned_flag)
+ count= INT_MAX32;
if (!res || args[1]->null_value || !rpad || count < 0)
goto err;
null_value=0;
- if (count <= (int32) (res_char_length=res->numchars()))
+
+ if (count <= (res_char_length= res->numchars()))
{ // String to pad is big enough
- res->length(res->charpos(count)); // Shorten result if longer
+ res->length(res->charpos((int) count)); // Shorten result if longer
return (res);
}
pad_char_length= rpad->numchars();
- if ((ulong) byte_count > current_thd->variables.max_allowed_packet)
+
+ byte_count= count * collation.collation->mbmaxlen;
+ if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
@@ -2265,7 +2352,7 @@ String *Item_func_rpad::val_str(String *str)
if (args[2]->null_value || !pad_char_length)
goto err;
res_byte_length= res->length(); /* Must be done before alloc_buffer */
- if (!(res= alloc_buffer(res,str,&tmp_value,byte_count)))
+ if (!(res= alloc_buffer(res,str,&tmp_value, (ulong) byte_count)))
goto err;
to= (char*) res->ptr()+res_byte_length;
@@ -2279,7 +2366,7 @@ String *Item_func_rpad::val_str(String *str)
}
if (count)
{
- pad_byte_length= rpad->charpos(count);
+ pad_byte_length= rpad->charpos((int) count);
memcpy(to,ptr_pad,(size_t) pad_byte_length);
to+= pad_byte_length;
}
@@ -2300,8 +2387,20 @@ void Item_func_lpad::fix_length_and_dec()
if (args[1]->const_item())
{
- ulonglong length= ((ulonglong) args[1]->val_int() *
- collation.collation->mbmaxlen);
+ ulonglong length= 0;
+
+ if (collation.collation->mbmaxlen > 0)
+ {
+ ulonglong temp= (ulonglong) args[1]->val_int();
+
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ /* Set here so that rest of code sees out-of-bound value as such. */
+ if (temp > INT_MAX32)
+ temp= INT_MAX32;
+
+ length= temp * collation.collation->mbmaxlen;
+ }
+
if (length >= MAX_BLOB_WIDTH)
{
length= MAX_BLOB_WIDTH;
@@ -2321,26 +2420,32 @@ String *Item_func_lpad::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
uint32 res_char_length,pad_char_length;
- ulong count= (long) args[1]->val_int(), byte_count;
+ /* must be longlong to avoid truncation */
+ longlong count= args[1]->val_int();
+ longlong byte_count;
String *res= args[0]->val_str(&tmp_value);
String *pad= args[2]->val_str(&lpad_str);
- if (!res || args[1]->null_value || !pad)
- goto err;
+ /* Assumes that the maximum length of a String is < INT_MAX32. */
+ /* Set here so that rest of code sees out-of-bound value as such. */
+ if ((count > INT_MAX32) || args[1]->unsigned_flag)
+ count= INT_MAX32;
+ if (!res || args[1]->null_value || !pad || count < 0)
+ goto err;
null_value=0;
res_char_length= res->numchars();
if (count <= res_char_length)
{
- res->length(res->charpos(count));
+ res->length(res->charpos((int) count));
return res;
}
pad_char_length= pad->numchars();
byte_count= count * collation.collation->mbmaxlen;
- if (byte_count > current_thd->variables.max_allowed_packet)
+ if ((ulonglong) byte_count > current_thd->variables.max_allowed_packet)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_ALLOWED_PACKET_OVERFLOWED,
@@ -2349,7 +2454,8 @@ String *Item_func_lpad::val_str(String *str)
goto err;
}
- if (args[2]->null_value || !pad_char_length || str->alloc(byte_count))
+ if (args[2]->null_value || !pad_char_length ||
+ str->alloc((uint32) byte_count))
goto err;
str->length(0);
@@ -2361,7 +2467,7 @@ String *Item_func_lpad::val_str(String *str)
count-= pad_char_length;
}
if (count > 0)
- str->append(pad->ptr(), pad->charpos(count), collation.collation);
+ str->append(pad->ptr(), pad->charpos((int) count), collation.collation);
str->append(*res);
null_value= 0;
@@ -2691,7 +2797,7 @@ String *Item_load_file::val_str(String *str)
tmp_value.length(stat_info.st_size);
my_close(file, MYF(0));
null_value = 0;
- return &tmp_value;
+ DBUG_RETURN(&tmp_value);
err:
null_value = 1;
@@ -2970,6 +3076,7 @@ String *Item_func_compress::val_str(String *str)
null_value= 1;
return 0;
}
+ null_value= 0;
if (res->is_empty()) return res;
/*
@@ -3180,4 +3287,3 @@ String *Item_func_uuid::val_str(String *str)
strmov(s+18, clock_seq_and_node_str);
return str;
}
-
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 528180b803d..fd2aaf19675 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -37,6 +37,7 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
String *check_well_formed_result(String *str);
+ bool fix_fields(THD *thd, Item **ref);
};
class Item_func_md5 :public Item_str_func
@@ -525,9 +526,8 @@ public:
{ collation.set(cs); }
String *val_str(String *);
void fix_length_and_dec()
- {
- maybe_null=0;
- max_length=arg_count * collation.collation->mbmaxlen;
+ {
+ max_length= arg_count * collation.collation->mbmaxlen;
}
const char *func_name() const { return "char"; }
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 551795acd53..bffecb3c84c 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -54,7 +54,7 @@ void Item_subselect::init(st_select_lex *select_lex,
{
DBUG_ENTER("Item_subselect::init");
- DBUG_PRINT("enter", ("select_lex: 0x%x", (ulong) select_lex));
+ DBUG_PRINT("enter", ("select_lex: 0x%lx", (long) select_lex));
unit= select_lex->master_unit();
if (unit->item)
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index f1be99353cc..35ded79b75d 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -91,7 +91,7 @@ public:
enum Type type() const;
bool is_null()
{
- val_int();
+ update_null_value();
return null_value;
}
bool fix_fields(THD *thd, Item **ref);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index fccbdfa7925..7b296019709 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -322,9 +322,13 @@ void Item_sum::make_field(Send_field *tmp_field)
if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
{
((Item_field*) args[0])->field->make_field(tmp_field);
- tmp_field->db_name=(char*)"";
- tmp_field->org_table_name=tmp_field->table_name=(char*)"";
- tmp_field->org_col_name=tmp_field->col_name=name;
+ /* For expressions only col_name should be non-empty string. */
+ char *empty_string= (char*)"";
+ tmp_field->db_name= empty_string;
+ tmp_field->org_table_name= empty_string;
+ tmp_field->table_name= empty_string;
+ tmp_field->org_col_name= empty_string;
+ tmp_field->col_name= name;
if (maybe_null)
tmp_field->flags&= ~NOT_NULL_FLAG;
}
@@ -1050,7 +1054,7 @@ bool Item_sum_count::add()
count++;
else
{
- (void) args[0]->val_int();
+ args[0]->update_null_value();
if (!args[0]->null_value)
count++;
}
@@ -1067,6 +1071,7 @@ longlong Item_sum_count::val_int()
void Item_sum_count::cleanup()
{
DBUG_ENTER("Item_sum_count::cleanup");
+ count= 0;
Item_sum_int::cleanup();
used_table_cache= ~(table_map) 0;
DBUG_VOID_RETURN;
@@ -1956,7 +1961,7 @@ void Item_sum_count::reset_field()
nr=1;
else
{
- (void) args[0]->val_int();
+ args[0]->update_null_value();
if (!args[0]->null_value)
nr=1;
}
@@ -2066,7 +2071,7 @@ void Item_sum_count::update_field()
nr++;
else
{
- (void) args[0]->val_int();
+ args[0]->update_null_value();
if (!args[0]->null_value)
nr++;
}
@@ -2546,7 +2551,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
return TRUE; // End of memory
if (item->const_item())
{
- (void) item->val_int();
+ item->update_null_value();
if (item->null_value)
always_null=1;
}
@@ -2694,6 +2699,7 @@ bool Item_sum_count_distinct::add()
longlong Item_sum_count_distinct::val_int()
{
+ int error;
DBUG_ASSERT(fixed == 1);
if (!table) // Empty query
return LL(0);
@@ -2709,7 +2715,14 @@ longlong Item_sum_count_distinct::val_int()
is_evaluated= TRUE;
return (longlong) count;
}
- table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+
+ error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+
+ if(error)
+ {
+ table->file->print_error(error, MYF(0));
+ }
+
return table->file->records;
}
@@ -3013,6 +3026,7 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
String tmp2;
String *result= &item->result;
Item **arg= item->args, **arg_end= item->args + item->arg_count_field;
+ uint old_length= result->length();
if (item->no_appended)
item->no_appended= FALSE;
@@ -3047,8 +3061,22 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)),
/* stop if length of result more than max_length */
if (result->length() > item->max_length)
{
+ int well_formed_error;
+ CHARSET_INFO *cs= item->collation.collation;
+ const char *ptr= result->ptr();
+ uint add_length;
+ /*
+ It's ok to use item->result.length() as the fourth argument
+ as this is never used to limit the length of the data.
+ Cut is done with the third argument.
+ */
+ add_length= cs->cset->well_formed_len(cs,
+ ptr + old_length,
+ ptr + item->max_length,
+ result->length(),
+ &well_formed_error);
+ result->length(old_length + add_length);
item->count_cut_values++;
- result->length(item->max_length);
item->warning_for_row= TRUE;
return 1;
}
@@ -3238,8 +3266,7 @@ bool Item_func_group_concat::add()
we can dump the row here in case of GROUP_CONCAT(DISTINCT...)
instead of doing tree traverse later.
*/
- if (result.length() <= max_length &&
- !warning_for_row &&
+ if (!warning_for_row &&
(!tree || (el->count == 1 && distinct && !arg_count_order)))
dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this);
@@ -3308,7 +3335,8 @@ bool Item_func_group_concat::setup(THD *thd)
DBUG_RETURN(TRUE);
/* We'll convert all blobs to varchar fields in the temporary table */
- tmp_table_param->convert_blob_length= max_length;
+ tmp_table_param->convert_blob_length= max_length *
+ collation.collation->mbmaxlen;
/* Push all not constant fields to the list and create a temp table */
always_null= 0;
for (uint i= 0; i < arg_count_field; i++)
@@ -3385,8 +3413,8 @@ bool Item_func_group_concat::setup(THD *thd)
duplicate values (according to the syntax of this function). If there
is no DISTINCT or ORDER BY clauses, we don't create this tree.
*/
- init_tree(tree, min(thd->variables.max_heap_table_size,
- thd->variables.sortbuff_size/16), 0,
+ init_tree(tree, (uint) min(thd->variables.max_heap_table_size,
+ thd->variables.sortbuff_size/16), 0,
tree_key_length, compare_key, 0, NULL, (void*) this);
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index a2b2f7cab92..ad05b3c9d12 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -260,9 +260,30 @@ public:
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;
+
/*
Called when new group is started and results are being saved in
a temporary table. Similar to reset(), but must also store value in
@@ -306,7 +327,17 @@ public:
void make_field(Send_field *field);
void print(String *str);
void fix_num_length_and_dec();
- void no_rows_in_result() { reset(); }
+
+ /*
+ 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
+ the default value of the item after 'clear()': e.g. a numeric item
+ 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() {}
Item *get_tmp_table_item(THD *thd);
@@ -587,7 +618,7 @@ public:
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
- bool is_null() { (void) val_int(); return null_value; }
+ bool is_null() { update_null_value(); return null_value; }
String *val_str(String*);
enum_field_types field_type() const
{
@@ -628,6 +659,11 @@ public:
const char *func_name() const { return "avg("; }
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
+ void cleanup()
+ {
+ count= 0;
+ Item_sum_sum::cleanup();
+ }
};
class Item_sum_variance;
@@ -649,7 +685,7 @@ public:
{ /* can't be fix_fields()ed */ return (longlong) rint(val_real()); }
String *val_str(String*);
my_decimal *val_decimal(my_decimal *);
- bool is_null() { (void) val_int(); return null_value; }
+ bool is_null() { update_null_value(); return null_value; }
enum_field_types field_type() const
{
return hybrid_type == DECIMAL_RESULT ?
@@ -707,6 +743,12 @@ public:
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
enum Item_result result_type () const { return REAL_RESULT; }
+ void cleanup()
+ {
+ cur_dec= 0;
+ count= 0;
+ Item_sum_num::cleanup();
+ }
};
class Item_sum_std;
@@ -837,6 +879,11 @@ public:
void update_field();
void fix_length_and_dec()
{ decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; }
+ void cleanup()
+ {
+ bits= reset_bits;
+ Item_sum_int::cleanup();
+ }
};
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 1aa93b9ba8e..ca593664299 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -96,6 +96,124 @@ static bool make_datetime(date_time_format_types format, TIME *ltime,
/*
+ Wrapper over make_datetime() with validation of the input TIME value
+
+ NOTE
+ see make_datetime() for more information
+
+ RETURN
+ 1 if there was an error during converion
+ 0 otherwise
+*/
+
+static bool make_datetime_with_warn(date_time_format_types format, TIME *ltime,
+ String *str)
+{
+ int warning= 0;
+
+ if (make_datetime(format, ltime, str))
+ return 1;
+ if (check_time_range(ltime, &warning))
+ return 1;
+ if (!warning)
+ return 0;
+
+ make_truncated_value_warning(current_thd, str->ptr(), str->length(),
+ MYSQL_TIMESTAMP_TIME, NullS);
+ return make_datetime(format, ltime, str);
+}
+
+
+/*
+ Wrapper over make_time() with validation of the input TIME value
+
+ NOTE
+ see make_time() for more info
+
+ RETURN
+ 1 if there was an error during conversion
+ 0 otherwise
+*/
+
+static bool make_time_with_warn(const DATE_TIME_FORMAT *format,
+ TIME *l_time, String *str)
+{
+ int warning= 0;
+ make_time(format, l_time, str);
+ if (check_time_range(l_time, &warning))
+ return 1;
+ if (warning)
+ {
+ make_truncated_value_warning(current_thd, str->ptr(), str->length(),
+ MYSQL_TIMESTAMP_TIME, NullS);
+ make_time(format, l_time, str);
+ }
+
+ return 0;
+}
+
+
+/*
+ Convert seconds to TIME value with overflow checking
+
+ SYNOPSIS:
+ sec_to_time()
+ seconds number of seconds
+ unsigned_flag 1, if 'seconds' is unsigned, 0, otherwise
+ ltime output TIME value
+
+ DESCRIPTION
+ If the 'seconds' argument is inside TIME data range, convert it to a
+ corresponding value.
+ Otherwise, truncate the resulting value to the nearest endpoint, and
+ produce a warning message.
+
+ RETURN
+ 1 if the value was truncated during conversion
+ 0 otherwise
+*/
+
+static bool sec_to_time(longlong seconds, bool unsigned_flag, TIME *ltime)
+{
+ uint sec;
+
+ bzero((char *)ltime, sizeof(*ltime));
+
+ if (seconds < 0)
+ {
+ if (unsigned_flag)
+ goto overflow;
+ ltime->neg= 1;
+ if (seconds < -3020399)
+ goto overflow;
+ seconds= -seconds;
+ }
+ else if (seconds > 3020399)
+ goto overflow;
+
+ sec= (uint) ((ulonglong) seconds % 3600);
+ ltime->hour= (uint) (seconds/3600);
+ ltime->minute= sec/60;
+ ltime->second= sec % 60;
+
+ return 0;
+
+overflow:
+ ltime->hour= TIME_MAX_HOUR;
+ ltime->minute= TIME_MAX_MINUTE;
+ ltime->second= TIME_MAX_SECOND;
+
+ char buf[22];
+ int len= (int)(longlong10_to_str(seconds, buf, unsigned_flag ? 10 : -10)
+ - buf);
+ make_truncated_value_warning(current_thd, buf, len, MYSQL_TIMESTAMP_TIME,
+ NullS);
+
+ return 1;
+}
+
+
+/*
Date formats corresponding to compound %r and %T conversion specifiers
Note: We should init at least first element of "positions" array
@@ -1526,7 +1644,7 @@ double Item_func_sysdate_local::val_real()
{
DBUG_ASSERT(fixed == 1);
store_now_in_TIME(&ltime);
- return (longlong) TIME_to_ulonglong_datetime(&ltime);
+ return (double) TIME_to_ulonglong_datetime(&ltime);
}
@@ -1559,8 +1677,6 @@ int Item_func_sysdate_local::save_in_field(Field *to, bool no_conversions)
String *Item_func_sec_to_time::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- longlong seconds=(longlong) args[0]->val_int();
- uint sec;
TIME ltime;
if ((null_value=args[0]->null_value) || str->alloc(19))
@@ -1569,19 +1685,8 @@ String *Item_func_sec_to_time::val_str(String *str)
return (String*) 0;
}
- ltime.neg= 0;
- if (seconds < 0)
- {
- seconds= -seconds;
- ltime.neg= 1;
- }
-
- sec= (uint) ((ulonglong) seconds % 3600);
- ltime.day= 0;
- ltime.hour= (uint) (seconds/3600);
- ltime.minute= sec/60;
- ltime.second= sec % 60;
-
+ sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, &ltime);
+
make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
return str;
}
@@ -1590,16 +1695,15 @@ String *Item_func_sec_to_time::val_str(String *str)
longlong Item_func_sec_to_time::val_int()
{
DBUG_ASSERT(fixed == 1);
- longlong seconds=args[0]->val_int();
- longlong sign=1;
+ TIME ltime;
+
if ((null_value=args[0]->null_value))
return 0;
- if (seconds < 0)
- {
- seconds= -seconds;
- sign= -1;
- }
- return sign*((seconds / 3600)*10000+((seconds/60) % 60)*100+ (seconds % 60));
+
+ sec_to_time(args[0]->val_int(), args[0]->unsigned_flag, &ltime);
+
+ return (ltime.neg ? -1 : 1) *
+ ((ltime.hour)*10000 + ltime.minute*100 + ltime.second);
}
@@ -1919,17 +2023,14 @@ bool Item_func_convert_tz::get_date(TIME *ltime,
return 1;
}
- /* Check if we in range where we treat datetime values as non-UTC */
- if (ltime->year < TIMESTAMP_MAX_YEAR && ltime->year > TIMESTAMP_MIN_YEAR ||
- ltime->year==TIMESTAMP_MAX_YEAR && ltime->month==1 && ltime->day==1 ||
- ltime->year==TIMESTAMP_MIN_YEAR && ltime->month==12 && ltime->day==31)
{
my_bool not_used;
my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, &not_used);
- if (my_time_tmp >= TIMESTAMP_MIN_VALUE && my_time_tmp <= TIMESTAMP_MAX_VALUE)
+ /* my_time_tmp is guranteed to be in the allowed range */
+ if (my_time_tmp)
to_tz->gmt_sec_to_TIME(ltime, my_time_tmp);
}
-
+
null_value= 0;
return 0;
}
@@ -2140,11 +2241,15 @@ bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
(date_sub_interval == other->date_sub_interval));
}
+/*
+ 'interval_names' reflects the order of the enumeration interval_type.
+ See item_timefunc.h
+ */
static const char *interval_names[]=
{
- "year", "quarter", "month", "day", "hour",
- "minute", "week", "second", "microsecond",
+ "year", "quarter", "month", "week", "day",
+ "hour", "minute", "second", "microsecond",
"year_month", "day_hour", "day_minute",
"day_second", "hour_minute", "hour_second",
"minute_second", "day_microsecond",
@@ -2381,7 +2486,8 @@ String *Item_char_typecast::val_str(String *str)
{ // Safe even if const arg
char char_type[40];
my_snprintf(char_type, sizeof(char_type), "%s(%lu)",
- cast_cs == &my_charset_bin ? "BINARY" : "CHAR", length);
+ cast_cs == &my_charset_bin ? "BINARY" : "CHAR",
+ (ulong) length);
if (!res->alloced_length())
{ // Don't change const str
@@ -2681,7 +2787,9 @@ String *Item_func_add_time::val_str(String *str)
}
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
-
+
+ bzero((char *)&l_time3, sizeof(l_time3));
+
l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
&seconds, &microseconds);
@@ -2710,9 +2818,9 @@ String *Item_func_add_time::val_str(String *str)
}
l_time3.hour+= days*24;
- if (!make_datetime(l_time1.second_part || l_time2.second_part ?
- TIME_MICROSECOND : TIME_ONLY,
- &l_time3, str))
+ if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY,
+ &l_time3, str))
return str;
null_date:
@@ -2767,6 +2875,8 @@ String *Item_func_timediff::val_str(String *str)
if (l_time1.neg != l_time2.neg)
l_sign= -l_sign;
+ bzero((char *)&l_time3, sizeof(l_time3));
+
l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
&seconds, &microseconds);
@@ -2780,9 +2890,9 @@ String *Item_func_timediff::val_str(String *str)
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
- if (!make_datetime(l_time1.second_part || l_time2.second_part ?
- TIME_MICROSECOND : TIME_ONLY,
- &l_time3, str))
+ if (!make_datetime_with_warn(l_time1.second_part || l_time2.second_part ?
+ TIME_MICROSECOND : TIME_ONLY,
+ &l_time3, str))
return str;
null_date:
@@ -2800,29 +2910,58 @@ String *Item_func_maketime::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
TIME ltime;
+ bool overflow= 0;
- long hour= (long) args[0]->val_int();
- long minute= (long) args[1]->val_int();
- long second= (long) args[2]->val_int();
+ longlong hour= args[0]->val_int();
+ longlong minute= args[1]->val_int();
+ longlong second= args[2]->val_int();
if ((null_value=(args[0]->null_value ||
- args[1]->null_value ||
- args[2]->null_value ||
- minute > 59 || minute < 0 ||
- second > 59 || second < 0 ||
- str->alloc(19))))
+ args[1]->null_value ||
+ args[2]->null_value ||
+ minute < 0 || minute > 59 ||
+ second < 0 || second > 59 ||
+ str->alloc(19))))
return 0;
+ bzero((char *)&ltime, sizeof(ltime));
ltime.neg= 0;
+
+ /* Check for integer overflows */
if (hour < 0)
{
- ltime.neg= 1;
- hour= -hour;
+ if (args[0]->unsigned_flag)
+ overflow= 1;
+ else
+ ltime.neg= 1;
+ }
+ if (-hour > UINT_MAX || hour > UINT_MAX)
+ overflow= 1;
+
+ if (!overflow)
+ {
+ ltime.hour= (uint) ((hour < 0 ? -hour : hour));
+ ltime.minute= (uint) minute;
+ ltime.second= (uint) second;
+ }
+ else
+ {
+ ltime.hour= TIME_MAX_HOUR;
+ ltime.minute= TIME_MAX_MINUTE;
+ ltime.second= TIME_MAX_SECOND;
+ char buf[28];
+ char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10);
+ int len = (int)(ptr - buf) +
+ my_sprintf(ptr, (ptr, ":%02u:%02u", (uint)minute, (uint)second));
+ make_truncated_value_warning(current_thd, buf, len, MYSQL_TIMESTAMP_TIME,
+ NullS);
+ }
+
+ if (make_time_with_warn((DATE_TIME_FORMAT *) 0, &ltime, str))
+ {
+ null_value= 1;
+ return 0;
}
- ltime.hour= (ulong) hour;
- ltime.minute= (ulong) minute;
- ltime.second= (ulong) second;
- make_time((DATE_TIME_FORMAT *) 0, &ltime, str);
return str;
}
@@ -3178,7 +3317,7 @@ bool Item_func_str_to_date::get_date(TIME *ltime, uint fuzzy_date)
goto null_date;
null_value= 0;
- bzero((char*) ltime, sizeof(ltime));
+ bzero((char*) ltime, sizeof(*ltime));
date_time_format.format.str= (char*) format->ptr();
date_time_format.format.length= format->length();
if (extract_date_time(&date_time_format, val->ptr(), val->length(),
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 29978cf60a3..68e8700d1b0 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -669,18 +669,21 @@ public:
};
/*
- The following must be sorted so that simple intervals comes first.
- (get_interval_value() depends on this)
+ 'interval_type' must be sorted so that simple intervals comes first,
+ ie year, quarter, month, week, day, hour, etc. The order based on
+ interval size is also important and the intervals should be kept in a
+ large to smaller order. (get_interval_value() depends on this)
*/
enum interval_type
{
- INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR,
- INTERVAL_MINUTE, INTERVAL_WEEK, INTERVAL_SECOND, INTERVAL_MICROSECOND ,
- INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
- INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
- INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND,
- INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND
+ INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK,
+ INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND,
+ INTERVAL_MICROSECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
+ INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE,
+ INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND,
+ INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND,
+ INTERVAL_SECOND_MICROSECOND
};
class Item_date_add_interval :public Item_date_func
diff --git a/sql/log.cc b/sql/log.cc
index 960fc4f60c2..71bdecdc536 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1676,14 +1676,14 @@ bool MYSQL_LOG::write(Log_event *event_info)
}
trans_log->end_of_file= max_binlog_cache_size;
trans_register_ha(thd,
- thd->options & (OPTION_NOT_AUTOCOMMIT |
- OPTION_BEGIN),
+ test(thd->options & (OPTION_NOT_AUTOCOMMIT |
+ OPTION_BEGIN)),
&binlog_hton);
}
else if (!my_b_tell(trans_log))
trans_register_ha(thd,
- thd->options & (OPTION_NOT_AUTOCOMMIT |
- OPTION_BEGIN),
+ test(thd->options & (OPTION_NOT_AUTOCOMMIT |
+ OPTION_BEGIN)),
&binlog_hton);
file= trans_log;
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 271658d8054..0d7ef7e8f2a 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -727,7 +727,7 @@ Log_event* Log_event::read_log_event(IO_CACHE* file,
LOG_EVENT_MINIMAL_HEADER_LEN);
LOCK_MUTEX;
- DBUG_PRINT("info", ("my_b_tell=%lu", my_b_tell(file)));
+ DBUG_PRINT("info", ("my_b_tell: %lu", (ulong) my_b_tell(file)));
if (my_b_read(file, (byte *) head, header_size))
{
DBUG_PRINT("info", ("Log_event::read_log_event(IO_CACHE*,Format_desc*) \
@@ -1212,6 +1212,7 @@ bool Query_log_event::write(IO_CACHE* file)
/* Store length of status variables */
status_vars_len= (uint) (start-start_of_status);
+ DBUG_ASSERT(status_vars_len <= MAX_SIZE_LOG_EVENT_STATUS);
int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len);
/*
@@ -1297,7 +1298,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
}
else
time_zone_len= 0;
- DBUG_PRINT("info",("Query_log_event has flags2=%lu sql_mode=%lu",flags2,sql_mode));
+ DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %lu",
+ (ulong) flags2, sql_mode));
}
#endif /* MYSQL_CLIENT */
@@ -1345,7 +1347,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
common_header_len= description_event->common_header_len;
post_header_len= description_event->post_header_len[event_type-1];
- DBUG_PRINT("info",("event_len=%ld, common_header_len=%d, post_header_len=%d",
+ DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d",
event_len, common_header_len, post_header_len));
/*
@@ -1393,7 +1395,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
case Q_FLAGS2_CODE:
flags2_inited= 1;
flags2= uint4korr(pos);
- DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", flags2));
+ DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", (ulong) flags2));
pos+= 4;
break;
case Q_SQL_MODE_CODE:
@@ -3137,8 +3139,8 @@ Rotate_log_event::Rotate_log_event(THD* thd_arg,
#ifndef DBUG_OFF
char buff[22];
DBUG_ENTER("Rotate_log_event::Rotate_log_event(THD*,...)");
- DBUG_PRINT("enter",("new_log_ident %s pos %s flags %lu", new_log_ident_arg,
- llstr(pos_arg, buff), flags));
+ DBUG_PRINT("enter",("new_log_ident: %s pos: %s flags: %lu", new_log_ident_arg,
+ llstr(pos_arg, buff), (ulong) flags));
#endif
if (flags & DUP_NAME)
new_log_ident= my_strdup_with_length(new_log_ident_arg,
@@ -3912,7 +3914,7 @@ Slave_log_event::Slave_log_event(THD* thd_arg,
memcpy(master_log, rli->group_master_log_name, master_log_len + 1);
master_port = mi->port;
master_pos = rli->group_master_log_pos;
- DBUG_PRINT("info", ("master_log: %s pos: %d", master_log,
+ DBUG_PRINT("info", ("master_log: %s pos: %lu", master_log,
(ulong) master_pos));
}
else
diff --git a/sql/log_event.h b/sql/log_event.h
index f1b441dedb1..247e1962776 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -200,8 +200,26 @@ struct sql_ex_info
#define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1)
#define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)
-/*
- Event header offsets;
+/*
+ Max number of possible extra bytes in a replication event compared to a
+ packet (i.e. a query) sent from client to master;
+ First, an auxiliary log_event status vars estimation:
+*/
+#define MAX_SIZE_LOG_EVENT_STATUS (4 /* flags2 */ + \
+ 8 /* sql mode */ + \
+ 1 + 1 + 255 /* catalog */ + \
+ 4 /* autoinc */ + \
+ 6 /* charset */ + \
+ MAX_TIME_ZONE_NAME_LENGTH)
+#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \
+ LOG_EVENT_HEADER_LEN + /* write_header */ \
+ QUERY_HEADER_LEN + /* write_data */ \
+ EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \
+ MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
+ NAME_LEN + 1)
+
+/*
+ Event header offsets;
these point to places inside the fixed header.
*/
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index a556f190fdf..c5ec6f02cdd 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -96,6 +96,17 @@ extern CHARSET_INFO *system_charset_info, *files_charset_info ;
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
+enum Derivation
+{
+ DERIVATION_IGNORABLE= 5,
+ DERIVATION_COERCIBLE= 4,
+ DERIVATION_SYSCONST= 3,
+ DERIVATION_IMPLICIT= 2,
+ DERIVATION_NONE= 1,
+ DERIVATION_EXPLICIT= 0
+};
+
+
typedef struct my_locale_st
{
const char *name;
@@ -131,6 +142,8 @@ MY_LOCALE *my_locale_by_name(const char *name);
#define MAX_ACCEPT_RETRY 10 // Test accept this many times
#define MAX_FIELDS_BEFORE_HASH 32
#define USER_VARS_HASH_SIZE 16
+#define TABLE_OPEN_CACHE_MIN 64
+#define TABLE_OPEN_CACHE_DEFAULT 64
/*
Value of 9236 discovered through binary search 2006-09-26 on Ubuntu Dapper
@@ -210,12 +223,6 @@ MY_LOCALE *my_locale_by_name(const char *name);
/* Characters shown for the command in 'show processlist' */
#define PROCESS_LIST_WIDTH 100
-/* Time handling defaults */
-#define TIMESTAMP_MAX_YEAR 2038
-#define YY_PART_YEAR 70
-#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1)
-#define TIMESTAMP_MAX_VALUE 2145916799
-#define TIMESTAMP_MIN_VALUE 1
#define PRECISION_FOR_DOUBLE 53
#define PRECISION_FOR_FLOAT 24
@@ -738,7 +745,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
bool mysql_select(THD *thd, Item ***rref_pointer_array,
TABLE_LIST *tables, uint wild_num, List<Item> &list,
COND *conds, uint og_num, ORDER *order, ORDER *group,
- Item *having, ORDER *proc_param, ulong select_type,
+ Item *having, ORDER *proc_param, ulonglong select_type,
select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex);
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 1dd15398cd1..df1b7f1dd70 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -70,6 +70,12 @@
#define IF_PURIFY(A,B) (B)
#endif
+#if SIZEOF_CHARP == 4
+#define MAX_MEM_TABLE_SIZE ~(ulong) 0
+#else
+#define MAX_MEM_TABLE_SIZE ~(ulonglong) 0
+#endif
+
/* stack traces are only supported on linux intel */
#if defined(__linux__) && defined(__i386__) && defined(USE_PSTACK)
#define HAVE_STACK_TRACE_ON_SEGV
@@ -1531,8 +1537,8 @@ static void network_init(void)
if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
{
- sql_print_error("The socket file path is too long (> %lu): %s",
- sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
+ sql_print_error("The socket file path is too long (> %u): %s",
+ (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
unireg_abort(1);
}
if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
@@ -2641,19 +2647,43 @@ static int init_common_variables(const char *conf_file_name, int argc,
/* connections and databases needs lots of files */
{
- uint files, wanted_files;
+ uint files, wanted_files, max_open_files;
- wanted_files= 10+(uint) max(max_connections*5,
- max_connections+table_cache_size*2);
- set_if_bigger(wanted_files, open_files_limit);
- files= my_set_max_open_files(wanted_files);
+ /* MyISAM requires two file handles per table. */
+ wanted_files= 10+max_connections+table_cache_size*2;
+ /*
+ We are trying to allocate no less than max_connections*5 file
+ handles (i.e. we are trying to set the limit so that they will
+ be available). In addition, we allocate no less than how much
+ was already allocated. However below we report a warning and
+ recompute values only if we got less file handles than were
+ explicitly requested. No warning and re-computation occur if we
+ can't get max_connections*5 but still got no less than was
+ requested (value of wanted_files).
+ */
+ max_open_files= max(max(wanted_files, max_connections*5),
+ open_files_limit);
+ files= my_set_max_open_files(max_open_files);
if (files < wanted_files)
{
if (!open_files_limit)
{
- max_connections= (ulong) min((files-10),max_connections);
- table_cache_size= (ulong) max((files-10-max_connections)/2,64);
+ /*
+ If we have requested too much file handles than we bring
+ max_connections in supported bounds.
+ */
+ max_connections= (ulong) min(files-10-TABLE_OPEN_CACHE_MIN*2,
+ max_connections);
+ /*
+ Decrease table_cache_size according to max_connections, but
+ not below TABLE_OPEN_CACHE_MIN. Outer min() ensures that we
+ never increase table_cache_size automatically (that could
+ happen if max_connections is decreased above).
+ */
+ table_cache_size= (ulong) min(max((files-10-max_connections)/2,
+ TABLE_OPEN_CACHE_MIN),
+ table_cache_size);
DBUG_PRINT("warning",
("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
files, max_connections, table_cache_size));
@@ -3354,8 +3384,8 @@ int main(int argc, char **argv)
if (stack_size && stack_size < thread_stack)
{
if (global_system_variables.log_warnings)
- sql_print_warning("Asked for %ld thread stack, but got %ld",
- thread_stack, stack_size);
+ sql_print_warning("Asked for %lu thread stack, but got %ld",
+ thread_stack, (long) stack_size);
#if defined(__ia64__) || defined(__ia64)
thread_stack= stack_size*2;
#else
@@ -3889,7 +3919,7 @@ static void create_new_thread(THD *thd)
int error;
thread_created++;
threads.append(thd);
- DBUG_PRINT("info",(("creating thread %d"), thd->thread_id));
+ DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
thd->connect_time = time(NULL);
if ((error=pthread_create(&thd->real_id,&connection_attrib,
handle_one_connection,
@@ -5106,7 +5136,7 @@ master-ssl",
(gptr*) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"merge", OPT_MERGE, "Enable Merge storage engine. Disable with \
--skip-merge.",
- (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0},
+ (gptr*) &opt_merge, (gptr*) &opt_merge, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"myisam-recover", OPT_MYISAM_RECOVER,
"Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.",
(gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
@@ -5694,8 +5724,9 @@ The minimum value for this variable is 4096.",
{"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE,
"Don't allow creation of heap tables bigger than this.",
(gptr*) &global_system_variables.max_heap_table_size,
- (gptr*) &max_system_variables.max_heap_table_size, 0, GET_ULONG,
- REQUIRED_ARG, 16*1024*1024L, 16384, ~0L, MALLOC_OVERHEAD, 1024, 0},
+ (gptr*) &max_system_variables.max_heap_table_size, 0, GET_ULL,
+ REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE,
+ MALLOC_OVERHEAD, 1024, 0},
{"max_join_size", OPT_MAX_JOIN_SIZE,
"Joins that are probably going to read more than max_join_size records return an error.",
(gptr*) &global_system_variables.max_join_size,
@@ -5943,8 +5974,8 @@ The minimum value for this variable is 4096.",
0, 0, 0, 0},
{"table_cache", OPT_TABLE_CACHE,
"The number of open tables for all threads.", (gptr*) &table_cache_size,
- (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L,
- 0, 1, 0},
+ (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG,
+ TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
{"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT, "Timeout in "
"seconds to wait for a table level lock before returning an error. Used"
" only if the connection has active cursors.",
@@ -5970,8 +6001,8 @@ The minimum value for this variable is 4096.",
{"tmp_table_size", OPT_TMP_TABLE_SIZE,
"If an in-memory temporary table exceeds this size, MySQL will automatically convert it to an on-disk MyISAM table.",
(gptr*) &global_system_variables.tmp_table_size,
- (gptr*) &max_system_variables.tmp_table_size, 0, GET_ULONG,
- REQUIRED_ARG, 32*1024*1024L, 1024, ~0L, 0, 1, 0},
+ (gptr*) &max_system_variables.tmp_table_size, 0, GET_ULL,
+ REQUIRED_ARG, 32*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0},
{"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
"Allocation block size for transactions to be stored in binary log",
(gptr*) &global_system_variables.trans_alloc_block_size,
@@ -5997,6 +6028,10 @@ The minimum value for this variable is 4096.",
};
+/*
+ Variables shown by SHOW STATUS in alphabetical order
+*/
+
struct show_var_st status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
@@ -6149,6 +6184,7 @@ struct show_var_st status_vars[]= {
{"Open_streams", (char*) &my_stream_opened, SHOW_LONG_CONST},
{"Open_tables", (char*) 0, SHOW_OPENTABLES},
{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
+ {"Prepared_stmt_count", (char*) &prepared_stmt_count, SHOW_LONG_CONST},
#ifdef HAVE_QUERY_CACHE
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_CONST},
{"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_CONST},
@@ -6318,6 +6354,7 @@ static void mysql_init_variables(void)
binlog_cache_use= binlog_cache_disk_use= 0;
max_used_connections= slow_launch_threads = 0;
mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
+ prepared_stmt_count= 0;
errmesg= 0;
mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
@@ -7466,15 +7503,19 @@ void refresh_status(THD *thd)
{
pthread_mutex_lock(&LOCK_status);
- /* We must update the global status before cleaning up the thread */
+ /* Add thread's status variabes to global status */
add_to_status(&global_status_var, &thd->status_var);
+
+ /* Reset thread's status variables */
bzero((char*) &thd->status_var, sizeof(thd->status_var));
+ /* Reset some global variables */
for (struct show_var_st *ptr=status_vars; ptr->name; ptr++)
{
if (ptr->type == SHOW_LONG)
*(ulong*) ptr->value= 0;
}
+
/* Reset the counters of all key caches (default and named). */
process_key_caches(reset_key_cache_counters);
pthread_mutex_unlock(&LOCK_status);
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 1601f7e5177..e84b2266e82 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -810,7 +810,7 @@ my_real_read(NET *net, ulong *complen)
{
my_bool interrupted = vio_should_retry(net->vio);
- DBUG_PRINT("info",("vio_read returned %d, errno: %d",
+ DBUG_PRINT("info",("vio_read returned %ld, errno: %d",
length, vio_errno(net->vio)));
#if (!defined(__WIN__) && !defined(__EMX__) && !defined(OS2)) || defined(MYSQL_SERVER)
/*
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index d68ea0abfe7..23a82c6eda7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -878,7 +878,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
file->extra(HA_EXTRA_NO_KEYREAD);
if (free_file)
{
- DBUG_PRINT("info", ("Freeing separate handler %p (free=%d)", file,
+ DBUG_PRINT("info", ("Freeing separate handler 0x%lx (free: %d)", (long) file,
free_file));
file->reset();
file->external_lock(current_thd, F_UNLCK);
@@ -1836,9 +1836,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
double scan_time;
DBUG_ENTER("SQL_SELECT::test_quick_select");
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
- keys_to_use.to_ulonglong(), (ulong) prev_tables,
+ (ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables,
(ulong) const_tables));
- DBUG_PRINT("info", ("records=%lu", (ulong)head->file->records));
+ DBUG_PRINT("info", ("records: %lu", (ulong) head->file->records));
delete quick;
quick=0;
needed_reg.clear_all();
@@ -1924,6 +1924,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
key_parts->null_bit= key_part_info->null_bit;
key_parts->image_type =
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
+ key_parts->flag= (uint8) key_part_info->key_part_flag;
}
param.real_keynr[param.keys++]=idx;
}
@@ -2101,7 +2102,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(records)));
if (busy_blocks < 1.0)
busy_blocks= 1.0;
- DBUG_PRINT("info",("sweep: nblocks=%g, busy_blocks=%g", n_blocks,
+ DBUG_PRINT("info",("sweep: nblocks: %g, busy_blocks: %g", n_blocks,
busy_blocks));
/*
Disabled: Bail out if # of blocks to read is bigger than # of blocks in
@@ -2125,7 +2126,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
result= busy_blocks;
}
}
- DBUG_PRINT("info",("returning cost=%g", result));
+ DBUG_PRINT("return",("cost: %g", result));
DBUG_RETURN(result);
}
@@ -2219,7 +2220,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
ha_rows roru_total_records;
double roru_intersect_part= 1.0;
DBUG_ENTER("get_best_disjunct_quick");
- DBUG_PRINT("info", ("Full table scan cost =%g", read_time));
+ DBUG_PRINT("info", ("Full table scan cost: %g", read_time));
if (!(range_scans= (TRP_RANGE**)alloc_root(param->mem_root,
sizeof(TRP_RANGE*)*
@@ -2263,7 +2264,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
non_cpk_scan_records += (*cur_child)->records;
}
- DBUG_PRINT("info", ("index_merge scans cost=%g", imerge_cost));
+ DBUG_PRINT("info", ("index_merge scans cost %g", imerge_cost));
if (imerge_too_expensive || (imerge_cost > read_time) ||
(non_cpk_scan_records+cpk_scan_records >= param->table->file->records) &&
read_time != DBL_MAX)
@@ -2876,7 +2877,7 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
DBUG_PRINT("info", ("Current out_rows= %g", info->out_rows));
DBUG_PRINT("info", ("Adding scan on %s",
info->param->table->key_info[ror_scan->keynr].name));
- DBUG_PRINT("info", ("is_cpk_scan=%d",is_cpk_scan));
+ DBUG_PRINT("info", ("is_cpk_scan: %d",is_cpk_scan));
selectivity_mult = ror_scan_selectivity(info, ror_scan);
if (selectivity_mult == 1.0)
@@ -4347,7 +4348,9 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
}
break;
case Item_func::GT_FUNC:
- if (field_is_equal_to_item(field,value))
+ /* Don't use open ranges for partial key_segments */
+ if (field_is_equal_to_item(field,value) &&
+ !(key_part->flag & HA_PART_KEY_SEG))
tree->min_flag=NEAR_MIN;
/* fall through */
case Item_func::GE_FUNC:
@@ -6237,6 +6240,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
key_part->length= key_info->key_part[part].length;
key_part->store_length= key_info->key_part[part].store_length;
key_part->null_bit= key_info->key_part[part].null_bit;
+ key_part->flag= (uint8) key_info->key_part[part].key_part_flag;
}
if (insert_dynamic(&quick->ranges,(gptr)&range))
goto err;
@@ -7441,7 +7445,7 @@ static TRP_GROUP_MIN_MAX *
get_best_group_min_max(PARAM *param, SEL_TREE *tree)
{
THD *thd= param->thd;
- JOIN *join= thd->lex->select_lex.join;
+ JOIN *join= thd->lex->current_select->join;
TABLE *table= param->table;
bool have_min= FALSE; /* TRUE if there is a MIN function. */
bool have_max= FALSE; /* TRUE if there is a MAX function. */
@@ -7462,7 +7466,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
DBUG_ENTER("get_best_group_min_max");
/* Perform few 'cheap' tests whether this access method is applicable. */
- if (!join || (thd->lex->sql_command != SQLCOM_SELECT))
+ 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. */
@@ -8276,8 +8280,8 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
*records= num_groups;
DBUG_PRINT("info",
- ("table rows=%u, keys/block=%u, keys/group=%u, result rows=%u, blocks=%u",
- table_records, keys_per_block, keys_per_group, *records,
+ ("table rows: %u keys/block: %u keys/group: %u result rows: %lu blocks: %u",
+ table_records, keys_per_block, keys_per_group, (ulong) *records,
num_blocks));
DBUG_VOID_RETURN;
}
@@ -8312,7 +8316,7 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
DBUG_ENTER("TRP_GROUP_MIN_MAX::make_quick");
quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
- param->thd->lex->select_lex.join,
+ param->thd->lex->current_select->join,
have_min, have_max, min_max_arg_part,
group_prefix_len, used_key_parts,
index_info, index, read_cost, records,
diff --git a/sql/opt_range.h b/sql/opt_range.h
index ddc959f1cdf..f22b157df86 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -26,7 +26,7 @@
typedef struct st_key_part {
uint16 key,part, store_length, length;
- uint8 null_bit;
+ uint8 null_bit, flag;
Field *field;
Field::imagetype image_type;
} KEY_PART;
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index d17c42bca38..fc4edabc4a4 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -134,7 +134,12 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
else
{
- tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ if(error)
+ {
+ tl->table->file->print_error(error, MYF(0));
+ return error;
+ }
count*= tl->table->file->records;
}
}
diff --git a/sql/parse_file.h b/sql/parse_file.h
index 33871588e11..5fb65b4c7ec 100644
--- a/sql/parse_file.h
+++ b/sql/parse_file.h
@@ -107,4 +107,20 @@ public:
bool bad_format_errors);
};
+
+/*
+ Custom version of standard offsetof() macro which can be used to get
+ offsets of members in class for non-POD types (according to the current
+ version of C++ standard offsetof() macro can't be used in such cases and
+ attempt to do so causes warnings to be emitted, OTOH in many cases it is
+ still OK to assume that all instances of the class has the same offsets
+ for the same members).
+
+ This is temporary solution which should be removed once File_parser class
+ and related routines are refactored.
+*/
+
+#define my_offsetof(TYPE, MEMBER) \
+ ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10))
+
#endif /* _PARSE_FILE_H_ */
diff --git a/sql/password.c b/sql/password.c
index 506e1aa36a2..594096b6ec9 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -406,7 +406,7 @@ make_scrambled_password(char *to, const char *password)
mysql_sha1_result(&sha1_context, hash_stage2);
/* convert hash_stage2 to hex string */
*to++= PVERSION41_CHAR;
- octet2hex(to, hash_stage2, SHA1_HASH_SIZE);
+ octet2hex(to, (char*) hash_stage2, SHA1_HASH_SIZE);
}
@@ -520,5 +520,5 @@ void get_salt_from_password(uint8 *hash_stage2, const char *password)
void make_password_from_salt(char *to, const uint8 *hash_stage2)
{
*to++= PVERSION41_CHAR;
- octet2hex(to, hash_stage2, SHA1_HASH_SIZE);
+ octet2hex(to, (char*) hash_stage2, SHA1_HASH_SIZE);
}
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 5de24ebdcb3..e7a8d493341 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -46,7 +46,7 @@ bool Protocol_prep::net_store_data(const char *from, uint length)
packet->realloc(packet_length+9+length))
return 1;
char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
- (ulonglong) length);
+ length);
memcpy(to,from,length);
packet->length((uint) (to+length-packet->ptr()));
return 0;
@@ -280,8 +280,8 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
}
buff[0]=0; // No fields
- pos=net_store_length(buff+1,(ulonglong) affected_rows);
- pos=net_store_length(pos, (ulonglong) id);
+ pos=net_store_length(buff+1,affected_rows);
+ pos=net_store_length(pos, id);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
DBUG_PRINT("info",
@@ -456,7 +456,7 @@ void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
ulonglong for bigger numbers.
*/
-char *net_store_length(char *pkg, uint length)
+static char *net_store_length_fast(char *pkg, uint length)
{
uchar *packet=(uchar*) pkg;
if (length < 251)
@@ -479,7 +479,7 @@ char *net_store_length(char *pkg, uint length)
char *net_store_data(char *to,const char *from, uint length)
{
- to=net_store_length(to,length);
+ to=net_store_length_fast(to,length);
memcpy(to,from,length);
return to+length;
}
@@ -488,7 +488,7 @@ char *net_store_data(char *to,int32 from)
{
char buff[20];
uint length=(uint) (int10_to_str(from,buff,10)-buff);
- to=net_store_length(to,length);
+ to=net_store_length_fast(to,length);
memcpy(to,buff,length);
return to+length;
}
@@ -497,7 +497,7 @@ char *net_store_data(char *to,longlong from)
{
char buff[22];
uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
- to=net_store_length(to,length);
+ to=net_store_length_fast(to,length);
memcpy(to,buff,length);
return to+length;
}
@@ -561,7 +561,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
- char *pos=net_store_length(buff, (uint) list->elements);
+ char *pos=net_store_length(buff, list->elements);
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
diff --git a/sql/protocol.h b/sql/protocol.h
index 85c22724b74..7e2bc1516ec 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -166,7 +166,6 @@ void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0);
void send_eof(THD *thd);
bool send_old_password_request(THD *thd);
-char *net_store_length(char *packet,uint length);
char *net_store_data(char *to,const char *from, uint length);
char *net_store_data(char *to,int32 from);
char *net_store_data(char *to,longlong from);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index d0268d7017b..23afef742a6 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -121,7 +121,6 @@ static KEY_CACHE *create_key_cache(const char *name, uint length);
void fix_sql_mode_var(THD *thd, enum_var_type type);
static byte *get_error_count(THD *thd);
static byte *get_warning_count(THD *thd);
-static byte *get_prepared_stmt_count(THD *thd);
static byte *get_have_innodb(THD *thd);
static byte *get_tmpdir(THD *thd);
@@ -248,7 +247,7 @@ sys_var_thd_ulong sys_max_delayed_threads("max_delayed_threads",
fix_max_connections);
sys_var_thd_ulong sys_max_error_count("max_error_count",
&SV::max_error_count);
-sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size",
+sys_var_thd_ulonglong sys_max_heap_table_size("max_heap_table_size",
&SV::max_heap_table_size);
sys_var_thd_ulong sys_pseudo_thread_id("pseudo_thread_id",
&SV::pseudo_thread_id,
@@ -415,7 +414,7 @@ sys_var_thd_enum sys_tx_isolation("tx_isolation",
&SV::tx_isolation,
&tx_isolation_typelib,
fix_tx_isolation);
-sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
+sys_var_thd_ulonglong sys_tmp_table_size("tmp_table_size",
&SV::tmp_table_size);
sys_var_bool_ptr sys_timed_mutexes("timed_mutexes",
&timed_mutexes);
@@ -567,9 +566,6 @@ static sys_var_readonly sys_warning_count("warning_count",
OPT_SESSION,
SHOW_LONG,
get_warning_count);
-static sys_var_readonly sys_prepared_stmt_count("prepared_stmt_count",
- OPT_GLOBAL, SHOW_LONG,
- get_prepared_stmt_count);
/* alias for last_insert_id() to be compatible with Sybase */
#ifdef HAVE_REPLICATION
@@ -701,7 +697,6 @@ sys_var *sys_variables[]=
&sys_optimizer_prune_level,
&sys_optimizer_search_depth,
&sys_preload_buff_size,
- &sys_prepared_stmt_count,
&sys_pseudo_thread_id,
&sys_query_alloc_block_size,
&sys_query_cache_size,
@@ -804,7 +799,7 @@ sys_var *sys_variables[]=
/*
- Variables shown by SHOW variables in alphabetical order
+ Variables shown by SHOW VARIABLES in alphabetical order
*/
struct show_var_st init_vars[]= {
@@ -1008,7 +1003,6 @@ struct show_var_st init_vars[]= {
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
{"port", (char*) &mysqld_port, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
- {sys_prepared_stmt_count.name, (char*) &sys_prepared_stmt_count, SHOW_SYS},
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
SHOW_SYS},
@@ -2836,7 +2830,7 @@ static bool set_option_autocommit(THD *thd, set_var *var)
{
/* The test is negative as the flag we use is NOT autocommit */
- ulong org_options=thd->options;
+ ulonglong org_options= thd->options;
if (var->save_result.ulong_value != 0)
thd->options&= ~((sys_var_thd_bit*) var->var)->bit_flag;
@@ -2927,6 +2921,7 @@ static byte *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]);
return (byte*) &thd->sys_var_tmp.long_value;
}
@@ -2945,15 +2940,6 @@ static byte *get_have_innodb(THD *thd)
}
-static byte *get_prepared_stmt_count(THD *thd)
-{
- pthread_mutex_lock(&LOCK_prepared_stmt_count);
- thd->sys_var_tmp.ulong_value= prepared_stmt_count;
- pthread_mutex_unlock(&LOCK_prepared_stmt_count);
- return (byte*) &thd->sys_var_tmp.ulong_value;
-}
-
-
/*
Get the tmpdir that was specified or chosen by default
diff --git a/sql/slave.cc b/sql/slave.cc
index 28bb7f12008..d0396444ace 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -247,7 +247,7 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,
bool look_for_description_event)
{
DBUG_ENTER("init_relay_log_pos");
- DBUG_PRINT("info", ("pos=%lu", pos));
+ DBUG_PRINT("info", ("pos: %lu", (long) pos));
*errmsg=0;
pthread_mutex_t *log_lock=rli->relay_log.get_log_lock();
@@ -1513,7 +1513,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
TABLE_LIST tables;
int error= 1;
handler *file;
- ulong save_options;
+ ulonglong save_options;
NET *net= &mysql->net;
DBUG_ENTER("create_table_from_dump");
@@ -2854,8 +2854,21 @@ improper_arguments: %d timed_out: %d",
void set_slave_thread_options(THD* thd)
{
- thd->options = ((opt_log_slave_updates) ? OPTION_BIN_LOG:0) |
- OPTION_AUTO_IS_NULL;
+ /*
+ It's nonsense to constrain the slave threads with max_join_size; if a
+ query succeeded on master, we HAVE to execute it. So set
+ OPTION_BIG_SELECTS. Setting max_join_size to HA_POS_ERROR is not enough
+ (and it's not needed if we have OPTION_BIG_SELECTS) because an INSERT
+ SELECT examining more than 4 billion rows would still fail (yes, because
+ when max_join_size is 4G, OPTION_BIG_SELECTS is automatically set, but
+ only for client threads.
+ */
+ ulonglong options= thd->options | OPTION_BIG_SELECTS;
+ if (opt_log_slave_updates)
+ options|= OPTION_BIN_LOG;
+ else
+ options&= ~OPTION_BIN_LOG;
+ thd->options= options;
thd->variables.completion_type= 0;
}
@@ -2882,20 +2895,16 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO;
thd->security_ctx->skip_grants();
my_net_init(&thd->net, 0);
+/*
+ Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all
+ slave threads, since a replication event can become this much larger
+ than the corresponding packet (query) sent from client to master.
+*/
+ thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet
+ + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
thd->net.read_timeout = slave_net_timeout;
thd->slave_thread = 1;
set_slave_thread_options(thd);
- /*
- It's nonsense to constrain the slave threads with max_join_size; if a
- query succeeded on master, we HAVE to execute it. So set
- OPTION_BIG_SELECTS. Setting max_join_size to HA_POS_ERROR is not enough
- (and it's not needed if we have OPTION_BIG_SELECTS) because an INSERT
- SELECT examining more than 4 billion rows would still fail (yes, because
- when max_join_size is 4G, OPTION_BIG_SELECTS is automatically set, but
- only for client threads.
- */
- thd->options = ((opt_log_slave_updates) ? OPTION_BIN_LOG:0) |
- OPTION_AUTO_IS_NULL | OPTION_BIG_SELECTS;
thd->client_capabilities = CLIENT_LOCAL_FILES;
thd->real_id=pthread_self();
pthread_mutex_lock(&LOCK_thread_count);
@@ -3078,7 +3087,7 @@ static ulong read_event(MYSQL* mysql, MASTER_INFO *mi, bool* suppress_warnings)
return packet_error;
}
- DBUG_PRINT("info",( "len=%u, net->read_pos[4] = %d\n",
+ DBUG_PRINT("info",( "len: %lu net->read_pos[4]: %d\n",
len, mysql->net.read_pos[4]));
return len - 1;
}
@@ -3345,9 +3354,9 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
const char *errmsg;
/*
We were in a transaction which has been rolled back because of a
- deadlock (currently, InnoDB deadlock detected by InnoDB) or lock
- wait timeout (innodb_lock_wait_timeout exceeded); let's seek back to
- BEGIN log event and retry it all again.
+ Sonera deadlock. if lock wait timeout (innodb_lock_wait_timeout exceeded)
+ there is no rollback since 5.0.13 (ref: manual).
+ let's seek back to BEGIN log event and retry it all again.
We have to not only seek but also
a) init_master_info(), to seek back to hot relay log's start for later
(for when we will come back to this hot log after re-processing the
@@ -3369,6 +3378,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
else
{
exec_res= 0;
+ end_trans(thd, ROLLBACK);
/* chance for concurrent connection to get more locks */
safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
(CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli);
@@ -3386,9 +3396,17 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
"the slave_transaction_retries variable.",
slave_trans_retries);
}
- if (!((thd->options & OPTION_BEGIN) && opt_using_transactions))
- rli->trans_retries= 0; // restart from fresh
- }
+ else if (!((thd->options & OPTION_BEGIN) && opt_using_transactions))
+ {
+ /*
+ Only reset the retry counter if the event succeeded or
+ failed with a non-transient error. On a successful event,
+ the execution will proceed as usual; in the case of a
+ non-transient error, the slave will stop with an error.
+ */
+ rli->trans_retries= 0; // restart from fresh
+ }
+ }
return exec_res;
}
else
@@ -3472,11 +3490,19 @@ slave_begin:
thd->proc_info = "Connecting to master";
// we can get killed during safe_connect
if (!safe_connect(thd, mysql, mi))
+ {
sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',\
replication started in log '%s' at position %s", mi->user,
- mi->host, mi->port,
- IO_RPL_LOG_NAME,
- llstr(mi->master_log_pos,llbuff));
+ mi->host, mi->port,
+ IO_RPL_LOG_NAME,
+ llstr(mi->master_log_pos,llbuff));
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O
+ thread, since a replication event can become this much larger than
+ the corresponding packet (query) sent from client to master.
+ */
+ mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER;
+ }
else
{
sql_print_information("Slave I/O thread killed while connecting to master");
@@ -4114,7 +4140,7 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
/* Safe copy as 'rev' has been "sanitized" in Rotate_log_event's ctor */
memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
mi->master_log_pos= rev->pos;
- DBUG_PRINT("info", ("master_log_pos: '%s' %d",
+ DBUG_PRINT("info", ("master_log_pos: '%s' %lu",
mi->master_log_name, (ulong) mi->master_log_pos));
#ifndef DBUG_OFF
/*
@@ -4231,7 +4257,7 @@ static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf,
int error = process_io_create_file(mi,(Create_file_log_event*)ev);
delete ev;
mi->master_log_pos += inc_pos;
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
pthread_mutex_unlock(&mi->data_lock);
my_free((char*)tmp_buf, MYF(0));
DBUG_RETURN(error);
@@ -4258,7 +4284,7 @@ static int queue_binlog_ver_1_event(MASTER_INFO *mi, const char *buf,
}
delete ev;
mi->master_log_pos+= inc_pos;
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
pthread_mutex_unlock(&mi->data_lock);
DBUG_RETURN(0);
}
@@ -4314,7 +4340,7 @@ static int queue_binlog_ver_3_event(MASTER_INFO *mi, const char *buf,
delete ev;
mi->master_log_pos+= inc_pos;
err:
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
pthread_mutex_unlock(&mi->data_lock);
DBUG_RETURN(0);
}
@@ -4484,7 +4510,8 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
rli->ign_master_log_pos_end= mi->master_log_pos;
}
rli->relay_log.signal_update(); // the slave SQL thread needs to re-check
- DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu event originating from the same server, ignored",
+ (ulong) mi->master_log_pos));
}
else
{
@@ -4492,7 +4519,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
if (likely(!(rli->relay_log.appendv(buf,event_len,0))))
{
mi->master_log_pos+= inc_pos;
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
}
else
diff --git a/sql/sp.cc b/sql/sp.cc
index 49dbed79fe5..eae6e624d59 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -539,17 +539,17 @@ db_create_routine(THD *thd, int type, sp_head *sp)
table->field[MYSQL_PROC_FIELD_NAME]->
store(sp->m_name.str, sp->m_name.length, system_charset_info);
table->field[MYSQL_PROC_FIELD_TYPE]->
- store((longlong)type);
+ store((longlong)type, 1);
table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
store(sp->m_name.str, sp->m_name.length, system_charset_info);
if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS)
table->field[MYSQL_PROC_FIELD_ACCESS]->
- store((longlong)sp->m_chistics->daccess);
+ store((longlong)sp->m_chistics->daccess, 1);
table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
- store((longlong)(sp->m_chistics->detistic ? 1 : 2));
+ store((longlong)(sp->m_chistics->detistic ? 1 : 2), 1);
if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
- store((longlong)sp->m_chistics->suid);
+ store((longlong)sp->m_chistics->suid, 1);
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
store(sp->m_params.str, sp->m_params.length, system_charset_info);
if (sp->m_type == TYPE_ENUM_FUNCTION)
@@ -566,7 +566,7 @@ db_create_routine(THD *thd, int type, sp_head *sp)
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
table->field[MYSQL_PROC_FIELD_SQL_MODE]->
- store((longlong)thd->variables.sql_mode);
+ store((longlong)thd->variables.sql_mode, 1);
if (sp->m_chistics->comment.str)
table->field[MYSQL_PROC_FIELD_COMMENT]->
store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
@@ -651,6 +651,17 @@ db_drop_routine(THD *thd, int type, sp_name *name)
if (table->file->delete_row(table->record[0]))
ret= SP_DELETE_ROW_FAILED;
}
+
+ if (ret == SP_OK)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ }
+
close_thread_tables(thd);
DBUG_RETURN(ret);
}
@@ -661,7 +672,6 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
{
TABLE *table;
int ret;
- bool opened;
DBUG_ENTER("db_update_routine");
DBUG_PRINT("enter", ("type: %d name: %.*s",
type, name->m_name.length, name->m_name.str));
@@ -675,10 +685,10 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
if (chistics->suid != SP_IS_DEFAULT_SUID)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
- store((longlong)chistics->suid);
+ store((longlong)chistics->suid, 1);
if (chistics->daccess != SP_DEFAULT_ACCESS)
table->field[MYSQL_PROC_FIELD_ACCESS]->
- store((longlong)chistics->daccess);
+ store((longlong)chistics->daccess, 1);
if (chistics->comment.str)
table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str,
chistics->comment.length,
@@ -686,6 +696,17 @@ db_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
if ((table->file->update_row(table->record[1],table->record[0])))
ret= SP_WRITE_ROW_FAILED;
}
+
+ if (ret == SP_OK)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ }
+
close_thread_tables(thd);
DBUG_RETURN(ret);
}
@@ -764,6 +785,7 @@ print_field_values(THD *thd, TABLE *table,
return SP_INTERNAL_ERROR;
}
}
+
return SP_OK;
}
@@ -1369,6 +1391,10 @@ static bool add_used_routine(LEX *lex, Query_arena *arena,
const LEX_STRING *key,
TABLE_LIST *belong_to_view)
{
+ hash_init_opt(&lex->sroutines, system_charset_info,
+ Query_tables_list::START_SROUTINES_HASH_SIZE,
+ 0, 0, sp_sroutine_key, 0, 0);
+
if (!hash_search(&lex->sroutines, (byte *)key->str, key->length))
{
Sroutine_hash_entry *rn=
diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc
index fea6a67f32c..f5912caddaf 100644
--- a/sql/sp_cache.cc
+++ b/sql/sp_cache.cc
@@ -124,7 +124,6 @@ void sp_cache_clear(sp_cache **cp)
void sp_cache_insert(sp_cache **cp, sp_head *sp)
{
sp_cache *c;
- ulong v;
if (!(c= *cp))
{
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 9761de625be..152bc87aead 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -444,9 +444,12 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head()
:Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
m_flags(0), m_recursion_level(0), m_next_cached_sp(0),
- m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this),
m_cont_level(0)
{
+ m_first_instance= this;
+ m_first_free_instance= this;
+ m_last_cached_sp= this;
+
m_return_field_def.charset = NULL;
extern byte *
@@ -991,8 +994,7 @@ sp_head::execute(THD *thd)
save_sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode= m_sql_mode;
save_abort_on_warning= thd->abort_on_warning;
- thd->abort_on_warning=
- (m_sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES));
+ thd->abort_on_warning= 0;
/*
It is also more efficient to save/restore current thd->lex once when
@@ -1649,7 +1651,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
Item_null *null_item= new Item_null();
if (!null_item ||
- nctx->set_variable(thd, i, (struct Item **)&null_item))
+ nctx->set_variable(thd, i, (Item **)&null_item))
{
err_status= TRUE;
break;
@@ -2790,7 +2792,7 @@ void
sp_instr_freturn::print(String *str)
{
/* freturn type expr... */
- if (str->reserve(UINT_MAX+8+32)) // Add some for the expr. too
+ if (str->reserve(1024+8+32)) // Add some for the expr. too
return;
str->qs_append(STRING_WITH_LEN("freturn "));
str->qs_append((uint)m_type);
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 50cee6eeca4..ab39cb250f6 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1898,7 +1898,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
table->field[next_field+2]->store((longlong) mqh.conn_per_hour, TRUE);
if (table->s->fields >= 36 &&
(mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
- table->field[next_field+3]->store((longlong) mqh.user_conn);
+ table->field[next_field+3]->store((longlong) mqh.user_conn, TRUE);
mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
}
if (old_row_exists)
@@ -2999,9 +2999,22 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
grant_option=TRUE;
thd->mem_root= old_root;
pthread_mutex_unlock(&acl_cache->lock);
+
+ if (!result) /* success */
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ }
+
rw_unlock(&LOCK_grant);
- if (!result)
+
+ if (!result) /* success */
send_ok(thd);
+
/* Tables are automatically closed */
DBUG_RETURN(result);
}
@@ -3153,9 +3166,21 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
grant_option=TRUE;
thd->mem_root= old_root;
pthread_mutex_unlock(&acl_cache->lock);
+ if (!result && !no_error)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ }
+
rw_unlock(&LOCK_grant);
+
if (!result && !no_error)
send_ok(thd);
+
/* Tables are automatically closed */
DBUG_RETURN(result);
}
@@ -3253,11 +3278,23 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
}
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (!result)
+ {
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (!result)
send_ok(thd);
+
DBUG_RETURN(result);
}
@@ -3689,7 +3726,7 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant,
GRANT_COLUMN *grant_column;
ulong want_access= grant->want_privilege & ~grant->privilege;
DBUG_ENTER("check_grant_column");
- DBUG_PRINT("enter", ("table: %s want_access: %u", table_name, want_access));
+ DBUG_PRINT("enter", ("table: %s want_access: %lu", table_name, want_access));
if (!want_access)
DBUG_RETURN(0); // Already checked
@@ -5251,6 +5288,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5307,6 +5351,13 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
rebuild_check_host();
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5376,6 +5427,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
rebuild_check_host();
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
@@ -5549,6 +5607,13 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
+
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 3984ceac6a9..90043e45052 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -686,7 +686,7 @@ void close_temporary_tables(THD *thd)
/* We always quote db,table names though it is slight overkill */
if (found_user_tables &&
- !(was_quote_show= (thd->options & OPTION_QUOTE_SHOW_CREATE)))
+ !(was_quote_show= test(thd->options & OPTION_QUOTE_SHOW_CREATE)))
{
thd->options |= OPTION_QUOTE_SHOW_CREATE;
}
@@ -806,6 +806,10 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
Also SELECT::exclude_from_table_unique_test used to exclude from check
tables of main SELECT of multi-delete and multi-update
+ We also skip tables with TABLE_LIST::prelocking_placeholder set,
+ because we want to allow SELECTs from them, and their modification
+ will rise the error anyway.
+
TODO: when we will have table/view change detection we can do this check
only once for PS/SP
@@ -852,12 +856,13 @@ TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list)
if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) &&
(! (res= mysql_lock_have_duplicate(thd, table, table_list)))) ||
((!res->table || res->table != table->table) &&
- res->select_lex && !res->select_lex->exclude_from_table_unique_test))
+ res->select_lex && !res->select_lex->exclude_from_table_unique_test &&
+ !res->prelocking_placeholder))
break;
/*
- If we found entry of this table or or table of SELECT which already
+ If we found entry of this table or table of SELECT which already
processed in derived table or top select of multi-update/multi-delete
- (exclude_from_table_unique_test).
+ (exclude_from_table_unique_test) or prelocking placeholder.
*/
table_list= res->next_global;
DBUG_PRINT("info",
@@ -3303,6 +3308,12 @@ find_field_in_tables(THD *thd, Item_ident *item,
{
if (found == WRONG_GRANT)
return (Field*) 0;
+
+ /*
+ Only views fields should be marked as dependent, not an underlying
+ fields.
+ */
+ if (!table_ref->belong_to_view)
{
SELECT_LEX *current_sel= thd->lex->current_select;
SELECT_LEX *last_select= table_ref->select_lex;
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index ff033b69f98..2c77e0ef230 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -527,7 +527,8 @@ void Query_cache_query::init_n_lock()
my_rwlock_init(&lock, NULL);
lock_writing();
DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx",
- ((byte*) this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ (long) (((byte*) this) -
+ ALIGN_SIZE(sizeof(Query_cache_block)))));
DBUG_VOID_RETURN;
}
@@ -536,7 +537,8 @@ void Query_cache_query::unlock_n_destroy()
{
DBUG_ENTER("Query_cache_query::unlock_n_destroy");
DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
- ((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
+ (long) (((byte*) this) -
+ ALIGN_SIZE(sizeof(Query_cache_block)))));
/*
The following call is not needed on system where one can destroy an
active semaphore
@@ -702,6 +704,7 @@ void query_cache_abort(NET *net)
void query_cache_end_of_result(THD *thd)
{
+ Query_cache_block *query_block;
DBUG_ENTER("query_cache_end_of_result");
/* See the comment on double-check locking usage above. */
@@ -717,13 +720,9 @@ void query_cache_end_of_result(THD *thd)
if (unlikely(query_cache.query_cache_size == 0 ||
query_cache.flush_in_progress))
- {
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
- DBUG_VOID_RETURN;
- }
+ goto end;
- Query_cache_block *query_block= ((Query_cache_block*)
- thd->net.query_cache_query);
+ query_block= ((Query_cache_block*) thd->net.query_cache_query);
if (query_block)
{
DUMP(&query_cache);
@@ -742,27 +741,25 @@ void query_cache_end_of_result(THD *thd)
header->query()));
query_cache.wreck(__LINE__, "");
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
-
- DBUG_VOID_RETURN;
+ /*
+ We do not need call of BLOCK_UNLOCK_WR(query_block); here because
+ query_cache.wreck() switched query cache off but left content
+ untouched for investigation (it is debugging method).
+ */
+ goto end;
}
#endif
header->found_rows(current_thd->limit_found_rows);
header->result()->type= Query_cache_block::RESULT;
header->writer(0);
thd->net.query_cache_query= 0;
+ BLOCK_UNLOCK_WR(query_block);
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1););
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
-
- BLOCK_UNLOCK_WR(query_block);
- }
- else
- {
- // Cache was flushed or resized and query was deleted => do nothing
- STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
}
+end:
+ STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
DBUG_VOID_RETURN;
}
@@ -879,8 +876,8 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
flags.character_set_client_num,
flags.character_set_results_num,
flags.collation_connection_num,
- flags.limit,
- (ulong)flags.time_zone,
+ (ulong) flags.limit,
+ (ulong) flags.time_zone,
flags.sql_mode,
flags.max_sort_length,
flags.group_concat_max_len));
@@ -909,7 +906,7 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
if (thd->db_length)
{
memcpy(thd->query+thd->query_length+1, thd->db, thd->db_length);
- DBUG_PRINT("qcache", ("database : %s length %u",
+ DBUG_PRINT("qcache", ("database: %s length: %u",
thd->db, thd->db_length));
}
else
@@ -1055,7 +1052,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
(pre-space is removed in dispatch_command)
First '/' looks like comment before command it is not
- frequently appeared in real lihe, consequently we can
+ frequently appeared in real life, consequently we can
check all such queries, too.
*/
if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
@@ -1084,7 +1081,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
if (thd->db_length)
{
memcpy(sql+query_length+1, thd->db, thd->db_length);
- DBUG_PRINT("qcache", ("database: '%s' length %u",
+ DBUG_PRINT("qcache", ("database: '%s' length: %u",
thd->db, thd->db_length));
}
else
@@ -1122,8 +1119,8 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
flags.character_set_client_num,
flags.character_set_results_num,
flags.collation_connection_num,
- flags.limit,
- (ulong)flags.time_zone,
+ (ulong) flags.limit,
+ (ulong) flags.time_zone,
flags.sql_mode,
flags.max_sort_length,
flags.group_concat_max_len));
@@ -1237,9 +1234,9 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
if (engine_data != table->engine_data())
{
DBUG_PRINT("qcache",
- ("Handler require invalidation queries of %s.%s %lld-%lld",
- table_list.db, table_list.alias,
- engine_data, table->engine_data()));
+ ("Handler require invalidation queries of %s.%s %lu-%lu",
+ table_list.db, table_list.alias,
+ (ulong) engine_data, (ulong) table->engine_data()));
invalidate_table((byte *) table->db(), table->key_length());
}
else
@@ -1260,10 +1257,10 @@ sql mode: 0x%lx, sort len: %lu, conncat len: %lu",
#ifndef EMBEDDED_LIBRARY
do
{
- DBUG_PRINT("qcache", ("Results (len %lu, used %lu, headers %lu)",
+ DBUG_PRINT("qcache", ("Results (len: %lu used: %lu headers: %lu)",
result_block->length, result_block->used,
- result_block->headers_len()+
- ALIGN_SIZE(sizeof(Query_cache_result))));
+ (ulong) (result_block->headers_len()+
+ ALIGN_SIZE(sizeof(Query_cache_result)))));
Query_cache_result *result = result_block->result();
if (net_real_write(&thd->net, result->data(),
@@ -1345,7 +1342,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
for (; tables_used; tables_used= tables_used->next)
{
invalidate_table((byte*) tables_used->key, tables_used->key_length);
- DBUG_PRINT("qcache", (" db %s, table %s", tables_used->key,
+ DBUG_PRINT("qcache", ("db: %s table: %s", tables_used->key,
tables_used->key+
strlen(tables_used->key)+1));
}
@@ -2037,7 +2034,7 @@ Query_cache::append_result_data(Query_cache_block **current_block,
{
DBUG_ENTER("Query_cache::append_result_data");
DBUG_PRINT("qcache", ("append %lu bytes to 0x%lx query",
- data_len, query_block));
+ data_len, (long) query_block));
if (query_block->query()->add(data_len) > query_cache_limit)
{
@@ -2356,7 +2353,7 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
{
char key[MAX_DBKEY_LENGTH];
uint key_length;
- DBUG_PRINT("qcache", ("view %s, db %s",
+ DBUG_PRINT("qcache", ("view: %s db: %s",
tables_used->view_name.str,
tables_used->view_db.str));
key_length= (uint) (strmov(strmov(key, tables_used->view_db.str) + 1,
@@ -2477,11 +2474,11 @@ Query_cache::insert_table(uint key_len, char *key,
table_block->table()->engine_data() != engine_data)
{
DBUG_PRINT("qcache",
- ("Handler require invalidation queries of %s.%s %lld-%lld",
+ ("Handler require invalidation queries of %s.%s %lu-%lu",
table_block->table()->db(),
table_block->table()->table(),
- engine_data,
- table_block->table()->engine_data()));
+ (ulong) engine_data,
+ (ulong) table_block->table()->engine_data()));
/*
as far as we delete all queries with this table, table block will be
deleted, too
@@ -2979,7 +2976,7 @@ static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used,
table_count++;
if (tables_used->view)
{
- DBUG_PRINT("qcache", ("view %s, db %s",
+ DBUG_PRINT("qcache", ("view: %s db: %s",
tables_used->view_name.str,
tables_used->view_db.str));
*tables_type|= HA_CACHE_TBL_NONTRANSACT;
@@ -3044,10 +3041,10 @@ Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex,
OPTION_TO_QUERY_CACHE))) &&
lex->safe_to_cache_query)
{
- DBUG_PRINT("qcache", ("options %lx %lx, type %u",
- OPTION_TO_QUERY_CACHE,
- lex->select_lex.options,
- (int) thd->variables.query_cache_type));
+ DBUG_PRINT("qcache", ("options: %lx %lx type: %u",
+ (long) OPTION_TO_QUERY_CACHE,
+ (long) lex->select_lex.options,
+ (int) thd->variables.query_cache_type));
if (!(table_count= process_and_count_tables(tables_used, tables_type)))
DBUG_RETURN(0);
@@ -3063,10 +3060,10 @@ Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex,
}
DBUG_PRINT("qcache",
- ("not interesting query: %d or not cacheable, options %lx %lx, type %u",
+ ("not interesting query: %d or not cacheable, options %lx %lx type: %u",
(int) lex->sql_command,
- OPTION_TO_QUERY_CACHE,
- lex->select_lex.options,
+ (long) OPTION_TO_QUERY_CACHE,
+ (long) lex->select_lex.options,
(int) thd->variables.query_cache_type));
DBUG_RETURN(0);
}
@@ -3529,7 +3526,7 @@ uint Query_cache::filename_2_table_key (char *key, const char *path,
#if defined(DBUG_OFF) && !defined(USE_QUERY_CACHE_INTEGRITY_CHECK)
-void wreck(uint line, const char *message) {}
+void wreck(uint line, const char *message) { query_cache_size = 0; }
void bins_dump() {}
void cache_dump() {}
void queries_dump() {}
@@ -3541,6 +3538,17 @@ my_bool in_blocks(Query_cache_block * point) { return 0; }
#else
+
+/*
+ Debug method which switch query cache off but left content for
+ investigation.
+
+ SYNOPSIS
+ Query_cache::wreck()
+ line line of the wreck() call
+ message message for logging
+*/
+
void Query_cache::wreck(uint line, const char *message)
{
THD *thd=current_thd;
@@ -3655,7 +3663,8 @@ void Query_cache::queries_dump()
DBUG_PRINT("qcache", ("F:%u C:%u L:%lu T:'%s' (%u) '%s' '%s'",
flags.client_long_flag,
flags.character_set_client_num,
- (ulong)flags.limit, flags.time_zone->get_name(),
+ (ulong)flags.limit,
+ flags.time_zone->get_name()->ptr(),
len, str, strend(str)+1));
DBUG_PRINT("qcache", ("-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
(ulong) block->next, (ulong) block->prev,
@@ -3763,8 +3772,8 @@ my_bool Query_cache::check_integrity(bool locked)
(((long)first_block) % (long)ALIGN_SIZE(1)))
{
DBUG_PRINT("error",
- ("block 0x%lx do not aligned by %d", (ulong) block,
- ALIGN_SIZE(1)));
+ ("block 0x%lx do not aligned by %d", (long) block,
+ (int) ALIGN_SIZE(1)));
result = 1;
}
// Check memory allocation
@@ -3875,9 +3884,8 @@ my_bool Query_cache::check_integrity(bool locked)
break;
}
default:
- DBUG_PRINT("error",
- ("block 0x%lx have incorrect type %u",
- block, block->type));
+ DBUG_PRINT("error", ("block 0x%lx have incorrect type %u",
+ (long) block, block->type));
result = 1;
}
@@ -3975,8 +3983,8 @@ my_bool Query_cache::check_integrity(bool locked)
} while (block != bins[i].free_blocks);
if (count != bins[i].number)
{
- DBUG_PRINT("error", ("bin[%d].number is %d, but bin have %d blocks",
- bins[i].number, count));
+ DBUG_PRINT("error", ("bins[%d].number = %d, but bin have %d blocks",
+ i, bins[i].number, count));
result = 1;
}
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 645ac6e28f3..d2f1e9ed0d9 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -205,6 +205,7 @@ THD::THD()
// Must be reset to handle error with THD's created for init of mysqld
lex->current_select= 0;
start_time=(time_t) 0;
+ time_after_lock=(time_t) 0;
current_linfo = 0;
slave_thread = 0;
variables.pseudo_thread_id= 0;
@@ -463,14 +464,13 @@ THD::~THD()
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
{
- ulong *end= (ulong*) ((byte*) to_var + offsetof(STATUS_VAR,
- last_system_status_var) +
+ ulong *end= (ulong*) ((byte*) to_var +
+ offsetof(STATUS_VAR, last_system_status_var) +
sizeof(ulong));
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
while (to != end)
*(to++)+= *(from++);
- /* it doesn't make sense to add last_query_cost values */
}
@@ -712,7 +712,7 @@ void THD::add_changed_table(const char *key, long key_length)
{
list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
- ("key_length %u %u", key_length, (*prev_changed)->key_length));
+ ("key_length %ld %u", key_length, (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -722,7 +722,7 @@ void THD::add_changed_table(const char *key, long key_length)
{
list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
- ("key_length %u %u", key_length,
+ ("key_length %ld %u", key_length,
(*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
@@ -734,7 +734,7 @@ void THD::add_changed_table(const char *key, long key_length)
}
}
*prev_changed = changed_table_dup(key, key_length);
- DBUG_PRINT("info", ("key_length %u %u", key_length,
+ DBUG_PRINT("info", ("key_length %ld %u", key_length,
(*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 804c887f05a..9ad67524998 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -495,6 +495,8 @@ struct system_variables
{
ulonglong myisam_max_extra_sort_file_size;
ulonglong myisam_max_sort_file_size;
+ ulonglong max_heap_table_size;
+ ulonglong tmp_table_size;
ha_rows select_limit;
ha_rows max_join_size;
ulong auto_increment_increment, auto_increment_offset;
@@ -503,7 +505,6 @@ struct system_variables
ulong long_query_time;
ulong max_allowed_packet;
ulong max_error_count;
- ulong max_heap_table_size;
ulong max_length_for_sort_data;
ulong max_sort_length;
ulong max_tmp_tables;
@@ -527,7 +528,6 @@ struct system_variables
ulong div_precincrement;
ulong sortbuff_size;
ulong table_type;
- ulong tmp_table_size;
ulong tx_isolation;
ulong completion_type;
/* Determines which non-standard SQL behaviour should be enabled */
@@ -646,12 +646,17 @@ typedef struct system_status_var
ulong com_stmt_reset;
ulong com_stmt_close;
+ /*
+ Status variables which it does not make sense to add to
+ global status variable counter
+ */
double last_query_cost;
} STATUS_VAR;
/*
- This is used for 'show status'. It must be updated to the last ulong
- variable in system_status_var
+ This is used for 'SHOW STATUS'. It must be updated to the last ulong
+ variable in system_status_var which is makes sens to add to the global
+ counter
*/
#define last_system_status_var com_stmt_close
@@ -2069,7 +2074,8 @@ class user_var_entry
class Unique :public Sql_alloc
{
DYNAMIC_ARRAY file_ptrs;
- ulong max_elements, max_in_memory_size;
+ ulong max_elements;
+ ulonglong max_in_memory_size;
IO_CACHE file;
TREE tree;
byte *record_pointers;
@@ -2079,13 +2085,13 @@ class Unique :public Sql_alloc
public:
ulong elements;
Unique(qsort_cmp2 comp_func, void *comp_func_fixed_arg,
- uint size_arg, ulong max_in_memory_size_arg);
+ uint size_arg, ulonglong max_in_memory_size_arg);
~Unique();
ulong elements_in_tree() { return tree.elements_in_tree; }
inline bool unique_add(void *ptr)
{
DBUG_ENTER("unique_add");
- DBUG_PRINT("info", ("tree %u - %u", tree.elements_in_tree, max_elements));
+ DBUG_PRINT("info", ("tree %u - %lu", tree.elements_in_tree, max_elements));
if (tree.elements_in_tree > max_elements && flush())
DBUG_RETURN(1);
DBUG_RETURN(!tree_insert(&tree, ptr, 0, tree.custom_arg));
@@ -2093,13 +2099,13 @@ public:
bool get(TABLE *table);
static double get_use_cost(uint *buffer, uint nkeys, uint key_size,
- ulong max_in_memory_size);
+ ulonglong max_in_memory_size);
inline static int get_cost_calc_buff_size(ulong nkeys, uint key_size,
- ulong max_in_memory_size)
+ ulonglong max_in_memory_size)
{
- register ulong max_elems_in_tree=
+ register ulonglong max_elems_in_tree=
(1 + max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size));
- return sizeof(uint)*(1 + nkeys/max_elems_in_tree);
+ return (int) (sizeof(uint)*(1 + nkeys/max_elems_in_tree));
}
void reset();
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 81508e4e9be..1dd9406109c 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -585,6 +585,7 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
qinfo.db = db;
qinfo.db_len = strlen(db);
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -656,6 +657,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
qinfo.db_len = strlen(db);
thd->clear_error();
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -779,6 +781,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
qinfo.db_len = strlen(db);
thd->clear_error();
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
thd->server_status|= SERVER_STATUS_DB_DROPPED;
@@ -805,6 +808,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
tbl_name_len= strlen(tbl->table_name) + 3;
if (query_pos + tbl_name_len + 1 >= query_end)
{
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
query_pos= query_data_start;
}
@@ -817,6 +821,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
if (query_pos != query_data_start)
{
+ /* These DDL methods and logging protected with LOCK_mysql_create_db */
write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
}
}
@@ -1167,7 +1172,7 @@ err:
bool mysql_change_db(THD *thd, const char *name, bool no_access_check)
{
- int path_length, db_length;
+ int db_length;
char *db_name;
bool system_db= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 3e3378542aa..b665113dd18 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -49,7 +49,12 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(TRUE);
}
- table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ if (error)
+ {
+ table->file->print_error(error, MYF(0));
+ DBUG_RETURN(error);
+ }
thd->proc_info="init";
table->map=1;
@@ -317,11 +322,11 @@ cleanup:
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
- if (error < 0)
+ if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error))
{
thd->row_count_func= deleted;
send_ok(thd,deleted);
- DBUG_PRINT("info",("%d records deleted",deleted));
+ DBUG_PRINT("info",("%ld records deleted",(long) deleted));
}
DBUG_RETURN(error >= 0 || thd->net.report_error);
}
@@ -897,7 +902,7 @@ end:
trunc_by_del:
/* Probably InnoDB table */
- ulong save_options= thd->options;
+ ulonglong save_options= thd->options;
table_list->lock_type= TL_WRITE;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
ha_enable_transaction(thd, FALSE);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 0193d4d5355..7eb248f3706 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -338,7 +338,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
{
TABLE_LIST *hash_tables;
- TABLE **table_ptr;
TABLE *table;
MYSQL_LOCK *lock;
List<Item> list;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index dee198d14bc..3de842c8551 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -150,7 +150,6 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->safe_to_cache_query= 1;
lex->time_zone_tables_used= 0;
lex->leaf_tables_insert= 0;
- lex->variables_used= 0;
lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1;
lex->next_state=MY_LEX_START;
@@ -1639,9 +1638,18 @@ void Query_tables_list::reset_query_tables_list(bool init)
query_tables_last= &query_tables;
query_tables_own_last= 0;
if (init)
- hash_init(&sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0);
+ {
+ /*
+ We delay real initialization of hash (and therefore related
+ memory allocation) until first insertion into this hash.
+ */
+ hash_clear(&sroutines);
+ }
else if (sroutines.records)
+ {
+ /* Non-zero sroutines.records means that hash was initialized. */
my_hash_reset(&sroutines);
+ }
sroutines_list.empty();
sroutines_list_own_last= sroutines_list.next;
sroutines_list_own_elements= 0;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 1d6f344cb1c..be12467d097 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -397,7 +397,7 @@ protected:
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
- ulong found_rows_for_union;
+ ulonglong found_rows_for_union;
bool res;
public:
bool prepared, // prepare phase already performed for UNION (unit)
@@ -747,7 +747,11 @@ public:
0 - indicates that this query does not need prelocking.
*/
TABLE_LIST **query_tables_own_last;
- /* Set of stored routines called by statement. */
+ /*
+ Set of stored routines called by statement.
+ (Note that we use lazy-initialization for this hash).
+ */
+ enum { START_SROUTINES_HASH_SIZE= 16 };
HASH sroutines;
/*
List linking elements of 'sroutines' set. Allows you to add new elements
@@ -812,6 +816,25 @@ public:
};
+/*
+ st_parsing_options contains the flags for constructions that are
+ allowed in the current statement.
+*/
+
+struct st_parsing_options
+{
+ bool allows_variable;
+ bool allows_select_into;
+ bool allows_select_procedure;
+ bool allows_derived;
+
+ st_parsing_options()
+ : allows_variable(TRUE), allows_select_into(TRUE),
+ allows_select_procedure(TRUE), allows_derived(TRUE)
+ {}
+};
+
+
/* The state of the lex parsing. This is saved in the THD struct */
typedef struct st_lex : public Query_tables_list
@@ -955,7 +978,7 @@ typedef struct st_lex : public Query_tables_list
bool stmt_prepare_mode;
bool safe_to_cache_query;
bool subqueries, ignore;
- bool variables_used;
+ st_parsing_options parsing_options;
ALTER_INFO alter_info;
/* Prepared statements SQL syntax:*/
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index bdc08b7bd2d..018db006276 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -696,7 +696,12 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (item->type() == Item::FIELD_ITEM)
{
Field *field= ((Item_field *)item)->field;
- field->reset();
+ if (field->reset())
+ {
+ my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
+ thd->row_count);
+ DBUG_RETURN(1);
+ }
field->set_null();
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
@@ -745,6 +750,13 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
{
if (item->type() == Item::FIELD_ITEM)
{
+ Field *field= ((Item_field *)item)->field;
+ if (field->reset())
+ {
+ my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
+ thd->row_count);
+ DBUG_RETURN(1);
+ }
/*
QQ: We probably should not throw warning for each field.
But how about intention to always have the same number
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index c62c286cfdb..fec7e5ab20d 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -381,9 +381,9 @@ int check_user(THD *thd, enum enum_server_command command,
NO_ACCESS)) // authentication is OK
{
DBUG_PRINT("info",
- ("Capabilities: %d packet_length: %ld Host: '%s' "
+ ("Capabilities: %lu packet_length: %ld Host: '%s' "
"Login user: '%s' Priv_user: '%s' Using password: %s "
- "Access: %u db: '%s'",
+ "Access: %lu db: '%s'",
thd->client_capabilities,
thd->max_client_packet_length,
thd->main_security_ctx.host_or_ip,
@@ -956,7 +956,7 @@ static int check_connection(THD *thd)
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
thd->variables.sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
- DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities));
+ DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
if (thd->client_capabilities & CLIENT_SSL)
{
/* Do the SSL layering. */
@@ -1112,7 +1112,7 @@ pthread_handler_t handle_one_connection(void *arg)
of handle_one_connection, which is thd. We need to know the
start of the stack so that we could check for stack overruns.
*/
- DBUG_PRINT("info", ("handle_one_connection called by thread %d\n",
+ DBUG_PRINT("info", ("handle_one_connection called by thread %lu\n",
thd->thread_id));
/* now that we've called my_thread_init(), it is safe to call DBUG_* */
@@ -1168,7 +1168,14 @@ pthread_handler_t handle_one_connection(void *arg)
{
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
if (thd->query_error)
+ {
thd->killed= THD::KILL_CONNECTION;
+ sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
+ 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", net->last_error);
+ }
thd->proc_info=0;
thd->set_time();
thd->init_for_queries();
@@ -1757,7 +1764,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (alloc_query(thd, packet, packet_length))
break; // fatal error is set
char *packet_end= thd->query + thd->query_length;
- mysql_log.write(thd,command, "%.*b", thd->query_length, thd->query);
+ /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
+ const char *format= "%.*b";
+ mysql_log.write(thd,command, format, thd->query_length, thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2159,9 +2168,11 @@ void log_slow_statement(THD *thd)
if ((ulong) (thd->start_time - thd->time_after_lock) >
thd->variables.long_query_time ||
- ((thd->server_status &
+ (thd->server_status &
(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
- (specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES)))
+ (specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES) &&
+ /* == SQLCOM_END unless this is a SHOW command */
+ thd->lex->orig_sql_command == SQLCOM_END)
{
thd->status_var.long_query_count++;
mysql_slow_log.write(thd, thd->query, thd->query_length, start_of_query);
@@ -2494,7 +2505,23 @@ mysql_execute_command(THD *thd)
{
/* we warn the slave SQL thread */
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
- reset_one_shot_variables(thd);
+ if (thd->one_shot_set)
+ {
+ /*
+ It's ok to check thd->one_shot_set here:
+
+ The charsets in a MySQL 5.0 slave can change by both a binlogged
+ SET ONE_SHOT statement and the event-internal charset setting,
+ and these two ways to change charsets do not seems to work
+ together.
+
+ At least there seems to be problems in the rli cache for
+ charsets if we are using ONE_SHOT. Note that this is normally no
+ problem because either the >= 5.0 slave reads a 4.1 binlog (with
+ ONE_SHOT) *or* or 5.0 binlog (without ONE_SHOT) but never both."
+ */
+ reset_one_shot_variables(thd);
+ }
DBUG_RETURN(0);
}
}
@@ -3045,11 +3072,6 @@ end_with_restore_list:
case SQLCOM_ALTER_TABLE:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
-#if defined(DONT_ALLOW_SHOW_COMMANDS)
- my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
- MYF(0)); /* purecov: inspected */
- goto error;
-#else
{
ulong priv=0;
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
@@ -3115,7 +3137,6 @@ end_with_restore_list:
}
break;
}
-#endif /*DONT_ALLOW_SHOW_COMMANDS*/
case SQLCOM_RENAME_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -3209,6 +3230,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, REPAIR and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3243,6 +3265,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, ANALYZE and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3268,6 +3291,7 @@ end_with_restore_list:
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
{
+ /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */
if (mysql_bin_log.is_open())
{
thd->clear_error(); // No binlog error generated
@@ -3369,8 +3393,16 @@ end_with_restore_list:
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
lex->update_list, lex->value_list,
lex->duplicates, lex->ignore);
+
+ /*
+ If we have inserted into a VIEW, and the base table has
+ AUTO_INCREMENT column, but this column is not accessible through
+ a view, then we should restore LAST_INSERT_ID to the value it
+ had before the statement.
+ */
if (first_table->view && !first_table->contain_auto_increment)
- thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
+ thd->last_insert_id= thd->current_insert_id;
+
break;
}
case SQLCOM_REPLACE_SELECT:
@@ -3421,8 +3453,12 @@ end_with_restore_list:
if (first_table->lock_type == TL_WRITE_CONCURRENT_INSERT &&
thd->lock)
{
+ /* INSERT ... SELECT should invalidate only the very first table */
+ TABLE_LIST *save_table= first_table->next_local;
+ first_table->next_local= 0;
mysql_unlock_tables(thd, thd->lock);
query_cache_invalidate3(thd, first_table, 1);
+ first_table->next_local= save_table;
thd->lock=0;
}
delete result;
@@ -3431,8 +3467,15 @@ end_with_restore_list:
select_lex->table_list.first= (byte*) first_table;
}
+ /*
+ If we have inserted into a VIEW, and the base table has
+ AUTO_INCREMENT column, but this column is not accessible through
+ a view, then we should restore LAST_INSERT_ID to the value it
+ had before the statement.
+ */
if (first_table->view && !first_table->contain_auto_increment)
- thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
+ thd->last_insert_id= thd->current_insert_id;
+
break;
}
case SQLCOM_TRUNCATE:
@@ -3554,6 +3597,7 @@ end_with_restore_list:
/* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
}
+ /* DDL and binlog write order protected by LOCK_open */
res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
lex->drop_temporary);
}
@@ -3842,15 +3886,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_create_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_DROP_USER:
@@ -3860,15 +3898,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_drop_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_RENAME_USER:
@@ -3878,15 +3910,9 @@ end_with_restore_list:
break;
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog */
if (!(res= mysql_rename_user(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_REVOKE_ALL:
@@ -3894,15 +3920,9 @@ end_with_restore_list:
if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
check_global_access(thd,CREATE_USER_ACL))
break;
+ /* Conditionally writes to binlog */
if (!(res = mysql_revoke_all(thd, lex->users_list)))
- {
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
send_ok(thd);
- }
break;
}
case SQLCOM_REVOKE:
@@ -3961,6 +3981,7 @@ end_with_restore_list:
check_grant_routine(thd, grants | GRANT_ACL, all_tables,
lex->type == TYPE_ENUM_PROCEDURE, 0))
goto error;
+ /* Conditionally writes to binlog */
res= mysql_routine_grant(thd, all_tables,
lex->type == TYPE_ENUM_PROCEDURE,
lex->users_list, grants,
@@ -3973,16 +3994,11 @@ end_with_restore_list:
GRANT_ACL),
all_tables, 0, UINT_MAX, 0))
goto error;
+ /* Conditionally writes to binlog */
res= mysql_table_grant(thd, all_tables, lex->users_list,
lex->columns, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
}
- if (!res && mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
}
else
{
@@ -3993,16 +4009,11 @@ end_with_restore_list:
goto error;
}
else
+ /* Conditionally writes to binlog */
res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
if (!res)
{
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
if (lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
@@ -4040,6 +4051,7 @@ end_with_restore_list:
We WANT to write and we CAN write.
! we write after unlocking the table.
*/
+ /* Presumably, RESET and binlog writing doesn't require synchronization */
if (!lex->no_write_to_binlog && write_to_binlog)
{
if (mysql_bin_log.is_open())
@@ -4560,20 +4572,16 @@ end_with_restore_list:
already puts on CREATE FUNCTION.
*/
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
+ /* Conditionally writes to binlog */
result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
else
+ /* Conditionally writes to binlog */
result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
}
}
switch (result)
{
case SP_OK:
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
@@ -4618,9 +4626,11 @@ end_with_restore_list:
}
#endif
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
- result= sp_drop_procedure(thd, lex->spname);
+ /* Conditionally writes to binlog */
+ result= sp_drop_procedure(thd, lex->spname); /* Conditionally writes to binlog */
else
- result= sp_drop_function(thd, lex->spname);
+ /* Conditionally writes to binlog */
+ result= sp_drop_function(thd, lex->spname); /* Conditionally writes to binlog */
}
else
{
@@ -4633,6 +4643,8 @@ end_with_restore_list:
{
if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0))
goto error;
+
+ /* Does NOT write to binlog */
if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
{
send_ok(thd);
@@ -4653,12 +4665,6 @@ end_with_restore_list:
switch (result)
{
case SP_OK:
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
@@ -4755,49 +4761,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
- if (!(res= mysql_create_view(thd, thd->lex->create_view_mode)) &&
- mysql_bin_log.is_open())
- {
- String buff;
- const LEX_STRING command[3]=
- {{(char *)STRING_WITH_LEN("CREATE ")},
- {(char *)STRING_WITH_LEN("ALTER ")},
- {(char *)STRING_WITH_LEN("CREATE OR REPLACE ")}};
- thd->clear_error();
-
- buff.append(command[thd->lex->create_view_mode].str,
- command[thd->lex->create_view_mode].length);
- view_store_options(thd, first_table, &buff);
- buff.append(STRING_WITH_LEN("VIEW "));
- /* Test if user supplied a db (ie: we did not use thd->db) */
- if (first_table->db && first_table->db[0] &&
- (thd->db == NULL || strcmp(first_table->db, thd->db)))
- {
- append_identifier(thd, &buff, first_table->db,
- first_table->db_length);
- buff.append('.');
- }
- append_identifier(thd, &buff, first_table->table_name,
- first_table->table_name_length);
- if (lex->view_list.elements)
- {
- List_iterator_fast<LEX_STRING> names(lex->view_list);
- LEX_STRING *name;
- int i;
-
- for (i= 0; name= names++; i++)
- {
- buff.append(i ? ", " : "(");
- append_identifier(thd, &buff, name->str, name->length);
- }
- buff.append(')');
- }
- buff.append(STRING_WITH_LEN(" AS "));
- buff.append(first_table->source.str, first_table->source.length);
-
- Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ res= mysql_create_view(thd, first_table, thd->lex->create_view_mode);
break;
}
case SQLCOM_DROP_VIEW:
@@ -4805,13 +4769,8 @@ end_with_restore_list:
if (check_table_access(thd, DROP_ACL, all_tables, 0) ||
end_active_trans(thd))
goto error;
- if (!(res= mysql_drop_view(thd, first_table, thd->lex->drop_mode)) &&
- mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ /* Conditionally writes to binlog. */
+ res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
break;
}
case SQLCOM_CREATE_TRIGGER:
@@ -4819,6 +4778,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog. */
res= mysql_create_or_drop_trigger(thd, all_tables, 1);
/* We don't care about trigger body after this point */
@@ -4831,6 +4791,7 @@ end_with_restore_list:
if (end_active_trans(thd))
goto error;
+ /* Conditionally writes to binlog. */
res= mysql_create_or_drop_trigger(thd, all_tables, 0);
break;
}
@@ -5878,14 +5839,19 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
DBUG_ASSERT(thd->net.report_error);
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error));
- query_cache_abort(&thd->net);
- lex->unit.cleanup();
+
+ /*
+ The first thing we do after parse error is freeing sp_head to
+ ensure that we have restored original memroot.
+ */
if (thd->lex->sphead)
{
/* Clean up after failed stored procedure/function */
delete thd->lex->sphead;
thd->lex->sphead= NULL;
}
+ query_cache_abort(&thd->net);
+ lex->unit.cleanup();
}
thd->proc_info="freeing items";
thd->end_statement();
@@ -6177,7 +6143,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->alias= alias_str;
if (lower_case_table_names && table->table.length)
- my_casedn_str(files_charset_info, table->table.str);
+ table->table.length= my_casedn_str(files_charset_info, table->table.str);
ptr->table_name=table->table.str;
ptr->table_name_length=table->table.length;
ptr->lock_type= lock_type;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 32f0ca6859d..8c0235e9768 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1664,7 +1664,7 @@ static bool check_prepared_statement(Prepared_statement *stmt,
enum enum_sql_command sql_command= lex->sql_command;
int res= 0;
DBUG_ENTER("check_prepared_statement");
- DBUG_PRINT("enter",("command: %d, param_count: %ld",
+ DBUG_PRINT("enter",("command: %d, param_count: %u",
sql_command, stmt->param_count));
lex->first_lists_tables_same();
@@ -1877,9 +1877,12 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
thd->stmt_map.erase(stmt);
}
else
- mysql_log.write(thd, COM_STMT_PREPARE, "[%lu] %.*b", stmt->id,
+ {
+ const char *format= "[%lu] %.*b";
+ mysql_log.write(thd, COM_STMT_PREPARE, format, stmt->id,
stmt->query_length, stmt->query);
+ }
/* check_prepared_statemnt sends the metadata packet in case of success */
DBUG_VOID_RETURN;
}
@@ -2248,13 +2251,24 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
#endif
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
+
+ /*
+ If the free_list is not empty, we'll wrongly free some externally
+ allocated items when cleaning up after validation of the prepared
+ statement.
+ */
+ DBUG_ASSERT(thd->free_list == NULL);
+
error= stmt->execute(&expanded_query,
test(flags & (ulong) CURSOR_TYPE_READ_ONLY));
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
if (error == 0)
- mysql_log.write(thd, COM_STMT_EXECUTE, "[%lu] %.*b", stmt->id,
+ {
+ const char *format= "[%lu] %.*b";
+ mysql_log.write(thd, COM_STMT_EXECUTE, format, stmt->id,
thd->query_length, thd->query);
+ }
DBUG_VOID_RETURN;
@@ -2310,6 +2324,13 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_PRINT("info",("stmt: %p", stmt));
+ /*
+ If the free_list is not empty, we'll wrongly free some externally
+ allocated items when cleaning up after validation of the prepared
+ statement.
+ */
+ DBUG_ASSERT(thd->free_list == NULL);
+
if (stmt->set_params_from_vars(stmt, lex->prepared_stmt_params,
&expanded_query))
goto set_params_data_err;
@@ -2773,6 +2794,16 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
error= MYSQLparse((void *)thd) || thd->is_fatal_error ||
thd->net.report_error || init_param_array(this);
+
+ /*
+ The first thing we do after parse error is freeing sp_head to
+ ensure that we have restored original memroot.
+ */
+ if (error && lex->sphead)
+ {
+ delete lex->sphead;
+ lex->sphead= NULL;
+ }
/*
While doing context analysis of the query (in check_prepared_statement)
we allocate a lot of additional memory: for open tables, JOINs, derived
@@ -2788,16 +2819,17 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
external changes when cleaning up after validation.
*/
DBUG_ASSERT(thd->change_list.is_empty());
- /*
- If the free_list is not empty, we'll wrongly free some externally
- allocated items when cleaning up after validation of the prepared
- statement.
+
+ /*
+ The only case where we should have items in the thd->free_list is
+ after stmt->set_params_from_vars(), which may in some cases create
+ Item_null objects.
*/
- DBUG_ASSERT(thd->free_list == NULL);
if (error == 0)
error= check_prepared_statement(this, name.str != 0);
+ /* Free sp_head if check_prepared_statement() failed. */
if (error && lex->sphead)
{
delete lex->sphead;
@@ -2847,7 +2879,6 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
{
Statement stmt_backup;
Query_arena *old_stmt_arena;
- Item *old_free_list;
bool error= TRUE;
statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status);
@@ -2891,7 +2922,13 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
allocated items when cleaning up after execution of this statement.
*/
DBUG_ASSERT(thd->change_list.is_empty());
- DBUG_ASSERT(thd->free_list == NULL);
+
+ /*
+ The only case where we should have items in the thd->free_list is
+ after stmt->set_params_from_vars(), which may in some cases create
+ Item_null objects.
+ */
+
thd->set_n_backup_statement(this, &stmt_backup);
if (expanded_query->length() &&
alloc_query(thd, (char*) expanded_query->ptr(),
@@ -2909,6 +2946,12 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
stmt_backup.query_length= thd->query_length;
/*
+ Save orig_sql_command as we use it to disable slow logging for SHOW
+ commands (see log_slow_statement()).
+ */
+ stmt_backup.lex->orig_sql_command= thd->lex->orig_sql_command;
+
+ /*
At first execution of prepared statement we may perform logical
transformations of the query tree. Such changes should be performed
on the parse tree of current prepared statement and new items should
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index c87a8696bbc..8beb9839177 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -257,7 +257,7 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
static TABLE_LIST *
rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
{
- TABLE_LIST *ren_table,*new_table, *tmp_table;
+ TABLE_LIST *ren_table, *new_table;
DBUG_ENTER("rename_tables");
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index e1933d42f9e..8da8bbe25ca 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -430,6 +430,12 @@ impossible position";
goto err;
}
packet->set("\0", 1, &my_charset_bin);
+ /*
+ Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become
+ this larger than the corresponding packet (query) sent
+ from client to master.
+ */
+ thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER;
/*
We can set log_lock now, it does not move (it's a member of
@@ -1101,7 +1107,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
{
mi->master_log_pos= lex_mi->pos;
}
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
if (lex_mi->host)
strmake(mi->host, lex_mi->host, sizeof(mi->host)-1);
@@ -1218,7 +1224,7 @@ bool change_master(THD* thd, MASTER_INFO* mi)
}
}
mi->rli.group_master_log_pos = mi->master_log_pos;
- DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
+ DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos));
/*
Coordinates in rli were spoilt by the 'if (need_relay_log_purge)' block,
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index cfc068cec86..3d2f46a9982 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -82,7 +82,7 @@ static store_key *get_store_key(THD *thd,
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
static void make_outerjoin_info(JOIN *join);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
-static void make_join_readinfo(JOIN *join,uint options);
+static void make_join_readinfo(JOIN *join, ulonglong options);
static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
static void update_depend_map(JOIN *join);
static void update_depend_map(JOIN *join, ORDER *order);
@@ -90,7 +90,7 @@ static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
bool change_list, bool *simple_order);
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
List<Item> &fields, bool send_row,
- uint select_options, const char *info,
+ ulonglong select_options, const char *info,
Item *having);
static COND *build_equal_items(THD *thd, COND *cond,
COND_EQUAL *inherited,
@@ -114,7 +114,7 @@ static bool resolve_nested_join (TABLE_LIST *table);
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
- ulong options);
+ ulonglong options);
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
Procedure *proc);
@@ -699,6 +699,8 @@ JOIN::optimize()
{
if (res > 1)
{
+ thd->fatal_error();
+ error= res;
DBUG_PRINT("error",("Error from opt_sum_query"));
DBUG_RETURN(1);
}
@@ -1469,6 +1471,7 @@ JOIN::exec()
curr_join->examined_rows= 0;
if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
+ !thd->lex->describe &&
get_schema_tables_result(curr_join))
{
DBUG_VOID_RETURN;
@@ -1971,7 +1974,7 @@ bool
mysql_select(THD *thd, Item ***rref_pointer_array,
TABLE_LIST *tables, uint wild_num, List<Item> &fields,
COND *conds, uint og_num, ORDER *order, ORDER *group,
- Item *having, ORDER *proc_param, ulong select_options,
+ Item *having, ORDER *proc_param, ulonglong select_options,
select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex)
{
@@ -2160,7 +2163,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
s->needed_reg.init();
table_vector[i]=s->table=table=tables->table;
table->pos_in_table_list= tables;
- table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);// record count
+ error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ if(error)
+ {
+ table->file->print_error(error, MYF(0));
+ DBUG_RETURN(1);
+ }
table->quick_keys.clear_all();
table->reginfo.join_tab=s;
table->reginfo.not_exists_optimize=0;
@@ -4115,7 +4123,7 @@ choose_plan(JOIN *join, table_map join_tables)
{
uint search_depth= join->thd->variables.optimizer_search_depth;
uint prune_level= join->thd->variables.optimizer_prune_level;
- bool straight_join= join->select_options & SELECT_STRAIGHT_JOIN;
+ bool straight_join= test(join->select_options & SELECT_STRAIGHT_JOIN);
DBUG_ENTER("choose_plan");
join->cur_embedding_map= 0;
@@ -4717,8 +4725,6 @@ static void
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
double read_time)
{
- ha_rows rec;
- double tmp;
THD *thd= join->thd;
if (!rest_tables)
{
@@ -5772,7 +5778,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
}
static void
-make_join_readinfo(JOIN *join, uint options)
+make_join_readinfo(JOIN *join, ulonglong options)
{
uint i;
@@ -6427,7 +6433,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
static int
return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
- List<Item> &fields, bool send_row, uint select_options,
+ List<Item> &fields, bool send_row, ulonglong select_options,
const char *info, Item *having)
{
DBUG_ENTER("return_zero_rows");
@@ -6978,7 +6984,6 @@ static COND *build_equal_items_for_cond(COND *cond,
Item_equal *item_equal;
uint members;
COND_EQUAL cond_equal;
- COND *new_cond;
cond_equal.upper_levels= inherited;
if (cond->type() == Item::COND_ITEM)
@@ -8618,6 +8623,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
item->collation.collation);
else
new_field= item->make_string_field(table);
+ new_field->set_derivation(item->collation.derivation);
break;
case DECIMAL_RESULT:
new_field= new Field_new_decimal(item->max_length, maybe_null, item->name,
@@ -8793,7 +8799,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
(make_copy_field ? 0 : copy_func),
modify_item, convert_blob_length);
case Item::TYPE_HOLDER:
- return ((Item_type_holder *)item)->make_field_by_type(table);
+ result= ((Item_type_holder *)item)->make_field_by_type(table);
+ result->set_derivation(item->collation.derivation);
+ return result;
default: // Dosen't have to be stored
return 0;
}
@@ -9309,13 +9317,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
param->recinfo=recinfo;
store_record(table,s->default_values); // Make empty default record
- if (thd->variables.tmp_table_size == ~(ulong) 0) // No limit
+ if (thd->variables.tmp_table_size == ~ (ulonglong) 0) // No limit
table->s->max_rows= ~(ha_rows) 0;
else
- table->s->max_rows= (((table->s->db_type == DB_TYPE_HEAP) ?
- min(thd->variables.tmp_table_size,
- thd->variables.max_heap_table_size) :
- thd->variables.tmp_table_size)/ table->s->reclength);
+ table->s->max_rows= (ha_rows) (((table->s->db_type == DB_TYPE_HEAP) ?
+ min(thd->variables.tmp_table_size,
+ thd->variables.max_heap_table_size) :
+ thd->variables.tmp_table_size)/
+ table->s->reclength);
set_if_bigger(table->s->max_rows,1); // For dummy start options
/*
Push the LIMIT clause to the temporary table creation, so that we
@@ -9617,7 +9626,7 @@ static bool open_tmp_table(TABLE *table)
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
- ulong options)
+ ulonglong options)
{
int error;
MI_KEYDEF keydef;
@@ -10023,7 +10032,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (join->result->send_eof())
rc= 1; // Don't send error
}
- DBUG_PRINT("info",("%ld records output",join->send_records));
+ DBUG_PRINT("info",("%ld records output", (long) join->send_records));
}
else
rc= -1;
@@ -11639,7 +11648,7 @@ part_of_refkey(TABLE *table,Field *field)
for (uint part=0 ; part < ref_parts ; part++,key_part++)
if (field->eq(key_part->field) &&
- !(key_part->key_part_flag & HA_PART_KEY_SEG))
+ !(key_part->key_part_flag & (HA_PART_KEY_SEG | HA_NULL_PART)))
return table->reginfo.join_tab->ref.items[part];
}
return (Item*) 0;
@@ -12268,6 +12277,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
/* Fill schema tables with data before filesort if it's necessary */
if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
+ !thd->lex->describe &&
get_schema_tables_result(join))
goto err;
@@ -13596,9 +13606,16 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
if (real_pos->type() == Item::FIELD_ITEM)
{
Item_field *item;
- pos= real_pos;
- if (!(item= new Item_field(thd, ((Item_field*) pos))))
+ if (!(item= new Item_field(thd, ((Item_field*) real_pos))))
goto err;
+ if (pos->type() == Item::REF_ITEM)
+ {
+ /* preserve the names of the ref when dereferncing */
+ Item_ref *ref= (Item_ref *) pos;
+ item->db_name= ref->db_name;
+ item->table_name= ref->table_name;
+ item->name= ref->name;
+ }
pos= item;
if (item->field->flags & BLOB_FLAG)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index d859db03437..ee310ea6fe4 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -464,7 +464,6 @@ bool mysqld_show_create_db(THD *thd, char *dbname,
HA_CREATE_INFO *create_info)
{
Security_context *sctx= thd->security_ctx;
- int length;
char buff[2048];
String buffer(buff, sizeof(buff), system_charset_info);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -1323,7 +1322,9 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
"%s:%u", tmp_sctx->host_or_ip, tmp->peer_port);
}
else
- thd_info->host= thd->strdup(tmp_sctx->host_or_ip);
+ thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ?
+ tmp_sctx->host_or_ip :
+ tmp_sctx->host ? tmp_sctx->host : "");
if ((thd_info->db=tmp->db)) // Safe test
thd_info->db=thd->strdup(thd_info->db);
thd_info->command=(int) tmp->command;
@@ -2365,7 +2366,6 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond)
INDEX_FIELD_VALUES idx_field_vals;
List<char> files;
char *file_name;
- uint length;
bool with_i_schema;
HA_CREATE_INFO create;
TABLE *table= tables->table;
@@ -2937,7 +2937,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
restore_record(table, s->default_values);
if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0))
{
- int enum_idx= proc_table->field[5]->val_int();
+ int enum_idx= (int) proc_table->field[5]->val_int();
table->field[3]->store(sp_name.ptr(), sp_name.length(), cs);
get_field(thd->mem_root, proc_table->field[3], &tmp_string);
table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs);
@@ -3103,7 +3103,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
show_table->field[key_part->fieldnr-1]->key_length()))
{
table->field[10]->store((longlong) key_part->length /
- key_part->field->charset()->mbmaxlen);
+ key_part->field->charset()->mbmaxlen, 1);
table->field[10]->set_notnull();
}
uint flags= key_part->field ? key_part->field->flags : 0;
@@ -4044,7 +4044,7 @@ ST_FIELD_INFO columns_fields_info[]=
{"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
{"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field"},
{"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
- {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"},
+ {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0, 1, "Default"},
{"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
{"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
{"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 7aaca809113..85ff1fddc45 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -854,6 +854,162 @@ outp:
}
+/*
+ copy a string,
+ with optional character set conversion,
+ with optional left padding (for binary -> UCS2 conversion)
+
+ SYNOPSIS
+ well_formed_copy_nhars()
+ to Store result here
+ to_length Maxinum length of "to" string
+ to_cs Character set of "to" string
+ from Copy from here
+ from_length Length of from string
+ from_cs From character set
+ nchars Copy not more that nchars characters
+ well_formed_error_pos Return position when "from" is not well formed
+ or NULL otherwise.
+ cannot_convert_error_pos Return position where a not convertable
+ character met, or NULL otherwise.
+ from_end_pos Return position where scanning of "from"
+ string stopped.
+ NOTES
+
+ RETURN
+ length of bytes copied to 'to'
+*/
+
+
+uint32
+well_formed_copy_nchars(CHARSET_INFO *to_cs,
+ char *to, uint to_length,
+ CHARSET_INFO *from_cs,
+ const char *from, uint from_length,
+ uint nchars,
+ const char **well_formed_error_pos,
+ const char **cannot_convert_error_pos,
+ const char **from_end_pos)
+{
+ uint res;
+
+ if ((to_cs == &my_charset_bin) ||
+ (from_cs == &my_charset_bin) ||
+ (to_cs == from_cs) ||
+ my_charset_same(from_cs, to_cs))
+ {
+ if (to_length < to_cs->mbminlen || !nchars)
+ {
+ *from_end_pos= from;
+ *cannot_convert_error_pos= NULL;
+ *well_formed_error_pos= NULL;
+ return 0;
+ }
+
+ if (to_cs == &my_charset_bin)
+ {
+ res= min(min(nchars, to_length), from_length);
+ memmove(to, from, res);
+ *from_end_pos= from + res;
+ *well_formed_error_pos= NULL;
+ *cannot_convert_error_pos= NULL;
+ }
+ else
+ {
+ int well_formed_error;
+ uint from_offset;
+
+ if ((from_offset= (from_length % to_cs->mbminlen)) &&
+ (from_cs == &my_charset_bin))
+ {
+ /*
+ Copying from BINARY to UCS2 needs to prepend zeros sometimes:
+ INSERT INTO t1 (ucs2_column) VALUES (0x01);
+ 0x01 -> 0x0001
+ */
+ uint pad_length= to_cs->mbminlen - from_offset;
+ bzero(to, pad_length);
+ memmove(to + pad_length, from, from_offset);
+ nchars--;
+ from+= from_offset;
+ from_length-= from_offset;
+ to+= to_cs->mbminlen;
+ to_length-= to_cs->mbminlen;
+ }
+
+ set_if_smaller(from_length, to_length);
+ res= to_cs->cset->well_formed_len(to_cs, from, from + from_length,
+ nchars, &well_formed_error);
+ memmove(to, from, res);
+ *from_end_pos= from + res;
+ *well_formed_error_pos= well_formed_error ? from + res : NULL;
+ *cannot_convert_error_pos= NULL;
+ if (from_offset)
+ res+= to_cs->mbminlen;
+ }
+ }
+ else
+ {
+ int cnvres;
+ my_wc_t wc;
+ int (*mb_wc)(struct charset_info_st *, my_wc_t *,
+ const uchar *, const uchar *)= from_cs->cset->mb_wc;
+ int (*wc_mb)(struct charset_info_st *, my_wc_t,
+ uchar *s, uchar *e)= to_cs->cset->wc_mb;
+ const uchar *from_end= (const uchar*) from + from_length;
+ uchar *to_end= (uchar*) to + to_length;
+ char *to_start= to;
+ *well_formed_error_pos= NULL;
+ *cannot_convert_error_pos= NULL;
+
+ for ( ; nchars; nchars--)
+ {
+ const char *from_prev= from;
+ if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
+ from+= cnvres;
+ else if (cnvres == MY_CS_ILSEQ)
+ {
+ if (!*well_formed_error_pos)
+ *well_formed_error_pos= from;
+ from++;
+ wc= '?';
+ }
+ else if (cnvres > MY_CS_TOOSMALL)
+ {
+ /*
+ A correct multibyte sequence detected
+ But it doesn't have Unicode mapping.
+ */
+ if (!*cannot_convert_error_pos)
+ *cannot_convert_error_pos= from;
+ from+= (-cnvres);
+ wc= '?';
+ }
+ else
+ break; // Not enough characters
+
+outp:
+ if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
+ to+= cnvres;
+ else if (cnvres == MY_CS_ILUNI && wc != '?')
+ {
+ if (!*cannot_convert_error_pos)
+ *cannot_convert_error_pos= from_prev;
+ wc= '?';
+ goto outp;
+ }
+ else
+ break;
+ }
+ *from_end_pos= from;
+ res= to - to_start;
+ }
+ return (uint32) res;
+}
+
+
+
+
void String::print(String *str)
{
char *st= (char*)Ptr, *end= st+str_length;
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 0659f684afe..2be2cca5427 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -32,6 +32,14 @@ String *copy_if_not_alloced(String *a,String *b,uint32 arg_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);
+uint32 well_formed_copy_nchars(CHARSET_INFO *to_cs,
+ char *to, uint to_length,
+ CHARSET_INFO *from_cs,
+ const char *from, uint from_length,
+ uint nchars,
+ const char **well_formed_error_pos,
+ const char **cannot_convert_error_pos,
+ const char **from_end_pos);
class String
{
@@ -355,3 +363,9 @@ public:
return (s->alloced && Ptr >= s->Ptr && Ptr < s->Ptr + s->str_length);
}
};
+
+static inline bool check_if_only_end_space(CHARSET_INFO *cs, char *str,
+ char *end)
+{
+ return str+ cs->cset->scan(cs, str, end, MY_SEQ_SPACES) == end;
+}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3fc74ad1371..c14529f6eb1 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2933,208 +2933,6 @@ err:
}
-#ifdef NOT_USED
-/*
- CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
- the proper arguments. This isn't very fast but it should work for most
- cases.
- One should normally create all indexes with CREATE TABLE or ALTER TABLE.
-*/
-
-int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
-{
- List<create_field> fields;
- List<Alter_drop> drop;
- List<Alter_column> alter;
- HA_CREATE_INFO create_info;
- int rc;
- uint idx;
- uint db_options;
- uint key_count;
- TABLE *table;
- Field **f_ptr;
- KEY *key_info_buffer;
- char path[FN_REFLEN+1];
- DBUG_ENTER("mysql_create_index");
-
- /*
- Try to use online generation of index.
- This requires that all indexes can be created online.
- Otherwise, the old alter table procedure is executed.
-
- Open the table to have access to the correct table handler.
- */
- if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
- DBUG_RETURN(-1);
-
- /*
- The add_index method takes an array of KEY structs for the new indexes.
- Preparing a new table structure generates this array.
- It needs a list with all fields of the table, which does not need to
- be correct in every respect. The field names are important.
- */
- for (f_ptr= table->field; *f_ptr; f_ptr++)
- {
- create_field *c_fld= new create_field(*f_ptr, *f_ptr);
- c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/
- fields.push_back(c_fld);
- }
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
- db_options= 0;
- if (mysql_prepare_table(thd, &create_info, &fields,
- &keys, /*tmp_table*/ 0, &db_options, table->file,
- &key_info_buffer, key_count,
- /*select_field_count*/ 0))
- DBUG_RETURN(-1);
-
- /*
- Check if all keys can be generated with the add_index method.
- If anyone cannot, then take the old way.
- */
- for (idx=0; idx< key_count; idx++)
- {
- DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name));
- if (!(table->file->index_ddl_flags(key_info_buffer+idx)&
- (HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
- break ;
- }
- if ((idx < key_count)|| !key_count)
- {
- /* Re-initialize the create_info, which was changed by prepare table. */
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
- /* Cleanup the fields list. We do not want to create existing fields. */
- fields.delete_elements();
- if (real_alter_table(thd, table_list->db, table_list->table_name,
- &create_info, table_list, table,
- fields, keys, drop, alter, 0, (ORDER*)0,
- ALTER_ADD_INDEX, DUP_ERROR))
- /* Don't need to free((gptr) key_info_buffer);*/
- DBUG_RETURN(-1);
- }
- else
- {
- if (table->file->add_index(table, key_info_buffer, key_count)||
- build_table_path(path, sizeof(path), table_list->db,
- (lower_case_table_names == 2) ?
- table_list->alias : table_list->table_name,
- reg_ext) == 0 ||
- mysql_create_frm(thd, path, &create_info,
- fields, key_count, key_info_buffer, table->file))
- /* don't need to free((gptr) key_info_buffer);*/
- DBUG_RETURN(-1);
- }
- /* don't need to free((gptr) key_info_buffer);*/
- DBUG_RETURN(0);
-}
-
-
-int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
- List<Alter_drop> &drop)
-{
- List<create_field> fields;
- List<Key> keys;
- List<Alter_column> alter;
- HA_CREATE_INFO create_info;
- uint idx;
- uint db_options;
- uint key_count;
- uint *key_numbers;
- TABLE *table;
- Field **f_ptr;
- KEY *key_info;
- KEY *key_info_buffer;
- char path[FN_REFLEN];
- DBUG_ENTER("mysql_drop_index");
-
- /*
- Try to use online generation of index.
- This requires that all indexes can be created online.
- Otherwise, the old alter table procedure is executed.
-
- Open the table to have access to the correct table handler.
- */
- if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
- DBUG_RETURN(-1);
-
- /*
- The drop_index method takes an array of key numbers.
- It cannot get more entries than keys in the table.
- */
- key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys);
- key_count= 0;
-
- /*
- Get the number of each key and check if it can be created online.
- */
- List_iterator<Alter_drop> drop_it(drop);
- Alter_drop *drop_key;
- while ((drop_key= drop_it++))
- {
- /* Find the key in the table. */
- key_info=table->key_info;
- for (idx=0; idx< table->keys; idx++, key_info++)
- {
- if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
- break;
- }
- if (idx>= table->keys)
- {
- my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name);
- /*don't need to free((gptr) key_numbers);*/
- DBUG_RETURN(-1);
- }
- /*
- Check if the key can be generated with the add_index method.
- If anyone cannot, then take the old way.
- */
- DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name));
- if (!(table->file->index_ddl_flags(table->key_info+idx)&
- (HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
- break ;
- key_numbers[key_count++]= idx;
- }
-
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
-
- if ((drop_key)|| (drop.elements<= 0))
- {
- if (real_alter_table(thd, table_list->db, table_list->table_name,
- &create_info, table_list, table,
- fields, keys, drop, alter, 0, (ORDER*)0,
- ALTER_DROP_INDEX, DUP_ERROR))
- /*don't need to free((gptr) key_numbers);*/
- DBUG_RETURN(-1);
- }
- else
- {
- db_options= 0;
- if (table->file->drop_index(table, key_numbers, key_count)||
- mysql_prepare_table(thd, &create_info, &fields,
- &keys, /*tmp_table*/ 0, &db_options, table->file,
- &key_info_buffer, key_count,
- /*select_field_count*/ 0)||
- build_table_path(path, sizeof(path), table_list->db,
- (lower_case_table_names == 2) ?
- table_list->alias : table_list->table_name,
- reg_ext) == 0 ||
- mysql_create_frm(thd, path, &create_info,
- fields, key_count, key_info_buffer, table->file))
- /*don't need to free((gptr) key_numbers);*/
- DBUG_RETURN(-1);
- }
-
- /*don't need to free((gptr) key_numbers);*/
- DBUG_RETURN(0);
-}
-#endif /* NOT_USED */
-
-
/*
Alter table
*/
@@ -3173,6 +2971,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
+ /* Conditionally writes to binlog. */
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
alter_info->tablespace_op));
sprintf(new_name_buff,"%s/%s/%s%s",mysql_data_home, db, table_name, reg_ext);
@@ -3299,10 +3098,10 @@ view_err:
!table->s->tmp_table) // no need to touch frm
{
error=0;
+ VOID(pthread_mutex_lock(&LOCK_open));
if (new_name != table_name || new_db != db)
{
thd->proc_info="rename";
- VOID(pthread_mutex_lock(&LOCK_open));
/* Then do a 'simple' rename of the table */
error=0;
if (!access(new_name_buff,F_OK))
@@ -3324,7 +3123,6 @@ view_err:
error= -1;
}
}
- VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
@@ -3333,16 +3131,12 @@ view_err:
case LEAVE_AS_IS:
break;
case ENABLE:
- VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
- VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
- VOID(pthread_mutex_unlock(&LOCK_open));
error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */
break;
@@ -3372,6 +3166,7 @@ view_err:
table->file->print_error(error, MYF(0));
error= -1;
}
+ VOID(pthread_mutex_unlock(&LOCK_open));
table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
DBUG_RETURN(error);
@@ -3818,6 +3613,10 @@ view_err:
my_free((gptr) new_table,MYF(0));
goto err;
}
+ /*
+ Writing to the binlog does not need to be synchronized for temporary tables,
+ which are thread-specific.
+ */
if (mysql_bin_log.is_open())
{
thd->clear_error();
@@ -4000,7 +3799,7 @@ end_temporary:
thd->some_tables_deleted=0;
DBUG_RETURN(FALSE);
- err:
+err:
DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index c0c9c34cbeb..3569733d064 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -36,17 +36,17 @@ static File_option triggers_file_parameters[]=
{
{
{(char *) STRING_WITH_LEN("triggers") },
- offsetof(class Table_triggers_list, definitions_list),
+ my_offsetof(class Table_triggers_list, definitions_list),
FILE_OPTIONS_STRLIST
},
{
{(char *) STRING_WITH_LEN("sql_modes") },
- offsetof(class Table_triggers_list, definition_modes_list),
+ my_offsetof(class Table_triggers_list, definition_modes_list),
FILE_OPTIONS_ULLLIST
},
{
{(char *) STRING_WITH_LEN("definers") },
- offsetof(class Table_triggers_list, definers_list),
+ my_offsetof(class Table_triggers_list, definers_list),
FILE_OPTIONS_STRLIST
},
{ { 0, 0 }, 0, FILE_OPTIONS_STRING }
@@ -55,7 +55,7 @@ static File_option triggers_file_parameters[]=
File_option sql_modes_parameters=
{
{(char*) STRING_WITH_LEN("sql_modes") },
- offsetof(class Table_triggers_list, definition_modes_list),
+ my_offsetof(class Table_triggers_list, definition_modes_list),
FILE_OPTIONS_ULLLIST
};
@@ -107,7 +107,9 @@ const LEX_STRING trg_event_type_names[]=
};
-static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig);
+static int
+add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
+ TABLE_LIST ** table);
class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook
{
@@ -156,6 +158,13 @@ private:
*/
bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
{
+ /*
+ FIXME: The code below takes too many different paths depending on the
+ 'create' flag, so that the justification for a single function
+ 'mysql_create_or_drop_trigger', compared to two separate functions
+ 'mysql_create_trigger' and 'mysql_drop_trigger' is not apparent.
+ This is a good candidate for a minor refactoring.
+ */
TABLE *table;
bool result= TRUE;
String stmt_query;
@@ -181,10 +190,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
DBUG_RETURN(TRUE);
}
- if (!create &&
- !(tables= add_table_for_trigger(thd, thd->lex->spname)))
- DBUG_RETURN(TRUE);
-
/*
We don't allow creating triggers on tables in the 'mysql' schema
*/
@@ -194,9 +199,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
DBUG_RETURN(TRUE);
}
- /* We should have only one table in table list. */
- DBUG_ASSERT(tables->next_global == 0);
-
/*
TODO: We should check if user has TRIGGER privilege for table here.
Now we just require SUPER privilege for creating/dropping because
@@ -211,7 +213,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
DROP for example) so we do the check for privileges. For now there is
already a stronger test right above; but when this stronger test will
be removed, the test below will hold. Because triggers have the same
- nature as functions regarding binlogging: their body is implicitely
+ nature as functions regarding binlogging: their body is implicitly
binlogged, so they share the same danger, so trust_function_creators
applies to them too.
*/
@@ -222,24 +224,52 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
DBUG_RETURN(TRUE);
}
- /* We do not allow creation of triggers on temporary tables. */
- if (create && find_temporary_table(thd, tables->db, tables->table_name))
- {
- my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
- DBUG_RETURN(TRUE);
- }
-
/*
We don't want perform our operations while global read lock is held
- so we have to wait until its end and then prevent it from occuring
+ so we have to wait until its end and then prevent it from occurring
again until we are done. (Acquiring LOCK_open is not enough because
- global read lock is held without helding LOCK_open).
+ global read lock is held without holding LOCK_open).
*/
if (wait_if_global_read_lock(thd, 0, 1))
DBUG_RETURN(TRUE);
VOID(pthread_mutex_lock(&LOCK_open));
+ if (!create)
+ {
+ bool if_exists= thd->lex->drop_if_exists;
+
+ if (add_table_for_trigger(thd, thd->lex->spname, if_exists, & tables))
+ goto end;
+
+ if (!tables)
+ {
+ DBUG_ASSERT(if_exists);
+ /*
+ Since the trigger does not exist, there is no associated table,
+ and therefore :
+ - no TRIGGER privileges to check,
+ - no trigger to drop,
+ - no table to lock/modify,
+ so the drop statement is successful.
+ */
+ result= FALSE;
+ /* Still, we need to log the query ... */
+ stmt_query.append(thd->query, thd->query_length);
+ goto end;
+ }
+ }
+
+ /* We should have only one table in table list. */
+ DBUG_ASSERT(tables->next_global == 0);
+
+ /* We do not allow creation of triggers on temporary tables. */
+ if (create && find_temporary_table(thd, tables->db, tables->table_name))
+ {
+ my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
+ goto end;
+ }
+
if (lock_table_names(thd, tables))
goto end;
@@ -270,8 +300,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
table->triggers->drop_trigger(thd, tables, &stmt_query));
end:
- VOID(pthread_mutex_unlock(&LOCK_open));
- start_waiting_global_read_lock(thd);
if (!result)
{
@@ -284,9 +312,13 @@ end:
FALSE);
mysql_bin_log.write(&qinfo);
}
+ }
+
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ start_waiting_global_read_lock(thd);
+ if (!result)
send_ok(thd);
- }
DBUG_RETURN(result);
}
@@ -324,7 +356,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
char dir_buff[FN_REFLEN], file_buff[FN_REFLEN], trigname_buff[FN_REFLEN],
trigname_path[FN_REFLEN];
LEX_STRING dir, file, trigname_file;
- LEX_STRING *trg_def, *name;
+ LEX_STRING *trg_def;
LEX_STRING definer_user;
LEX_STRING definer_host;
ulonglong *trg_sql_mode;
@@ -847,7 +879,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
DBUG_RETURN(1);
List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
- LEX_STRING *trg_create_str, *trg_name_str;
+ LEX_STRING *trg_create_str;
ulonglong *trg_sql_mode;
if (triggers->definition_modes_list.is_empty() &&
@@ -964,7 +996,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
goto err_with_lex_cleanup;
}
- lex.sphead->set_info(0, 0, &lex.sp_chistics, *trg_sql_mode);
+ lex.sphead->set_info(0, 0, &lex.sp_chistics, (ulong) *trg_sql_mode);
triggers->bodies[lex.trg_chistics.event]
[lex.trg_chistics.action_time]= lex.sphead;
@@ -1143,13 +1175,17 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
mysql_table_for_trigger()
thd - current thread context
trig - identifier for trigger
+ if_exists - treat a not existing trigger as a warning if TRUE
+ table - pointer to TABLE_LIST object for the table trigger (output)
RETURN VALUE
- 0 - error
- # - pointer to TABLE_LIST object for the table
+ 0 Success
+ 1 Error
*/
-static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
+static int
+add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
+ TABLE_LIST **table)
{
LEX *lex= thd->lex;
char path_buff[FN_REFLEN];
@@ -1160,6 +1196,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
path_buff, &trigname.trigger_table);
DBUG_ENTER("add_table_for_trigger");
+ DBUG_ASSERT(table != NULL);
strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", trig->m_db.str, "/",
trig->m_name.str, trigname_file_ext, NullS);
@@ -1168,30 +1205,45 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
if (access(path_buff, F_OK))
{
+ if (if_exists)
+ {
+ push_warning_printf(thd,
+ MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TRG_DOES_NOT_EXIST,
+ ER(ER_TRG_DOES_NOT_EXIST));
+ *table= NULL;
+ DBUG_RETURN(0);
+ }
+
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
}
if (!(parser= sql_parse_prepare(&path, thd->mem_root, 1)))
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
if (!is_equal(&trigname_file_type, parser->type()))
{
my_error(ER_WRONG_OBJECT, MYF(0), trig->m_name.str, trigname_file_ext+1,
"TRIGGERNAME");
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
}
if (parser->parse((gptr)&trigname, thd->mem_root,
trigname_file_parameters, 1,
&trigger_table_hook))
- DBUG_RETURN(0);
+ DBUG_RETURN(1);
/* We need to reset statement table list to be PS/SP friendly. */
lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
- DBUG_RETURN(sp_add_to_query_tables(thd, lex, trig->m_db.str,
- trigname.trigger_table.str, TL_IGNORE));
+ *table= sp_add_to_query_tables(thd, lex, trig->m_db.str,
+ trigname.trigger_table.str, TL_IGNORE);
+
+ if (! *table)
+ DBUG_RETURN(1);
+
+ DBUG_RETURN(0);
}
@@ -1285,7 +1337,6 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd,
{
char path_buff[FN_REFLEN];
LEX_STRING *def, *on_table_name, new_def;
- ulonglong *sql_mode;
ulong save_sql_mode= thd->variables.sql_mode;
List_iterator_fast<LEX_STRING> it_def(definitions_list);
List_iterator_fast<LEX_STRING> it_on_table_name(on_table_names_list);
@@ -1299,7 +1350,7 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd,
while ((def= it_def++))
{
on_table_name= it_on_table_name++;
- thd->variables.sql_mode= *(it_mode++);
+ thd->variables.sql_mode= (ulong) *(it_mode++);
/* Construct CREATE TRIGGER statement with new table name. */
buff.length(0);
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index c5af81ae55a..478b2dce370 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -496,7 +496,12 @@ bool st_select_lex_unit::exec()
DBUG_RETURN(res);
}
/* Needed for the following test and for records_at_start in next loop */
- table->file->info(HA_STATUS_VARIABLE);
+ int error= table->file->info(HA_STATUS_VARIABLE);
+ if(error)
+ {
+ table->file->print_error(error, MYF(0));
+ DBUG_RETURN(1);
+ }
if (found_rows_for_union && !sl->braces &&
select_limit_cnt != HA_POS_ERROR)
{
@@ -689,7 +694,17 @@ bool st_select_lex_unit::change_result(select_subselect *result,
List<Item> *st_select_lex_unit::get_unit_column_types()
{
- bool is_union= test(first_select()->next_select());
+ SELECT_LEX *sl= first_select();
+ bool is_union= test(sl->next_select());
+ bool is_procedure= test(sl->join->procedure);
+
+ if (is_procedure)
+ {
+ /* Types for "SELECT * FROM t1 procedure analyse()"
+ are generated during execute */
+ return &sl->join->procedure_fields_list;
+ }
+
if (is_union)
{
@@ -697,7 +712,8 @@ List<Item> *st_select_lex_unit::get_unit_column_types()
/* Types are generated during prepare */
return &types;
}
- return &first_select()->item_list;
+
+ return &sl->item_list;
}
bool st_select_lex::cleanup()
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index d431b671f18..3b6aa5f1aa2 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -118,7 +118,7 @@ int mysql_update(THD *thd,
enum enum_duplicates handle_duplicates, bool ignore)
{
bool using_limit= limit != HA_POS_ERROR;
- bool safe_update= thd->options & OPTION_SAFE_UPDATES;
+ bool safe_update= test(thd->options & OPTION_SAFE_UPDATES);
bool used_key_is_modified, transactional_table;
bool can_compare_record;
int res;
@@ -569,7 +569,7 @@ int mysql_update(THD *thd,
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
send_ok(thd, (ulong) thd->row_count_func,
thd->insert_id_used ? thd->last_insert_id : 0L,buff);
- DBUG_PRINT("info",("%d records updated",updated));
+ DBUG_PRINT("info",("%ld records updated", (long) updated));
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
thd->abort_on_warning= 0;
@@ -667,7 +667,7 @@ static table_map get_table_map(List<Item> *items)
while ((item= (Item_field *) item_it++))
map|= item->used_tables();
- DBUG_PRINT("info",("table_map: 0x%08x", map));
+ DBUG_PRINT("info", ("table_map: 0x%08lx", (long) map));
return map;
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 94c5ad331dd..53844eb0fd2 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -197,7 +197,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
lex->definer= &view->definer;
}
if (lex->create_view_algorithm == VIEW_ALGORITHM_UNDEFINED)
- lex->create_view_algorithm= decoy.algorithm;
+ lex->create_view_algorithm= (uint8) decoy.algorithm;
if (lex->create_view_suid == VIEW_SUID_DEFAULT)
lex->create_view_suid= decoy.view_suid ?
VIEW_SUID_DEFINER : VIEW_SUID_INVOKER;
@@ -212,6 +212,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
SYNOPSIS
mysql_create_view()
thd - thread handler
+ views - views to create
mode - VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
RETURN VALUE
@@ -219,7 +220,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
TRUE Error
*/
-bool mysql_create_view(THD *thd,
+bool mysql_create_view(THD *thd, TABLE_LIST *views,
enum_view_create_mode mode)
{
LEX *lex= thd->lex;
@@ -236,25 +237,9 @@ bool mysql_create_view(THD *thd,
bool res= FALSE;
DBUG_ENTER("mysql_create_view");
- if (lex->proc_list.first ||
- lex->result)
- {
- my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), (lex->result ?
- "INTO" :
- "PROCEDURE"));
- res= TRUE;
- goto err;
- }
- if (lex->derived_tables ||
- lex->variables_used || lex->param_list.elements)
- {
- int err= (lex->derived_tables ?
- ER_VIEW_SELECT_DERIVED :
- ER_VIEW_SELECT_VARIABLE);
- my_message(err, ER(err), MYF(0));
- res= TRUE;
- goto err;
- }
+ /* This is ensured in the parser. */
+ DBUG_ASSERT(!lex->proc_list.first && !lex->result &&
+ !lex->param_list.elements && !lex->derived_tables);
if (mode != VIEW_CREATE_NEW)
{
@@ -548,6 +533,50 @@ bool mysql_create_view(THD *thd,
}
VOID(pthread_mutex_lock(&LOCK_open));
res= mysql_register_view(thd, view, mode);
+
+ if (mysql_bin_log.is_open())
+ {
+ String buff;
+ const LEX_STRING command[3]=
+ {{(char *)STRING_WITH_LEN("CREATE ")},
+ {(char *)STRING_WITH_LEN("ALTER ")},
+ {(char *)STRING_WITH_LEN("CREATE OR REPLACE ")}};
+
+ buff.append(command[thd->lex->create_view_mode].str,
+ command[thd->lex->create_view_mode].length);
+ view_store_options(thd, views, &buff);
+ buff.append(STRING_WITH_LEN("VIEW "));
+
+ /* Test if user supplied a db (ie: we did not use thd->db) */
+ if (views->db && views->db[0] &&
+ (thd->db == NULL || strcmp(views->db, thd->db)))
+ {
+ append_identifier(thd, &buff, views->db,
+ views->db_length);
+ buff.append('.');
+ }
+ append_identifier(thd, &buff, views->table_name,
+ views->table_name_length);
+ if (lex->view_list.elements)
+ {
+ List_iterator_fast<LEX_STRING> names(lex->view_list);
+ LEX_STRING *name;
+ int i;
+
+ for (i= 0; (name= names++); i++)
+ {
+ buff.append(i ? ", " : "(");
+ append_identifier(thd, &buff, name->str, name->length);
+ }
+ buff.append(')');
+ }
+ buff.append(STRING_WITH_LEN(" AS "));
+ buff.append(views->source.str, views->source.length);
+
+ Query_log_event qinfo(thd, buff.ptr(), buff.length(), 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+
VOID(pthread_mutex_unlock(&LOCK_open));
if (view->revision != 1)
query_cache_invalidate3(thd, view, 0);
@@ -582,40 +611,40 @@ static const int num_view_backups= 3;
*/
static File_option view_parameters[]=
{{{(char*) STRING_WITH_LEN("query")},
- offsetof(TABLE_LIST, query),
+ my_offsetof(TABLE_LIST, query),
FILE_OPTIONS_ESTRING},
{{(char*) STRING_WITH_LEN("md5")},
- offsetof(TABLE_LIST, md5),
+ my_offsetof(TABLE_LIST, md5),
FILE_OPTIONS_STRING},
{{(char*) STRING_WITH_LEN("updatable")},
- offsetof(TABLE_LIST, updatable_view),
+ my_offsetof(TABLE_LIST, updatable_view),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("algorithm")},
- offsetof(TABLE_LIST, algorithm),
+ my_offsetof(TABLE_LIST, algorithm),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("definer_user")},
- offsetof(TABLE_LIST, definer.user),
+ my_offsetof(TABLE_LIST, definer.user),
FILE_OPTIONS_STRING},
{{(char*) STRING_WITH_LEN("definer_host")},
- offsetof(TABLE_LIST, definer.host),
+ my_offsetof(TABLE_LIST, definer.host),
FILE_OPTIONS_STRING},
{{(char*) STRING_WITH_LEN("suid")},
- offsetof(TABLE_LIST, view_suid),
+ my_offsetof(TABLE_LIST, view_suid),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("with_check_option")},
- offsetof(TABLE_LIST, with_check),
+ my_offsetof(TABLE_LIST, with_check),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("revision")},
- offsetof(TABLE_LIST, revision),
+ my_offsetof(TABLE_LIST, revision),
FILE_OPTIONS_REV},
{{(char*) STRING_WITH_LEN("timestamp")},
- offsetof(TABLE_LIST, timestamp),
+ my_offsetof(TABLE_LIST, timestamp),
FILE_OPTIONS_TIMESTAMP},
{{(char*)STRING_WITH_LEN("create-version")},
- offsetof(TABLE_LIST, file_version),
+ my_offsetof(TABLE_LIST, file_version),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("source")},
- offsetof(TABLE_LIST, source),
+ my_offsetof(TABLE_LIST, source),
FILE_OPTIONS_ESTRING},
{{NullS, 0}, 0,
FILE_OPTIONS_STRING}
@@ -1306,12 +1335,12 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
char *wrong_object_db= NULL, *wrong_object_name= NULL;
bool error= FALSE;
+ VOID(pthread_mutex_lock(&LOCK_open));
for (view= views; view; view= view->next_local)
{
strxnmov(path, FN_REFLEN, mysql_data_home, "/", view->db, "/",
view->table_name, reg_ext, NullS);
(void) unpack_filename(path, path);
- VOID(pthread_mutex_lock(&LOCK_open));
type= FRMTYPE_ERROR;
if (access(path, F_OK) ||
FRMTYPE_VIEW != (type= mysql_frm_type(thd, path, &not_used)))
@@ -1323,7 +1352,6 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
name);
- VOID(pthread_mutex_unlock(&LOCK_open));
continue;
}
if (type == FRMTYPE_TABLE)
@@ -1340,15 +1368,22 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
non_existant_views.append(',');
non_existant_views.append(String(view->table_name,system_charset_info));
}
- VOID(pthread_mutex_unlock(&LOCK_open));
continue;
}
if (my_delete(path, MYF(MY_WME)))
error= TRUE;
query_cache_invalidate3(thd, view, 0);
sp_cache_invalidate();
- VOID(pthread_mutex_unlock(&LOCK_open));
}
+ if (mysql_bin_log.is_open())
+ {
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+
+ VOID(pthread_mutex_unlock(&LOCK_open));
+
if (error)
{
DBUG_RETURN(TRUE);
@@ -1442,7 +1477,6 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
TABLE *table;
Field_translator *trans, *end_of_trans;
KEY *key_info, *key_info_end;
- uint i;
DBUG_ENTER("check_key_in_view");
/*
diff --git a/sql/sql_view.h b/sql/sql_view.h
index b6c27a60eeb..a3f11f352b0 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-bool mysql_create_view(THD *thd,
+bool mysql_create_view(THD *thd, TABLE_LIST *view,
enum_view_create_mode mode);
bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e5c11f6d437..a362d1ce4ea 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -746,7 +746,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
- bool_term bool_factor bool_test bool_pri
+ variable variable_aux bool_term bool_factor bool_test bool_pri
predicate bit_expr bit_term bit_factor value_expr term factor
table_wild simple_expr udf_expr
expr_or_default set_expr_or_default interval_expr
@@ -1444,15 +1444,20 @@ call:
lex->value_list.empty();
sp_add_used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE);
}
- '(' sp_cparam_list ')' {}
+ opt_sp_cparam_list {}
;
/* CALL parameters */
-sp_cparam_list:
+opt_sp_cparam_list:
/* Empty */
- | sp_cparams
+ | '(' opt_sp_cparams ')'
;
+opt_sp_cparams:
+ /* Empty */
+ | sp_cparams
+ ;
+
sp_cparams:
sp_cparams ',' expr
{
@@ -1621,7 +1626,6 @@ sp_decl:
uint num_vars= pctx->context_var_count();
enum enum_field_types var_type= (enum enum_field_types) $4;
Item *dflt_value_item= $5;
- create_field *create_field_op;
if (!dflt_value_item)
{
@@ -4322,32 +4326,7 @@ simple_expr:
}
| literal
| param_marker
- | '@' ident_or_text SET_VAR expr
- {
- $$= new Item_func_set_user_var($2,$4);
- LEX *lex= Lex;
- lex->uncacheable(UNCACHEABLE_RAND);
- lex->variables_used= 1;
- }
- | '@' ident_or_text
- {
- $$= new Item_func_get_user_var($2);
- LEX *lex= Lex;
- lex->uncacheable(UNCACHEABLE_RAND);
- lex->variables_used= 1;
- }
- | '@' '@' opt_var_ident_type ident_or_text opt_component
- {
-
- if ($4.str && $5.str && check_reserved_words(&$4))
- {
- yyerror(ER(ER_SYNTAX_ERROR));
- YYABORT;
- }
- if (!($$= get_system_var(YYTHD, $3, $4, $5)))
- YYABORT;
- Lex->variables_used= 1;
- }
+ | variable
| sum_expr
| simple_expr OR_OR_SYM simple_expr
{ $$= new Item_func_concat($1, $3); }
@@ -5074,6 +5053,46 @@ sum_expr:
$5->empty();
};
+variable:
+ '@'
+ {
+ if (! Lex->parsing_options.allows_variable)
+ {
+ my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
+ YYABORT;
+ }
+ }
+ variable_aux
+ {
+ $$= $3;
+ }
+ ;
+
+variable_aux:
+ ident_or_text SET_VAR expr
+ {
+ $$= new Item_func_set_user_var($1, $3);
+ LEX *lex= Lex;
+ lex->uncacheable(UNCACHEABLE_RAND);
+ }
+ | ident_or_text
+ {
+ $$= new Item_func_get_user_var($1);
+ LEX *lex= Lex;
+ lex->uncacheable(UNCACHEABLE_RAND);
+ }
+ | '@' opt_var_ident_type ident_or_text opt_component
+ {
+ if ($3.str && $4.str && check_reserved_words(&$3))
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ if (!($$= get_system_var(YYTHD, $2, $3, $4)))
+ YYABORT;
+ }
+ ;
+
opt_distinct:
/* empty */ { $$ = 0; }
|DISTINCT { $$ = 1; };
@@ -5185,7 +5204,7 @@ when_list2:
/* Warning - may return NULL in case of incomplete SELECT */
table_ref:
table_factor { $$=$1; }
- | join_table { $$=$1; }
+ | join_table
{
LEX *lex= Lex;
if (!($$= lex->current_select->nest_last_join(lex->thd)))
@@ -5227,7 +5246,7 @@ join_table:
| table_ref normal_join table_ref
ON
{
- YYERROR_UNLESS($1 && ($$=$3));
+ YYERROR_UNLESS($1 && $3);
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $3))
YYABORT;
@@ -5242,7 +5261,7 @@ join_table:
| table_ref STRAIGHT_JOIN table_factor
ON
{
- YYERROR_UNLESS($1 && ($$=$3));
+ YYERROR_UNLESS($1 && $3);
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $3))
YYABORT;
@@ -5509,6 +5528,13 @@ select_derived_init:
SELECT_SYM
{
LEX *lex= Lex;
+
+ if (! lex->parsing_options.allows_derived)
+ {
+ my_error(ER_VIEW_SELECT_DERIVED, MYF(0));
+ YYABORT;
+ }
+
SELECT_LEX *sel= lex->current_select;
TABLE_LIST *embedding;
if (!sel->embedding || sel->end_nested_join(lex->thd))
@@ -5868,6 +5894,13 @@ procedure_clause:
| PROCEDURE ident /* Procedure name */
{
LEX *lex=Lex;
+
+ if (! lex->parsing_options.allows_select_procedure)
+ {
+ my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE");
+ YYABORT;
+ }
+
if (&lex->select_lex != lex->current_select)
{
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
@@ -5967,28 +6000,40 @@ select_var_ident:
;
into:
- INTO OUTFILE TEXT_STRING_filesystem
+ INTO
+ {
+ if (! Lex->parsing_options.allows_select_into)
+ {
+ my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO");
+ YYABORT;
+ }
+ }
+ into_destination
+ ;
+
+into_destination:
+ OUTFILE TEXT_STRING_filesystem
{
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- if (!(lex->exchange= new sql_exchange($3.str, 0)) ||
+ if (!(lex->exchange= new sql_exchange($2.str, 0)) ||
!(lex->result= new select_export(lex->exchange)))
YYABORT;
}
opt_field_term opt_line_term
- | INTO DUMPFILE TEXT_STRING_filesystem
+ | DUMPFILE TEXT_STRING_filesystem
{
LEX *lex=Lex;
if (!lex->describe)
{
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
- if (!(lex->exchange= new sql_exchange($3.str,1)))
+ if (!(lex->exchange= new sql_exchange($2.str,1)))
YYABORT;
if (!(lex->result= new select_dump(lex->exchange)))
YYABORT;
}
}
- | INTO select_var_list_init
+ | select_var_list_init
{
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
}
@@ -6074,11 +6119,12 @@ drop:
lex->sql_command= SQLCOM_DROP_VIEW;
lex->drop_if_exists= $3;
}
- | DROP TRIGGER_SYM sp_name
+ | DROP TRIGGER_SYM if_exists sp_name
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_TRIGGER;
- lex->spname= $3;
+ lex->drop_if_exists= $3;
+ lex->spname= $4;
}
;
@@ -7007,6 +7053,8 @@ load_data_lock:
Ignore this option in SP to avoid problem with query cache
*/
if (Lex->sphead != 0)
+ $$= YYTHD->update_lock_default;
+ else
#endif
$$= TL_WRITE_CONCURRENT_INSERT;
}
@@ -7148,8 +7196,13 @@ param_marker:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
- Item_param *item= new Item_param((uint) (lex->tok_start -
- (uchar *) thd->query));
+ Item_param *item;
+ if (! lex->parsing_options.allows_variable)
+ {
+ my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
+ YYABORT;
+ }
+ item= new Item_param((uint) (lex->tok_start - (uchar *) thd->query));
if (!($$= item) || lex->param_list.push_back(item))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
@@ -7269,6 +7322,12 @@ simple_ident:
if (spc && (spv = spc->find_variable(&$1)))
{
/* We're compiling a stored procedure and found a variable */
+ if (! lex->parsing_options.allows_variable)
+ {
+ my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
+ YYABORT;
+ }
+
Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, spv->type,
lex->tok_start_prev -
@@ -7278,7 +7337,6 @@ simple_ident:
splocal->m_sp= lex->sphead;
#endif
$$ = (Item*) splocal;
- lex->variables_used= 1;
lex->safe_to_cache_query=0;
}
else
@@ -9126,6 +9184,24 @@ view_list:
;
view_select:
+ {
+ LEX *lex= Lex;
+ lex->parsing_options.allows_variable= FALSE;
+ lex->parsing_options.allows_select_into= FALSE;
+ lex->parsing_options.allows_select_procedure= FALSE;
+ lex->parsing_options.allows_derived= FALSE;
+ }
+ view_select_aux
+ {
+ LEX *lex= Lex;
+ lex->parsing_options.allows_variable= TRUE;
+ lex->parsing_options.allows_select_into= TRUE;
+ lex->parsing_options.allows_select_procedure= TRUE;
+ lex->parsing_options.allows_derived= TRUE;
+ }
+ ;
+
+view_select_aux:
SELECT_SYM remember_name select_init2
{
THD *thd=YYTHD;
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index a2fe2ab88f1..77e7707592d 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -186,7 +186,7 @@ terribly wrong...\n");
#if defined(__alpha__) && defined(__GNUC__)
uchar** new_fp = find_prev_fp(pc, fp);
- if (frame_count == SIGRETURN_FRAME_COUNT - 1)
+ if (frame_count == sigreturn_frame_count - 1)
{
new_fp += 90;
}
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index c822d10af46..d03d88ee051 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -150,7 +150,7 @@ uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs)
int pos;
const char *j;
DBUG_ENTER("find_type2");
- DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, typelib));
+ DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, (long) typelib));
if (!typelib->count)
{
diff --git a/sql/table.cc b/sql/table.cc
index 9aecf28ab8c..1305ed9cc24 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -88,7 +88,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
MEM_ROOT **root_ptr, *old_root;
TABLE_SHARE *share;
DBUG_ENTER("openfrm");
- DBUG_PRINT("enter",("name: '%s' form: 0x%lx",name,outparam));
+ DBUG_PRINT("enter",("name: '%s' form: 0x%lx", name, (long) outparam));
error= 1;
disk_buff= NULL;
@@ -730,6 +730,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (key_part->fieldnr)
{ // Should always be true !
Field *field=key_part->field=outparam->field[key_part->fieldnr-1];
+ key_part->type= field->key_type();
if (field->null_ptr)
{
key_part->null_offset=(uint) ((byte*) field->null_ptr -
@@ -834,7 +835,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
as we need to test for NULL = NULL.
*/
if (field->real_maybe_null())
- key_part->key_part_flag|= HA_PART_KEY_SEG;
+ key_part->key_part_flag|= HA_NULL_PART;
}
else
{ // Error: shorten key
@@ -2458,7 +2459,18 @@ bool st_table_list::prepare_view_securety_context(THD *thd)
}
else
{
- my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str);
+ if (thd->security_ctx->master_access & SUPER_ACL)
+ {
+ my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str);
+
+ }
+ else
+ {
+ my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
+ thd->security_ctx->priv_user,
+ thd->security_ctx->priv_host,
+ (thd->password ? ER(ER_YES) : ER(ER_NO)));
+ }
DBUG_RETURN(TRUE);
}
}
diff --git a/sql/time.cc b/sql/time.cc
index 5069031081d..6c68d610207 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -229,14 +229,11 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, my_bool *in_dst_time_gap)
*in_dst_time_gap= 0;
- if (t->year < TIMESTAMP_MAX_YEAR && t->year > TIMESTAMP_MIN_YEAR ||
- t->year == TIMESTAMP_MAX_YEAR && t->month == 1 && t->day == 1 ||
- t->year == TIMESTAMP_MIN_YEAR && t->month == 12 && t->day == 31)
+ timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
+ if (timestamp)
{
thd->time_zone_used= 1;
- timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap);
- if (timestamp >= TIMESTAMP_MIN_VALUE && timestamp <= TIMESTAMP_MAX_VALUE)
- return timestamp;
+ return timestamp;
}
/* If we are here we have range error. */
@@ -254,9 +251,9 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, my_bool *in_dst_time_gap)
bool
str_to_time_with_warn(const char *str, uint length, TIME *l_time)
{
- int was_cut;
- bool ret_val= str_to_time(str, length, l_time, &was_cut);
- if (was_cut)
+ int warning;
+ bool ret_val= str_to_time(str, length, l_time, &warning);
+ if (ret_val || warning)
make_truncated_value_warning(current_thd, str, length,
MYSQL_TIMESTAMP_TIME, NullS);
return ret_val;
diff --git a/sql/tztime.cc b/sql/tztime.cc
index d12aef47b40..4becf4a9fcc 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -886,8 +886,14 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp,
my_time_t local_t;
uint saved_seconds;
uint i;
+ int shift= 0;
+
DBUG_ENTER("TIME_to_gmt_sec");
+ if (!validate_timestamp_range(t))
+ DBUG_RETURN(0);
+
+
/* We need this for correct leap seconds handling */
if (t->second < SECS_PER_MIN)
saved_seconds= 0;
@@ -895,11 +901,29 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp,
saved_seconds= t->second;
/*
- NOTE If we want to convert full my_time_t range without MySQL
- restrictions we should catch overflow here somehow.
+ NOTE: to convert full my_time_t range we do a shift of the
+ boundary dates here to avoid overflow of my_time_t.
+ We use alike approach in my_system_gmt_sec().
+
+ However in that function we also have to take into account
+ overflow near 0 on some platforms. That's because my_system_gmt_sec
+ uses localtime_r(), which doesn't work with negative values correctly
+ on platforms with unsigned time_t (QNX). Here we don't use localtime()
+ => we negative values of local_t are ok.
*/
- local_t= sec_since_epoch(t->year, t->month, t->day,
+ if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4)
+ {
+ /*
+ We will pass (t->day - shift) to sec_since_epoch(), and
+ want this value to be a positive number, so we shift
+ only dates > 4.01.2038 (to avoid owerflow).
+ */
+ shift= 2;
+ }
+
+
+ local_t= sec_since_epoch(t->year, t->month, (t->day - shift),
t->hour, t->minute,
saved_seconds ? 0 : t->second);
@@ -918,6 +942,21 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp,
/* binary search for our range */
i= find_time_range(local_t, sp->revts, sp->revcnt);
+ /*
+ As there are no offset switches at the end of TIMESTAMP range,
+ we could simply check for overflow here (and don't need to bother
+ about DST gaps etc)
+ */
+ if (shift)
+ {
+ if (local_t > (my_time_t) (TIMESTAMP_MAX_VALUE - shift*86400L +
+ sp->revtis[i].rt_offset - saved_seconds))
+ {
+ DBUG_RETURN(0); /* my_time_t overflow */
+ }
+ local_t+= shift*86400L;
+ }
+
if (sp->revtis[i].rt_type)
{
/*
@@ -927,10 +966,16 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp,
beginning of the gap.
*/
*in_dst_time_gap= 1;
- DBUG_RETURN(sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds);
+ local_t= sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds;
}
else
- DBUG_RETURN(local_t - sp->revtis[i].rt_offset + saved_seconds);
+ local_t= local_t - sp->revtis[i].rt_offset + saved_seconds;
+
+ /* check for TIMESTAMP_MAX_VALUE was already done above */
+ if (local_t < TIMESTAMP_MIN_VALUE)
+ local_t= 0;
+
+ DBUG_RETURN(local_t);
}
@@ -1296,9 +1341,24 @@ Time_zone_offset::Time_zone_offset(long tz_offset_arg):
my_time_t
Time_zone_offset::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const
{
- return sec_since_epoch(t->year, t->month, t->day,
- t->hour, t->minute, t->second) -
- offset;
+ my_time_t local_t;
+
+ /*
+ Check timestamp range.we have to do this as calling function relies on
+ us to make all validation checks here.
+ */
+ if (!validate_timestamp_range(t))
+ return 0;
+
+ local_t= sec_since_epoch(t->year, t->month, t->day,
+ t->hour, t->minute, t->second) -
+ offset;
+
+ if (local_t >= TIMESTAMP_MIN_VALUE && local_t <= TIMESTAMP_MAX_VALUE)
+ return local_t;
+
+ /* range error*/
+ return 0;
}
@@ -1669,9 +1729,9 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
tz_leapcnt++;
DBUG_PRINT("info",
- ("time_zone_leap_second table: tz_leapcnt=%u tt_time=%lld offset=%ld",
- tz_leapcnt, (longlong)tz_lsis[tz_leapcnt-1].ls_trans,
- tz_lsis[tz_leapcnt-1].ls_corr));
+ ("time_zone_leap_second table: tz_leapcnt: %u tt_time: %lu offset=%ld",
+ tz_leapcnt, (ulong) tz_lsis[tz_leapcnt-1].ls_trans,
+ tz_lsis[tz_leapcnt-1].ls_corr));
res= table->file->index_next(table->record[0]);
}
@@ -1981,8 +2041,8 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
tz_info->timecnt++;
DBUG_PRINT("info",
- ("time_zone_transition table: tz_id=%u tt_time=%lld tt_id=%u",
- tzid, (longlong)ttime, ttid));
+ ("time_zone_transition table: tz_id: %u tt_time: %lu tt_id: %u",
+ tzid, (ulong) ttime, ttid));
res= table->file->index_next_same(table->record[0],
(byte*)table->field[0]->ptr, 4);
diff --git a/sql/uniques.cc b/sql/uniques.cc
index ad074f8b2b0..c7bdbdeb207 100644
--- a/sql/uniques.cc
+++ b/sql/uniques.cc
@@ -55,18 +55,19 @@ int unique_write_to_ptrs(gptr key, element_count count, Unique *unique)
}
Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg,
- uint size_arg, ulong max_in_memory_size_arg)
+ uint size_arg, ulonglong max_in_memory_size_arg)
:max_in_memory_size(max_in_memory_size_arg), size(size_arg), elements(0)
{
my_b_clear(&file);
- init_tree(&tree, max_in_memory_size / 16, 0, size, comp_func, 0, NULL,
- comp_func_fixed_arg);
+ init_tree(&tree, (ulong) (max_in_memory_size / 16), 0, size, comp_func, 0,
+ NULL, comp_func_fixed_arg);
/* If the following fail's the next add will also fail */
my_init_dynamic_array(&file_ptrs, sizeof(BUFFPEK), 16, 16);
/*
If you change the following, change it in get_max_elements function, too.
*/
- max_elements= max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size);
+ max_elements= (ulong) (max_in_memory_size /
+ ALIGN_SIZE(sizeof(TREE_ELEMENT)+size));
VOID(open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE,
MYF(MY_WME)));
}
@@ -260,15 +261,15 @@ static double get_merge_many_buffs_cost(uint *buffer,
*/
double Unique::get_use_cost(uint *buffer, uint nkeys, uint key_size,
- ulong max_in_memory_size)
+ ulonglong max_in_memory_size)
{
ulong max_elements_in_tree;
ulong last_tree_elems;
int n_full_trees; /* number of trees in unique - 1 */
double result;
- max_elements_in_tree=
- max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size);
+ max_elements_in_tree= ((ulong) max_in_memory_size /
+ ALIGN_SIZE(sizeof(TREE_ELEMENT)+key_size));
n_full_trees= nkeys / max_elements_in_tree;
last_tree_elems= nkeys % max_elements_in_tree;
@@ -386,9 +387,11 @@ C_MODE_END
/*
DESCRIPTION
+
Function is very similar to merge_buffers, but instead of writing sorted
unique keys to the output file, it invokes walk_action for each key.
This saves I/O if you need to pass through all unique keys only once.
+
SYNOPSIS
merge_walk()
All params are 'IN' (but see comment for begin, end):
@@ -416,7 +419,7 @@ C_MODE_END
<> 0 error
*/
-static bool merge_walk(uchar *merge_buffer, uint merge_buffer_size,
+static bool merge_walk(uchar *merge_buffer, ulong merge_buffer_size,
uint key_length, BUFFPEK *begin, BUFFPEK *end,
tree_walk_action walk_action, void *walk_action_arg,
qsort_cmp2 compare, void *compare_arg,
@@ -425,14 +428,15 @@ static bool merge_walk(uchar *merge_buffer, uint merge_buffer_size,
BUFFPEK_COMPARE_CONTEXT compare_context = { compare, compare_arg };
QUEUE queue;
if (end <= begin ||
- merge_buffer_size < key_length * (end - begin + 1) ||
- init_queue(&queue, end - begin, offsetof(BUFFPEK, key), 0,
+ merge_buffer_size < (ulong) (key_length * (end - begin + 1)) ||
+ init_queue(&queue, (uint) (end - begin), offsetof(BUFFPEK, key), 0,
buffpek_compare, &compare_context))
return 1;
/* we need space for one key when a piece of merge buffer is re-read */
merge_buffer_size-= key_length;
uchar *save_key_buff= merge_buffer + merge_buffer_size;
- uint max_key_count_per_piece= merge_buffer_size/(end-begin)/key_length;
+ uint max_key_count_per_piece= (uint) (merge_buffer_size/(end-begin) /
+ key_length);
/* if piece_size is aligned reuse_freed_buffer will always hit */
uint piece_size= max_key_count_per_piece * key_length;
uint bytes_read; /* to hold return value of read_to_buffer */
@@ -548,6 +552,9 @@ end:
bool Unique::walk(tree_walk_action action, void *walk_action_arg)
{
+ int res;
+ uchar *merge_buffer;
+
if (elements == 0) /* the whole tree is in memory */
return tree_walk(&tree, action, walk_action_arg, left_root_right);
@@ -556,15 +563,14 @@ bool Unique::walk(tree_walk_action action, void *walk_action_arg)
return 1;
if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0))
return 1;
- uchar *merge_buffer= (uchar *) my_malloc(max_in_memory_size, MYF(0));
- if (merge_buffer == 0)
+ if (!(merge_buffer= (uchar *) my_malloc((ulong) max_in_memory_size, MYF(0))))
return 1;
- int res= merge_walk(merge_buffer, max_in_memory_size, size,
- (BUFFPEK *) file_ptrs.buffer,
- (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
- action, walk_action_arg,
- tree.compare, tree.custom_arg, &file);
- x_free(merge_buffer);
+ res= merge_walk(merge_buffer, (ulong) max_in_memory_size, size,
+ (BUFFPEK *) file_ptrs.buffer,
+ (BUFFPEK *) file_ptrs.buffer + file_ptrs.elements,
+ action, walk_action_arg,
+ tree.compare, tree.custom_arg, &file);
+ my_free((char*) merge_buffer, MYF(0));
return res;
}
@@ -615,7 +621,7 @@ bool Unique::get(TABLE *table)
sort_param.sort_form=table;
sort_param.rec_length= sort_param.sort_length= sort_param.ref_length=
size;
- sort_param.keys= max_in_memory_size / sort_param.sort_length;
+ sort_param.keys= (uint) (max_in_memory_size / sort_param.sort_length);
sort_param.not_killable=1;
if (!(sort_buffer=(uchar*) my_malloc((sort_param.keys+1) *
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 768a288ca19..8568b09e498 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -394,16 +394,16 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
pos[6]=pos[7]=0; // For the future
pos+=8;
key_parts+=key->key_parts;
- DBUG_PRINT("loop",("flags: %d key_parts: %d at 0x%lx",
- key->flags,key->key_parts,
- key->key_part));
+ DBUG_PRINT("loop", ("flags: %d key_parts: %d at 0x%lx",
+ key->flags, key->key_parts,
+ (long) key->key_part));
for (key_part=key->key_part,key_part_end=key_part+key->key_parts ;
key_part != key_part_end ;
key_part++)
{
uint offset;
- DBUG_PRINT("loop",("field: %d startpos: %lu length: %ld",
+ DBUG_PRINT("loop",("field: %d startpos: %lu length: %d",
key_part->fieldnr, key_part->offset + data_offset,
key_part->length));
int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 0bd5a1fda76..3e8b05580f6 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -211,9 +211,10 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
/* This function is used for all conversion functions */
-static void my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)),
+static uint my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)),
char *str __attribute__((unused)))
{
+ return 0;
}
static uint my_case_bin(CHARSET_INFO *cs __attribute__((unused)),
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 394111be3bc..3ef245015d7 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -21,40 +21,44 @@
#ifdef USE_MB
-void my_caseup_str_mb(CHARSET_INFO * cs, char *str)
+uint my_caseup_str_mb(CHARSET_INFO * cs, char *str)
{
register uint32 l;
- register uchar *map=cs->to_upper;
+ register uchar *map= cs->to_upper;
+ char *str_orig= str;
while (*str)
{
/* Pointing after the '\0' is safe here. */
- if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen)))
- str+=l;
+ if ((l= my_ismbchar(cs, str, str + cs->mbmaxlen)))
+ str+= l;
else
{
- *str=(char) map[(uchar)*str];
+ *str= (char) map[(uchar)*str];
str++;
}
}
+ return str - str_orig;
}
-void my_casedn_str_mb(CHARSET_INFO * cs, char *str)
+uint my_casedn_str_mb(CHARSET_INFO * cs, char *str)
{
register uint32 l;
- register uchar *map=cs->to_lower;
+ register uchar *map= cs->to_lower;
+ char *str_orig= str;
while (*str)
{
/* Pointing after the '\0' is safe here. */
- if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen)))
- str+=l;
+ if ((l= my_ismbchar(cs, str, str + cs->mbmaxlen)))
+ str+= l;
else
{
- *str=(char) map[(uchar)*str];
+ *str= (char) map[(uchar)*str];
str++;
}
}
+ return str - str_orig;
}
uint my_caseup_mb(CHARSET_INFO * cs, char *src, uint srclen,
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index e40a1948dcf..fc9cbfc9d21 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -188,20 +188,26 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
}
-void my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
+uint my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
{
- register uchar *map=cs->to_upper;
- while ((*str = (char) map[(uchar) *str]) != 0)
+ register uchar *map= cs->to_upper;
+ char *str_orig= str;
+ while ((*str= (char) map[(uchar) *str]) != 0)
str++;
+ return str - str_orig;
}
-void my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
+
+uint my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
{
- register uchar *map=cs->to_lower;
- while ((*str = (char) map[(uchar)*str]) != 0)
+ register uchar *map= cs->to_lower;
+ char *str_orig= str;
+ while ((*str= (char) map[(uchar) *str]) != 0)
str++;
+ return str - str_orig;
}
+
uint my_caseup_8bit(CHARSET_INFO * cs, char *src, uint srclen,
char *dst __attribute__((unused)),
uint dstlen __attribute__((unused)))
@@ -1497,7 +1503,7 @@ my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)),
else
{
*error= 0;
- return (ulonglong) (longlong) (long) -ul;
+ return (ulonglong) (longlong) -(long) ul;
}
}
else
@@ -1648,7 +1654,7 @@ ret_sign:
return (ulonglong) LONGLONG_MIN;
}
*error= 0;
- return (ulonglong) -ull;
+ return (ulonglong) -(longlong) ull;
}
else
{
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 4a60220f73e..3c69a314b45 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -159,13 +159,13 @@ static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, uint slen,
}
-static void my_caseup_str_ucs2(CHARSET_INFO * cs __attribute__((unused)),
+static uint my_caseup_str_ucs2(CHARSET_INFO * cs __attribute__((unused)),
char * s __attribute__((unused)))
{
+ return 0;
}
-
static uint my_casedn_ucs2(CHARSET_INFO *cs, char *src, uint srclen,
char *dst __attribute__((unused)),
uint dstlen __attribute__((unused)))
@@ -188,9 +188,11 @@ static uint my_casedn_ucs2(CHARSET_INFO *cs, char *src, uint srclen,
return srclen;
}
-static void my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+
+static uint my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)),
char * s __attribute__((unused)))
{
+ return 0;
}
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index ae2c04fb068..a21fe4961ec 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -2045,6 +2045,52 @@ static int my_utf8_uni(CHARSET_INFO *cs __attribute__((unused)),
return MY_CS_ILSEQ;
}
+
+/*
+ The same as above, but without range check
+ for example, for a null-terminated string
+*/
+static int my_utf8_uni_no_range(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t * pwc, const uchar *s)
+{
+ unsigned char c;
+
+ c= s[0];
+ if (c < 0x80)
+ {
+ *pwc = c;
+ return 1;
+ }
+
+ if (c < 0xc2)
+ return MY_CS_ILSEQ;
+
+ if (c < 0xe0)
+ {
+ if (!((s[1] ^ 0x80) < 0x40))
+ return MY_CS_ILSEQ;
+
+ *pwc = ((my_wc_t) (c & 0x1f) << 6) | (my_wc_t) (s[1] ^ 0x80);
+ return 2;
+ }
+
+ if (c < 0xf0)
+ {
+ if (!((s[1] ^ 0x80) < 0x40 &&
+ (s[2] ^ 0x80) < 0x40 &&
+ (c >= 0xe1 || s[1] >= 0xa0)))
+ return MY_CS_ILSEQ;
+
+ *pwc= ((my_wc_t) (c & 0x0f) << 12) |
+ ((my_wc_t) (s[1] ^ 0x80) << 6) |
+ (my_wc_t) (s[2] ^ 0x80);
+
+ return 3;
+ }
+ return MY_CS_ILSEQ;
+}
+
+
static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) ,
my_wc_t wc, uchar *r, uchar *e)
{
@@ -2091,6 +2137,34 @@ static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) ,
}
+/*
+ The same as above, but without range check.
+*/
+static int my_uni_utf8_no_range(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, uchar *r)
+{
+ int count;
+
+ if (wc < 0x80)
+ count= 1;
+ else if (wc < 0x800)
+ count= 2;
+ else if (wc < 0x10000)
+ count= 3;
+ else
+ return MY_CS_ILUNI;
+
+ switch (count)
+ {
+ /* Fall through all cases!!! */
+ case 3: r[2]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x800;
+ case 2: r[1]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0xc0;
+ case 1: r[0]= (uchar) wc;
+ }
+ return count;
+}
+
+
static uint my_caseup_utf8(CHARSET_INFO *cs, char *src, uint srclen,
char *dst, uint dstlen)
{
@@ -2141,10 +2215,26 @@ static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen,
}
-static void my_caseup_str_utf8(CHARSET_INFO * cs, char * s)
+static uint my_caseup_str_utf8(CHARSET_INFO *cs, char *src)
{
- uint len= (uint) strlen(s);
- my_caseup_utf8(cs, s, len, s, len);
+ my_wc_t wc;
+ int srcres, dstres;
+ char *dst= src, *dst0= src;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ DBUG_ASSERT(cs->caseup_multiply == 1);
+
+ while (*src &&
+ (srcres= my_utf8_uni_no_range(cs, &wc, (uchar *) src)) > 0)
+ {
+ int plane= (wc>>8) & 0xFF;
+ wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
+ if ((dstres= my_uni_utf8_no_range(cs, wc, (uchar*) dst)) <= 0)
+ break;
+ src+= srcres;
+ dst+= dstres;
+ }
+ *dst= '\0';
+ return (uint) (dst - dst0);
}
@@ -2170,10 +2260,43 @@ static uint my_casedn_utf8(CHARSET_INFO *cs, char *src, uint srclen,
return (uint) (dst - dst0);
}
-static void my_casedn_str_utf8(CHARSET_INFO *cs, char * s)
+
+static uint my_casedn_str_utf8(CHARSET_INFO *cs, char *src)
{
- uint len= (uint) strlen(s);
- my_casedn_utf8(cs, s, len, s, len);
+ my_wc_t wc;
+ int srcres, dstres;
+ char *dst= src, *dst0= src;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ DBUG_ASSERT(cs->casedn_multiply == 1);
+
+ while (*src &&
+ (srcres= my_utf8_uni_no_range(cs, &wc, (uchar *) src)) > 0)
+ {
+ int plane= (wc>>8) & 0xFF;
+ wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc;
+ if ((dstres= my_uni_utf8_no_range(cs, wc, (uchar*) dst)) <= 0)
+ break;
+ src+= srcres;
+ dst+= dstres;
+ }
+
+ /*
+ In rare cases lower string can be shorter than
+ the original string, for example:
+
+ "U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE"
+ (which is 0xC4B0 in utf8, i.e. two bytes)
+
+ is converted into
+
+ "U+0069 LATIN SMALL LETTER I"
+ (which is 0x69 in utf8, i.e. one byte)
+
+ So, we need to put '\0' terminator after converting.
+ */
+
+ *dst= '\0';
+ return (uint) (dst - dst0);
}
diff --git a/strings/decimal.c b/strings/decimal.c
index 5a0bc0968b6..6b7a2266194 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -1036,7 +1036,7 @@ int decimal2ulonglong(decimal_t *from, ulonglong *to)
x=x*DIG_BASE + *buf++;
if (unlikely(y > ((ulonglong) ULONGLONG_MAX/DIG_BASE) || x < y))
{
- *to=y;
+ *to=ULONGLONG_MAX;
return E_DEC_OVERFLOW;
}
}
@@ -1348,7 +1348,7 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale)
}
from+=i;
*buf=x ^ mask;
- if (((uint32)*buf) >= powers10[intg0x+1])
+ if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1])
goto err;
if (buf > to->buf || *buf != 0)
buf++;
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index eefc4f55d35..6000773144c 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -194,6 +194,8 @@ necessary to develop MySQL client applications.
%package shared
Summary: MySQL - Shared libraries
Group: Applications/Databases
+Provides: mysql-shared
+Obsoletes: mysql-shared
%description shared
This package contains the shared libraries (*.so*) which certain
@@ -342,7 +344,10 @@ then
cp -fp config.log "$MYSQL_MAXCONFLOG_DEST"
fi
-make -i test-force-pl || true
+( cd mysql-test
+ perl ./mysql-test-run.pl --force --report-features
+ perl ./mysql-test-run.pl --force --ps-protocol
+ true )
# Save mysqld-max
./libtool --mode=execute cp sql/mysqld sql/mysqld-max
@@ -401,7 +406,10 @@ then
cp -fp config.log "$MYSQL_CONFLOG_DEST"
fi
-make -i test-force-pl || true
+( cd mysql-test
+ perl ./mysql-test-run.pl --force --report-features
+ perl ./mysql-test-run.pl --force --ps-protocol
+ true )
%install
RBR=$RPM_BUILD_ROOT
@@ -745,6 +753,17 @@ fi
# itself - note that they must be ordered by date (important when
# merging BK trees)
%changelog
+* Thu Nov 16 2006 Joerg Bruehe <joerg@mysql.com>
+
+- Explicitly note that the "MySQL-shared" RPMs (as built by MySQL AB)
+ replace "mysql-shared" (as distributed by SuSE) to allow easy upgrading
+ (bug#22081).
+
+* Wed Nov 15 2006 Joerg Bruehe <joerg@mysql.com>
+
+- Switch from "make test*" to explicit calls of the test suite,
+ so that "report features" can be used.
+
* Mon Jul 10 2006 Joerg Bruehe <joerg@mysql.com>
- Fix a typing error in the "make" target for the Perl script to run the tests.
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index d3f39296445..c596a589d55 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -121,8 +121,9 @@ static void client_disconnect();
void die(const char *file, int line, const char *expr)
{
+ fflush(stdout);
fprintf(stderr, "%s:%d: check failed: '%s'\n", file, line, expr);
- fflush(NULL);
+ fflush(stderr);
abort();
}
@@ -7496,10 +7497,22 @@ static void test_explain_bug()
MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
0, 0, "", 3, 0);
- verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
- mysql_get_server_version(mysql) <= 50000 ?
- MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
- 0, 0, "", 64, 0);
+ if ( mysql_get_server_version(mysql) >= 50027 )
+ {
+ /* The patch for bug#23037 changes column type of DEAULT to blob */
+ verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
+ MYSQL_TYPE_BLOB, 0, 0, "", 0, 0);
+ }
+ else
+ {
+ verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
+ mysql_get_server_version(mysql) >= 50027 ?
+ MYSQL_TYPE_BLOB :
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "",
+ mysql_get_server_version(mysql) >= 50027 ? 0 :64, 0);
+ }
verify_prepare_field(result, 5, "Extra", "EXTRA",
mysql_get_server_version(mysql) <= 50000 ?
@@ -11977,6 +11990,19 @@ static void test_cursors_with_union()
fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
}
+
+static void test_cursors_with_procedure()
+{
+ const char *queries[]=
+ {
+ "SELECT * FROM t1 procedure analyse()"
+ };
+ myheader("test_cursors_with_procedure");
+ fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH);
+ fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
+}
+
+
/*
Altough mysql_create_db(), mysql_rm_db() are deprecated since 4.0 they
should not crash server and should not hang in case of errors.
@@ -13660,7 +13686,8 @@ static void test_bug11172()
hired.year, hired.month, hired.day);
}
DIE_UNLESS(rc == MYSQL_NO_DATA);
- mysql_stmt_free_result(stmt) || mysql_stmt_reset(stmt);
+ if (!mysql_stmt_free_result(stmt))
+ mysql_stmt_reset(stmt);
}
mysql_stmt_close(stmt);
mysql_rollback(mysql);
@@ -14454,6 +14481,7 @@ static void test_bug11718()
printf("return type: %s", (res->fields[0].type == MYSQL_TYPE_DATE)?"DATE":
"not DATE");
DIE_UNLESS(res->fields[0].type == MYSQL_TYPE_DATE);
+ mysql_free_result(res);
rc= mysql_query(mysql, "drop table t1, t2");
myquery(rc);
}
@@ -14801,6 +14829,8 @@ static void test_opt_reconnect()
}
+#ifndef EMBEDDED_LIBRARY
+
static void test_bug12744()
{
MYSQL_STMT *prep_stmt = NULL;
@@ -14832,6 +14862,8 @@ static void test_bug12744()
client_connect(0);
}
+#endif /* EMBEDDED_LIBRARY */
+
/* Bug #16143: mysql_stmt_sqlstate returns an empty string instead of '00000' */
static void test_bug16143()
@@ -14902,6 +14934,8 @@ static void test_bug15613()
DIE_UNLESS(field[4].length == 255);
DIE_UNLESS(field[5].length == 255);
DIE_UNLESS(field[6].length == 255);
+ mysql_free_result(metadata);
+ mysql_stmt_free_result(stmt);
/* III. Cleanup */
rc= mysql_query(mysql, "drop table t1");
@@ -15078,6 +15112,9 @@ static void test_bug14169()
if (!opt_silent)
printf("GROUP_CONCAT() result type %i", field[1].type);
DIE_UNLESS(field[1].type == MYSQL_TYPE_BLOB);
+ mysql_free_result(res);
+ mysql_stmt_free_result(stmt);
+ mysql_stmt_close(stmt);
rc= mysql_query(mysql, "drop table t1");
myquery(rc);
@@ -15142,7 +15179,7 @@ static void test_bug15752()
MYSQL mysql_local;
int rc, i;
const int ITERATION_COUNT= 100;
- char *query= "CALL p1()";
+ const char *query= "CALL p1()";
myheader("test_bug15752");
@@ -15276,6 +15313,151 @@ static void test_bug21726()
/*
+ BUG#23383: mysql_affected_rows() returns different values than
+ mysql_stmt_affected_rows()
+
+ Test that both mysql_affected_rows() and mysql_stmt_affected_rows()
+ return -1 on error, 0 when no rows were affected, and (positive) row
+ count when some rows were affected.
+*/
+static void test_bug23383()
+{
+ const char *insert_query= "INSERT INTO t1 VALUES (1), (2)";
+ const char *update_query= "UPDATE t1 SET i= 4 WHERE i = 3";
+ MYSQL_STMT *stmt;
+ my_ulonglong row_count;
+ int rc;
+
+ DBUG_ENTER("test_bug23383");
+ myheader("test_bug23383");
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (i INT UNIQUE)");
+ myquery(rc);
+
+ rc= mysql_query(mysql, insert_query);
+ myquery(rc);
+ row_count= mysql_affected_rows(mysql);
+ DIE_UNLESS(row_count == 2);
+
+ rc= mysql_query(mysql, insert_query);
+ DIE_UNLESS(rc != 0);
+ row_count= mysql_affected_rows(mysql);
+ DIE_UNLESS(row_count == (my_ulonglong)-1);
+
+ rc= mysql_query(mysql, update_query);
+ myquery(rc);
+ row_count= mysql_affected_rows(mysql);
+ DIE_UNLESS(row_count == 0);
+
+ rc= mysql_query(mysql, "DELETE FROM t1");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+ DIE_UNLESS(stmt != 0);
+
+ rc= mysql_stmt_prepare(stmt, insert_query, strlen(insert_query));
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ row_count= mysql_stmt_affected_rows(stmt);
+ DIE_UNLESS(row_count == 2);
+
+ rc= mysql_stmt_execute(stmt);
+ DIE_UNLESS(rc != 0);
+ row_count= mysql_stmt_affected_rows(stmt);
+ DIE_UNLESS(row_count == (my_ulonglong)-1);
+
+ rc= mysql_stmt_prepare(stmt, update_query, strlen(update_query));
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ row_count= mysql_stmt_affected_rows(stmt);
+ DIE_UNLESS(row_count == 0);
+
+ rc= mysql_stmt_close(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ BUG#21635: MYSQL_FIELD struct's member strings seem to misbehave for
+ expression cols
+
+ Check that for MIN(), MAX(), COUNT() only MYSQL_FIELD::name is set
+ to either expression or its alias, and db, org_table, table,
+ org_name fields are empty strings.
+*/
+static void test_bug21635()
+{
+ const char *expr[]=
+ {
+ "MIN(i)", "MIN(i)",
+ "MIN(i) AS A1", "A1",
+ "MAX(i)", "MAX(i)",
+ "MAX(i) AS A2", "A2",
+ "COUNT(i)", "COUNT(i)",
+ "COUNT(i) AS A3", "A3",
+ };
+ char query[MAX_TEST_QUERY_LENGTH];
+ char *query_end;
+ MYSQL_RES *result;
+ MYSQL_FIELD *field;
+ unsigned int field_count, i;
+ int rc;
+
+ DBUG_ENTER("test_bug21635");
+ myheader("test_bug21635");
+
+ query_end= strxmov(query, "SELECT ", NullS);
+ for (i= 0; i < sizeof(expr) / sizeof(*expr) / 2; ++i)
+ query_end= strxmov(query_end, expr[i * 2], ", ", NullS);
+ query_end= strxmov(query_end - 2, " FROM t1 GROUP BY i", NullS);
+ DIE_UNLESS(query_end - query < MAX_TEST_QUERY_LENGTH);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ myquery(rc);
+ rc= mysql_query(mysql, "CREATE TABLE t1 (i INT)");
+ myquery(rc);
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
+ myquery(rc);
+
+ rc= mysql_real_query(mysql, query, query_end - query);
+ myquery(rc);
+
+ result= mysql_use_result(mysql);
+ DIE_UNLESS(result);
+
+ field_count= mysql_field_count(mysql);
+ for (i= 0; i < field_count; ++i)
+ {
+ field= mysql_fetch_field_direct(result, i);
+ printf("%s -> %s ... ", expr[i * 2], field->name);
+ fflush(stdout);
+ DIE_UNLESS(field->db[0] == 0 && field->org_table[0] == 0 &&
+ field->table[0] == 0 && field->org_name[0] == 0);
+ DIE_UNLESS(strcmp(field->name, expr[i * 2 + 1]) == 0);
+ puts("OK");
+ }
+
+ mysql_free_result(result);
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -15501,6 +15683,7 @@ static struct my_tests_st my_tests[]= {
{ "test_view_insert_fields", test_view_insert_fields },
{ "test_basic_cursors", test_basic_cursors },
{ "test_cursors_with_union", test_cursors_with_union },
+ { "test_cursors_with_procedure", test_cursors_with_procedure },
{ "test_truncation", test_truncation },
{ "test_truncation_option", test_truncation_option },
{ "test_client_character_set", test_client_character_set },
@@ -15550,6 +15733,8 @@ static struct my_tests_st my_tests[]= {
{ "test_bug15752", test_bug15752 },
{ "test_bug21206", test_bug21206 },
{ "test_bug21726", test_bug21726 },
+ { "test_bug23383", test_bug23383 },
+ { "test_bug21635", test_bug21635 },
{ 0, 0 }
};
diff --git a/vio/viosocket.c b/vio/viosocket.c
index 3ce1c994d79..cae0cf70db4 100644
--- a/vio/viosocket.c
+++ b/vio/viosocket.c
@@ -33,7 +33,7 @@ int vio_read(Vio * vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_read");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size));
/* Ensure nobody uses vio_read_buff and vio_read simultaneously */
DBUG_ASSERT(vio->read_end == vio->read_pos);
@@ -64,7 +64,7 @@ int vio_read_buff(Vio *vio, gptr buf, int size)
int rc;
#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
DBUG_ENTER("vio_read_buff");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size));
if (vio->read_pos < vio->read_end)
{
@@ -102,7 +102,7 @@ int vio_write(Vio * vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_write");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size));
#ifdef __WIN__
r = send(vio->sd, buf, size,0);
#else
@@ -227,7 +227,7 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive)
int r=0;
uint opt = 0;
DBUG_ENTER("vio_keepalive");
- DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int)
+ DBUG_PRINT("enter", ("sd: %d set_keep_alive: %d", vio->sd, (int)
set_keep_alive));
if (vio->type != VIO_TYPE_NAMEDPIPE)
{
@@ -411,7 +411,7 @@ int vio_read_pipe(Vio * vio, gptr buf, int size)
{
DWORD length;
DBUG_ENTER("vio_read_pipe");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
DBUG_RETURN(-1);
@@ -425,7 +425,7 @@ int vio_write_pipe(Vio * vio, const gptr buf, int size)
{
DWORD length;
DBUG_ENTER("vio_write_pipe");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
DBUG_RETURN(-1);
@@ -470,7 +470,7 @@ int vio_read_shared_memory(Vio * vio, gptr buf, int size)
char *current_postion;
DBUG_ENTER("vio_read_shared_memory");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
remain_local = size;
current_postion=buf;
@@ -531,7 +531,7 @@ int vio_write_shared_memory(Vio * vio, const gptr buf, int size)
char *current_postion;
DBUG_ENTER("vio_write_shared_memory");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size));
remain = size;
current_postion = buf;
diff --git a/vio/viossl.c b/vio/viossl.c
index e869493c604..f436262a3ce 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -26,6 +26,10 @@
#ifdef HAVE_OPENSSL
#ifdef __NETWARE__
+
+/* yaSSL already uses BSD sockets */
+#ifndef HAVE_YASSL
+
/*
The default OpenSSL implementation on NetWare uses WinSock.
This code allows us to use the BSD sockets.
@@ -47,6 +51,7 @@ static int SSL_set_fd_bsd(SSL *s, int fd)
#define SSL_set_fd(A, B) SSL_set_fd_bsd((A), (B))
+#endif /* HAVE_YASSL */
#endif /* __NETWARE__ */
@@ -82,8 +87,8 @@ int vio_ssl_read(Vio *vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_read");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d, ssl_: 0x%p",
- vio->sd, buf, size, vio->ssl_arg));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d ssl: 0x%lx",
+ vio->sd, (long) buf, size, (long) vio->ssl_arg));
r= SSL_read((SSL*) vio->ssl_arg, buf, size);
#ifndef DBUG_OFF
@@ -99,7 +104,7 @@ int vio_ssl_write(Vio *vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_write");
- DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
+ DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size));
r= SSL_write((SSL*) vio->ssl_arg, buf, size);
#ifndef DBUG_OFF
@@ -128,7 +133,7 @@ int vio_ssl_close(Vio *vio)
break;
/* Fallthrough */
default: /* Shutdown failed */
- DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %s",
+ DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %d",
SSL_get_error(ssl, r)));
break;
}
@@ -146,8 +151,8 @@ int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
my_bool net_blocking;
enum enum_vio_type old_type;
DBUG_ENTER("sslaccept");
- DBUG_PRINT("enter", ("sd: %d ptr: %p, timeout: %d",
- vio->sd, ptr, timeout));
+ DBUG_PRINT("enter", ("sd: %d ptr: 0x%lx, timeout: %ld",
+ vio->sd, (long) ptr, timeout));
old_type= vio->type;
net_blocking= vio_is_blocking(vio);
@@ -163,14 +168,13 @@ int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
DBUG_RETURN(1);
}
vio->ssl_arg= (void*)ssl;
- DBUG_PRINT("info", ("ssl_: %p timeout: %ld", ssl, timeout));
+ DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
SSL_clear(ssl);
SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
SSL_set_fd(ssl, vio->sd);
- SSL_set_accept_state(ssl);
- if (SSL_do_handshake(ssl) < 1)
+ if (SSL_accept(ssl) < 1)
{
- DBUG_PRINT("error", ("SSL_do_handshake failure"));
+ DBUG_PRINT("error", ("SSL_accept failure"));
report_errors(ssl);
SSL_free(ssl);
vio->ssl_arg= 0;
@@ -222,8 +226,8 @@ int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
enum enum_vio_type old_type;
DBUG_ENTER("sslconnect");
- DBUG_PRINT("enter", ("sd: %d, ptr: %p, ctx: %p",
- vio->sd, ptr, ptr->ssl_context));
+ DBUG_PRINT("enter", ("sd: %d ptr: 0x%lx ctx: 0x%lx",
+ vio->sd, (long) ptr, (long) ptr->ssl_context));
old_type= vio->type;
net_blocking= vio_is_blocking(vio);
@@ -238,14 +242,13 @@ int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
DBUG_RETURN(1);
}
vio->ssl_arg= (void*)ssl;
- DBUG_PRINT("info", ("ssl: %p, timeout: %ld", ssl, timeout));
+ DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
SSL_clear(ssl);
SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
SSL_set_fd(ssl, vio->sd);
- SSL_set_connect_state(ssl);
- if (SSL_do_handshake(ssl) < 1)
+ if (SSL_connect(ssl) < 1)
{
- DBUG_PRINT("error", ("SSL_do_handshake failure"));
+ DBUG_PRINT("error", ("SSL_connect failure"));
report_errors(ssl);
SSL_free(ssl);
vio->ssl_arg= 0;
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 2c528e9a2fc..014ce25d754 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -79,15 +79,14 @@ static int
vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
{
DBUG_ENTER("vio_set_cert_stuff");
- DBUG_PRINT("enter", ("ctx: %p, cert_file: %s, key_file: %s",
- ctx, cert_file, key_file));
+ DBUG_PRINT("enter", ("ctx: 0x%lx cert_file: %s key_file: %s",
+ (long) ctx, cert_file, key_file));
if (cert_file)
{
if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0)
{
DBUG_PRINT("error",("unable to get certificate from '%s'\n", cert_file));
- /* FIX stderr */
- fprintf(stderr,"Error when connection to server using SSL:");
+ fprintf(stderr,"SSL error: ");
ERR_print_errors_fp(stderr);
fprintf(stderr,"Unable to get certificate from '%s'\n", cert_file);
fflush(stderr);
@@ -100,8 +99,7 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0)
{
DBUG_PRINT("error", ("unable to get private key from '%s'\n", key_file));
- /* FIX stderr */
- fprintf(stderr,"Error when connection to server using SSL:");
+ fprintf(stderr,"SSL error: ");
ERR_print_errors_fp(stderr);
fprintf(stderr,"Unable to get private key from '%s'\n", key_file);
fflush(stderr);
@@ -130,7 +128,7 @@ vio_verify_callback(int ok, X509_STORE_CTX *ctx)
X509 *err_cert;
DBUG_ENTER("vio_verify_callback");
- DBUG_PRINT("enter", ("ok: %d, ctx: %p", ok, ctx));
+ DBUG_PRINT("enter", ("ok: %d ctx: 0x%lx", ok, (long) ctx));
err_cert= X509_STORE_CTX_get_current_cert(ctx);
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
@@ -141,7 +139,7 @@ vio_verify_callback(int ok, X509_STORE_CTX *ctx)
err= X509_STORE_CTX_get_error(ctx);
depth= X509_STORE_CTX_get_error_depth(ctx);
- DBUG_PRINT("error",("verify error: %d, '%s'",err,
+ DBUG_PRINT("error",("verify error: %d '%s'",err,
X509_verify_cert_error_string(err)));
/*
Approve cert if depth is greater then "verify_depth", currently
@@ -180,11 +178,15 @@ void netware_ssl_cleanup()
/* free memory from SSL_library_init() */
EVP_cleanup();
+/* OpenSSL NetWare port specific functions */
+#ifndef HAVE_YASSL
+
/* free global X509 method */
X509_STORE_method_cleanup();
/* free the thread_hash error table */
ERR_free_state_table();
+#endif
}
@@ -248,6 +250,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
{
DBUG_PRINT("error", ("failed to set ciphers to use"));
report_errors();
+ SSL_CTX_free(ssl_fd->ssl_context);
my_free((void*)ssl_fd,MYF(0));
DBUG_RETURN(0);
}
@@ -260,6 +263,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
{
DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
report_errors();
+ SSL_CTX_free(ssl_fd->ssl_context);
my_free((void*)ssl_fd,MYF(0));
DBUG_RETURN(0);
}
@@ -269,6 +273,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
{
DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
report_errors();
+ SSL_CTX_free(ssl_fd->ssl_context);
my_free((void*)ssl_fd,MYF(0));
DBUG_RETURN(0);
}