summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2002-11-21 15:56:48 +0200
committerunknown <monty@mashka.mysql.fi>2002-11-21 15:56:48 +0200
commit33fc0d53b543032accea2476a4eed0522cead2bb (patch)
treed3df5d3fc1abf364dcbcc8eb2305a1cf62540192
parent2723dbdb5e2c60162ca464f65f68fdd13b7c9cef (diff)
parent70a17cd5a7aab52697b494cd8379fb78db15eeea (diff)
downloadmariadb-git-33fc0d53b543032accea2476a4eed0522cead2bb.tar.gz
Merge with 4.0
BitKeeper/etc/gone: auto-union BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union BitKeeper/deleted/.del-.my_sys.h.swp~f6a4a7f8dae03f18: Auto merged BitKeeper/etc/config: Auto merged acconfig.h: Auto merged acinclude.m4: Auto merged Docs/manual.texi: Auto merged client/mysqlcheck.c: Auto merged client/mysqlshow.c: Auto merged include/myisam.h: Auto merged include/violite.h: Auto merged isam/pack_isam.c: Auto merged libmysql/libmysql.c: Auto merged libmysqld/lib_sql.cc: Auto merged myisam/Makefile.am: Auto merged myisam/ft_nlq_search.c: Auto merged myisam/mi_open.c: Auto merged myisam/mi_write.c: Auto merged myisam/sort.c: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/func_test.result: Auto merged mysql-test/r/isam.result: Auto merged mysql-test/r/rpl_replicate_do.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/t/func_test.test: Auto merged mysql-test/t/myisam.test: Auto merged mysql-test/t/rpl_rotate_logs.test: Auto merged mysql-test/t/variables.test: Auto merged mysys/hash.c: Auto merged mysys/tree.c: Auto merged scripts/Makefile.am: Auto merged sql/Makefile.am: Auto merged sql/filesort.cc: Auto merged sql/gen_lex_hash.cc: Auto merged sql/ha_berkeley.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/hash_filo.h: Auto merged sql/hostname.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/item_timefunc.cc: Auto merged sql/lex.h: Auto merged sql/lock.cc: Auto merged sql/log.cc: Auto merged sql/log_event.h: Auto merged sql/mini_client.cc: Auto merged sql/opt_range.cc: Auto merged sql/opt_sum.cc: Auto merged sql/repl_failsafe.cc: Auto merged sql/set_var.h: Auto merged sql/slave.h: Auto merged sql/sql_acl.cc: Auto merged sql/sql_analyse.cc: Auto merged sql/sql_cache.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_load.cc: Auto merged sql/sql_rename.cc: Auto merged sql/sql_repl.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_udf.cc: Auto merged sql/share/czech/errmsg.txt: Auto merged sql/share/danish/errmsg.txt: Auto merged sql/share/dutch/errmsg.txt: Auto merged sql/share/english/errmsg.txt: Auto merged sql/share/estonian/errmsg.txt: Auto merged sql/share/french/errmsg.txt: Auto merged sql/share/german/errmsg.txt: Auto merged sql/share/greek/errmsg.txt: Auto merged sql/share/hungarian/errmsg.txt: Auto merged sql/share/italian/errmsg.txt: Auto merged sql/share/japanese/errmsg.txt: Auto merged sql/share/korean/errmsg.txt: Auto merged sql/share/norwegian/errmsg.txt: Auto merged sql/table.h: Auto merged sql/unireg.cc: Auto merged sql-bench/server-cfg.sh: Auto merged sql/share/norwegian-ny/errmsg.txt: Auto merged sql/share/polish/errmsg.txt: Auto merged sql/share/portuguese/errmsg.txt: Auto merged sql/share/romanian/errmsg.txt: Auto merged sql/share/russian/errmsg.txt: Auto merged sql/share/slovak/errmsg.txt: Auto merged sql/share/spanish/errmsg.txt: Auto merged sql/share/swedish/errmsg.txt: Auto merged sql/share/ukrainian/errmsg.txt: Auto merged sql/ha_myisam.cc: Merge with 4.0 Removed some commented code sql/sql_db.cc: Merge with 4.0 Optimized the logging of the drop db call a bit sql/sql_update.cc: Added comment
-rw-r--r--.bzrignore76
-rw-r--r--BUILD/Makefile.am2
-rwxr-xr-xBUILD/compile-pentium-valgrind-max13
-rwxr-xr-xBUILD/compile-solaris-sparc-forte39
-rwxr-xr-xBUILD/compile-solaris-sparc-fortre19
-rw-r--r--BitKeeper/etc/config4
-rw-r--r--BitKeeper/etc/gone37
-rw-r--r--BitKeeper/etc/logging_ok2
-rwxr-xr-xBuild-tools/Do-compile32
-rw-r--r--Docs/internals.texi1071
-rw-r--r--Docs/manual.texi140
-rw-r--r--acconfig.h2
-rw-r--r--acinclude.m4137
-rw-r--r--client/client_priv.h4
-rw-r--r--client/mysqlbinlog.cc3
-rw-r--r--client/mysqlcheck.c44
-rw-r--r--client/mysqldump.c42
-rw-r--r--client/mysqlshow.c43
-rw-r--r--client/mysqltest.c12
-rw-r--r--configure.in26
-rwxr-xr-xdbug/dbug_add_tags.pl73
-rw-r--r--extra/Makefile.am2
-rw-r--r--include/errmsg.h41
-rw-r--r--include/my_alloc.h3
-rw-r--r--include/my_base.h2
-rw-r--r--include/my_global.h36
-rw-r--r--include/my_net.h4
-rw-r--r--include/my_pthread.h2
-rw-r--r--include/my_tree.h4
-rw-r--r--include/myisam.h2
-rw-r--r--include/myisampack.h2
-rw-r--r--include/queues.h5
-rw-r--r--include/violite.h3
-rw-r--r--innobase/btr/btr0btr.c135
-rw-r--r--innobase/btr/btr0cur.c43
-rw-r--r--innobase/btr/btr0pcur.c1
-rw-r--r--innobase/buf/buf0buf.c42
-rw-r--r--innobase/buf/buf0flu.c19
-rw-r--r--innobase/configure.in2
-rw-r--r--innobase/dict/dict0crea.c18
-rw-r--r--innobase/dict/dict0dict.c231
-rw-r--r--innobase/dict/dict0load.c2
-rw-r--r--innobase/fil/fil0fil.c16
-rw-r--r--innobase/fsp/fsp0fsp.c24
-rw-r--r--innobase/ibuf/ibuf0ibuf.c3
-rw-r--r--innobase/include/btr0btr.h13
-rw-r--r--innobase/include/btr0pcur.h8
-rw-r--r--innobase/include/btr0pcur.ic18
-rw-r--r--innobase/include/buf0buf.h17
-rw-r--r--innobase/include/db0err.h3
-rw-r--r--innobase/include/dict0dict.h14
-rw-r--r--innobase/include/fil0fil.h2
-rw-r--r--innobase/include/lock0lock.h48
-rw-r--r--innobase/include/log0recv.h1
-rw-r--r--innobase/include/os0file.h3
-rw-r--r--innobase/include/os0proc.h9
-rw-r--r--innobase/include/os0thread.h7
-rw-r--r--innobase/include/page0cur.h7
-rw-r--r--innobase/include/page0page.h10
-rw-r--r--innobase/include/que0que.h8
-rw-r--r--innobase/include/read0read.h8
-rw-r--r--innobase/include/rem0rec.h12
-rw-r--r--innobase/include/rem0rec.ic18
-rw-r--r--innobase/include/row0mysql.h43
-rw-r--r--innobase/include/srv0srv.h33
-rw-r--r--innobase/include/srv0start.h2
-rw-r--r--innobase/include/sync0rw.h3
-rw-r--r--innobase/include/sync0sync.h6
-rw-r--r--innobase/include/trx0purge.h3
-rw-r--r--innobase/include/trx0trx.h116
-rw-r--r--innobase/lock/lock0lock.c555
-rw-r--r--innobase/log/log0log.c4
-rw-r--r--innobase/log/log0recv.c30
-rw-r--r--innobase/mem/mem0dbg.c12
-rw-r--r--innobase/os/os0file.c45
-rw-r--r--innobase/os/os0proc.c17
-rw-r--r--innobase/os/os0sync.c10
-rw-r--r--innobase/os/os0thread.c13
-rw-r--r--innobase/page/page0cur.c52
-rw-r--r--innobase/page/page0page.c256
-rw-r--r--innobase/pars/lexyy.c10
-rw-r--r--innobase/pars/pars0grm.c2
-rw-r--r--innobase/que/que0que.c24
-rw-r--r--innobase/read/read0read.c22
-rw-r--r--innobase/rem/rem0cmp.c2
-rw-r--r--innobase/row/row0ins.c213
-rw-r--r--innobase/row/row0mysql.c180
-rw-r--r--innobase/row/row0purge.c30
-rw-r--r--innobase/row/row0sel.c310
-rw-r--r--innobase/row/row0uins.c6
-rw-r--r--innobase/row/row0undo.c20
-rw-r--r--innobase/row/row0upd.c32
-rw-r--r--innobase/srv/srv0srv.c82
-rw-r--r--innobase/srv/srv0start.c135
-rw-r--r--innobase/stamp-h.in1
-rw-r--r--innobase/sync/sync0rw.c3
-rw-r--r--innobase/sync/sync0sync.c9
-rw-r--r--innobase/trx/trx0purge.c3
-rw-r--r--innobase/trx/trx0roll.c8
-rw-r--r--innobase/trx/trx0trx.c16
-rw-r--r--isam/pack_isam.c14
-rw-r--r--libmysql/errmsg.c15
-rw-r--r--libmysql/libmysql.c16
-rw-r--r--libmysql/password.c2
-rw-r--r--libmysqld/lib_sql.cc4
-rw-r--r--myisam/ft_boolean_search.c18
-rw-r--r--myisam/ft_nlq_search.c3
-rw-r--r--myisam/mi_dynrec.c18
-rw-r--r--myisam/mi_open.c3
-rw-r--r--myisam/mi_page.c4
-rw-r--r--myisam/mi_write.c3
-rw-r--r--myisam/sort.c2
-rw-r--r--myisammrg/Makefile.am2
-rw-r--r--myisammrg/myrg_range.c41
-rw-r--r--mysql-test/mysql-test-run.sh27
-rw-r--r--mysql-test/r/bdb.result14
-rw-r--r--mysql-test/r/bdb_cache.result100
-rw-r--r--mysql-test/r/bool.result74
-rw-r--r--mysql-test/r/compare.result2
-rw-r--r--mysql-test/r/create.result2
-rw-r--r--mysql-test/r/distinct.result12
-rw-r--r--mysql-test/r/explain.result4
-rw-r--r--mysql-test/r/fulltext.result3
-rw-r--r--mysql-test/r/func_time.result24
-rw-r--r--mysql-test/r/group_by.result41
-rw-r--r--mysql-test/r/heap.result12
-rw-r--r--mysql-test/r/innodb.result20
-rw-r--r--mysql-test/r/isam.result6
-rw-r--r--mysql-test/r/join_outer.result14
-rw-r--r--mysql-test/r/key_diff.result2
-rw-r--r--mysql-test/r/merge.result59
-rw-r--r--mysql-test/r/multi_update.result27
-rw-r--r--mysql-test/r/myisam.result220
-rw-r--r--mysql-test/r/null.result2
-rw-r--r--mysql-test/r/null_key.result48
-rw-r--r--mysql-test/r/order_by.result38
-rw-r--r--mysql-test/r/query_cache.result6
-rw-r--r--mysql-test/r/rpl000007.result20
-rw-r--r--mysql-test/r/rpl_replicate_do.result28
-rw-r--r--mysql-test/r/rpl_rotate_logs.result3
-rw-r--r--mysql-test/r/select.result26
-rw-r--r--mysql-test/r/temp_table.result22
-rw-r--r--mysql-test/r/type_datetime.result2
-rw-r--r--mysql-test/r/type_decimal.result11
-rw-r--r--mysql-test/r/user_var.result8
-rw-r--r--mysql-test/r/variables.result6
-rw-r--r--mysql-test/t/bdb.test2
-rw-r--r--mysql-test/t/bdb_cache-master.opt1
-rw-r--r--mysql-test/t/bdb_cache.test50
-rw-r--r--mysql-test/t/bool.test51
-rw-r--r--mysql-test/t/fulltext.test1
-rw-r--r--mysql-test/t/func_time.test22
-rw-r--r--mysql-test/t/group_by.test41
-rw-r--r--mysql-test/t/merge.test52
-rw-r--r--mysql-test/t/multi_update.test28
-rw-r--r--mysql-test/t/myisam.test232
-rw-r--r--mysql-test/t/query_cache.test2
-rw-r--r--mysql-test/t/rpl000007-slave.opt1
-rw-r--r--mysql-test/t/rpl000007.test24
-rw-r--r--mysql-test/t/rpl_replicate_do-slave.opt1
-rw-r--r--mysql-test/t/rpl_replicate_do.test30
-rw-r--r--mysql-test/t/rpl_rotate_logs.test4
-rw-r--r--mysql-test/t/temp_table.test18
-rw-r--r--mysql-test/t/type_decimal.test10
-rw-r--r--mysql-test/t/variables.test6
-rw-r--r--mysys/Makefile.am5
-rw-r--r--mysys/hash.c15
-rw-r--r--mysys/mf_keycache.c11
-rw-r--r--mysys/my_aes.c24
-rw-r--r--mysys/my_alloc.c15
-rw-r--r--mysys/my_append.c2
-rw-r--r--mysys/my_copy.c2
-rw-r--r--mysys/my_pthread.c2
-rw-r--r--mysys/my_redel.c2
-rw-r--r--mysys/my_static.c2
-rw-r--r--mysys/my_static.h2
-rw-r--r--mysys/my_tempnam.c6
-rw-r--r--mysys/thr_alarm.c4
-rw-r--r--mysys/tree.c8
-rw-r--r--scripts/Makefile.am1
-rw-r--r--scripts/mysqlbug.sh2
-rw-r--r--scripts/mysqld_multi.sh3
-rw-r--r--scripts/mysqld_safe.sh3
-rw-r--r--scripts/mysqlhotcopy.sh1
-rw-r--r--sql-bench/Results/ATIS-mysql-Linux_2.4.4_SMP_alpha20
-rw-r--r--sql-bench/Results/RUN-mysql-Linux_2.4.4_SMP_alpha109
-rw-r--r--sql-bench/Results/alter-table-mysql-Linux_2.4.4_SMP_alpha16
-rw-r--r--sql-bench/Results/big-tables-mysql-Linux_2.4.4_SMP_alpha19
-rw-r--r--sql-bench/Results/connect-mysql-Linux_2.4.4_SMP_alpha35
-rw-r--r--sql-bench/Results/create-mysql-Linux_2.4.4_SMP_alpha18
-rw-r--r--sql-bench/Results/insert-mysql-Linux_2.4.4_SMP_alpha106
-rw-r--r--sql-bench/Results/select-mysql-Linux_2.4.4_SMP_alpha30
-rw-r--r--sql-bench/Results/transactions-mysql-Linux_2.4.4_SMP_alpha3
-rw-r--r--sql-bench/Results/wisconsin-mysql-Linux_2.4.4_SMP_alpha14
-rw-r--r--sql-bench/bench-init.pl.sh12
-rw-r--r--sql-bench/server-cfg.sh7
-rw-r--r--sql-bench/test-create.sh2
-rw-r--r--sql/field.cc155
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/gen_lex_hash.cc2
-rw-r--r--sql/ha_berkeley.cc4
-rw-r--r--sql/ha_berkeley.h3
-rw-r--r--sql/ha_heap.cc12
-rw-r--r--sql/ha_innodb.cc255
-rw-r--r--sql/ha_innodb.h2
-rw-r--r--sql/ha_isam.cc3
-rw-r--r--sql/ha_isammrg.cc12
-rw-r--r--sql/ha_myisam.cc46
-rw-r--r--sql/ha_myisammrg.cc66
-rw-r--r--sql/ha_myisammrg.h5
-rw-r--r--sql/handler.cc3
-rw-r--r--sql/handler.h3
-rw-r--r--sql/hash_filo.h4
-rw-r--r--sql/hostname.cc2
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_cmpfunc.cc88
-rw-r--r--sql/item_cmpfunc.h21
-rw-r--r--sql/item_func.cc63
-rw-r--r--sql/item_func.h2
-rw-r--r--sql/item_timefunc.cc19
-rw-r--r--sql/lex.h1
-rw-r--r--sql/lock.cc12
-rw-r--r--sql/log.cc38
-rw-r--r--sql/log_event.cc146
-rw-r--r--sql/log_event.h50
-rw-r--r--sql/mini_client.cc4
-rw-r--r--sql/mysql_priv.h23
-rw-r--r--sql/mysqld.cc136
-rw-r--r--sql/nt_servc.cc28
-rw-r--r--sql/opt_range.cc59
-rw-r--r--sql/opt_sum.cc13
-rw-r--r--sql/repl_failsafe.cc9
-rw-r--r--sql/set_var.cc25
-rw-r--r--sql/set_var.h17
-rw-r--r--sql/share/czech/errmsg.txt2
-rw-r--r--sql/share/danish/errmsg.txt2
-rw-r--r--sql/share/dutch/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/german/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/italian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/portuguese/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/russian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/spanish/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/share/ukrainian/errmsg.txt2
-rw-r--r--sql/slave.cc20
-rw-r--r--sql/slave.h4
-rw-r--r--sql/sql_acl.cc40
-rw-r--r--sql/sql_acl.h6
-rw-r--r--sql/sql_analyse.cc2
-rw-r--r--sql/sql_base.cc180
-rw-r--r--sql/sql_cache.cc129
-rw-r--r--sql/sql_cache.h4
-rw-r--r--sql/sql_class.cc107
-rw-r--r--sql/sql_class.h13
-rw-r--r--sql/sql_db.cc27
-rw-r--r--sql/sql_delete.cc108
-rw-r--r--sql/sql_insert.cc54
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_load.cc31
-rw-r--r--sql/sql_manager.cc2
-rw-r--r--sql/sql_parse.cc178
-rw-r--r--sql/sql_rename.cc2
-rw-r--r--sql/sql_repl.cc7
-rw-r--r--sql/sql_repl.h4
-rw-r--r--sql/sql_select.cc69
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_table.cc65
-rw-r--r--sql/sql_udf.cc4
-rw-r--r--sql/sql_update.cc117
-rw-r--r--sql/sql_yacc.yy246
-rw-r--r--sql/stacktrace.c2
-rw-r--r--sql/table.cc15
-rw-r--r--sql/table.h1
-rw-r--r--strings/Makefile.am11
-rw-r--r--strings/bmove_upp-sparc.s4
-rw-r--r--strings/do_ctype.c8
-rw-r--r--strings/str_test.c3
-rw-r--r--strings/strappend-sparc.s14
-rw-r--r--strings/strend-sparc.s6
-rw-r--r--strings/strmake-sparc.s8
-rw-r--r--strings/strmov-sparc.s6
-rw-r--r--strings/strnmov-sparc.s8
-rw-r--r--strings/strstr-sparc.s18
-rw-r--r--strings/strxmov-sparc.s17
-rw-r--r--support-files/mysql.server.sh2
-rw-r--r--tests/Makefile.am2
-rw-r--r--vio/viossl.c46
-rw-r--r--vio/viosslfactories.c6
300 files changed, 7654 insertions, 2415 deletions
diff --git a/.bzrignore b/.bzrignore
index 1f70a9c42c0..278c3de2ee5 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -31,8 +31,11 @@ BitKeeper/etc/gone
BitKeeper/etc/level
BitKeeper/etc/pushed
BitKeeper/tmp/*
+BitKeeper/tmp/bkr3sAHD
+BitKeeper/tmp/gone
COPYING
COPYING.LIB
+Docs/#manual.texi#
Docs/INSTALL-BINARY
Docs/include.texi
Docs/internals.info
@@ -73,6 +76,9 @@ PENDING/*
TAGS
aclocal.m4
autom4te.cache/*
+autom4te.cache/output.0
+autom4te.cache/requests
+autom4te.cache/traces.0
bdb/README
bdb/btree/btree_auto.c
bdb/build_unix/*
@@ -81,17 +87,21 @@ bdb/build_vxworks/db_int.h
bdb/build_win32/db.h
bdb/build_win32/db_archive.dsp
bdb/build_win32/db_checkpoint.dsp
+bdb/build_win32/db_config.h
+bdb/build_win32/db_cxx.h
bdb/build_win32/db_deadlock.dsp
bdb/build_win32/db_dll.dsp
bdb/build_win32/db_dump.dsp
bdb/build_win32/db_int.h
bdb/build_win32/db_java.dsp
bdb/build_win32/db_load.dsp
+bdb/build_win32/db_perf.dsp
bdb/build_win32/db_printlog.dsp
bdb/build_win32/db_recover.dsp
bdb/build_win32/db_stat.dsp
bdb/build_win32/db_static.dsp
bdb/build_win32/db_tcl.dsp
+bdb/build_win32/db_test.dsp
bdb/build_win32/db_upgrade.dsp
bdb/build_win32/db_verify.dsp
bdb/build_win32/ex_access.dsp
@@ -107,9 +117,16 @@ bdb/build_win32/excxx_lock.dsp
bdb/build_win32/excxx_mpool.dsp
bdb/build_win32/excxx_tpcb.dsp
bdb/build_win32/include.tcl
+bdb/build_win32/libdb.def
bdb/build_win32/libdb.rc
bdb/db/crdel_auto.c
bdb/db/db_auto.c
+bdb/dbinc_auto/*.*
+bdb/dbreg/dbreg_auto.c
+bdb/dist/autom4te.cache/*
+bdb/dist/autom4te.cache/output.0
+bdb/dist/autom4te.cache/requests
+bdb/dist/autom4te.cache/traces.0
bdb/dist/config.hin
bdb/dist/configure
bdb/dist/tags
@@ -118,11 +135,17 @@ bdb/dist/template/gen_client_ret
bdb/dist/template/rec_btree
bdb/dist/template/rec_crdel
bdb/dist/template/rec_db
+bdb/dist/template/rec_dbreg
+bdb/dist/template/rec_fileops
bdb/dist/template/rec_hash
bdb/dist/template/rec_log
bdb/dist/template/rec_qam
bdb/dist/template/rec_txn
+bdb/examples_c/ex_apprec/ex_apprec_auto.c
+bdb/examples_c/ex_apprec/ex_apprec_auto.h
+bdb/examples_c/ex_apprec/ex_apprec_template
bdb/examples_java
+bdb/fileops/fileops_auto.c
bdb/hash/hash_auto.c
bdb/include/btree_auto.h
bdb/include/btree_ext.h
@@ -151,16 +174,33 @@ bdb/include/tcl_ext.h
bdb/include/txn_auto.h
bdb/include/txn_ext.h
bdb/include/xa_ext.h
+bdb/java/src/com/sleepycat/db/Db.java
+bdb/java/src/com/sleepycat/db/DbBtreeStat.java
bdb/java/src/com/sleepycat/db/DbConstants.java
+bdb/java/src/com/sleepycat/db/DbHashStat.java
+bdb/java/src/com/sleepycat/db/DbLockStat.java
+bdb/java/src/com/sleepycat/db/DbLogStat.java
+bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
+bdb/java/src/com/sleepycat/db/DbQueueStat.java
+bdb/java/src/com/sleepycat/db/DbRepStat.java
+bdb/java/src/com/sleepycat/db/DbTxnStat.java
+bdb/libdb_java/java_stat_auto.c
+bdb/libdb_java/java_stat_auto.h
bdb/log/log_auto.c
bdb/qam/qam_auto.c
bdb/rpc_client/db_server_clnt.c
bdb/rpc_client/gen_client.c
+bdb/rpc_server/c/db_server_proc.c
+bdb/rpc_server/c/db_server_proc.sed
+bdb/rpc_server/c/db_server_svc.c
+bdb/rpc_server/c/db_server_xdr.c
+bdb/rpc_server/c/gen_db_server.c
bdb/rpc_server/db_server.x
bdb/rpc_server/db_server_proc.sed
bdb/rpc_server/db_server_svc.c
bdb/rpc_server/db_server_xdr.c
bdb/rpc_server/gen_db_server.c
+bdb/test/TESTS
bdb/test/include.tcl
bdb/test/logtrack.list
bdb/txn/txn_auto.c
@@ -194,6 +234,7 @@ configure.lineno
core
db-*.*.*
dbug/user.t
+depcomp
extra/comp_err
extra/my_print_defaults
extra/mysql_install
@@ -209,6 +250,9 @@ include/my_global.h
include/mysql_version.h
include/widec.h
innobase/autom4te.cache/*
+innobase/autom4te.cache/output.0
+innobase/autom4te.cache/requests
+innobase/autom4te.cache/traces.0
innobase/configure.lineno
innobase/conftest.s1
innobase/conftest.subs
@@ -392,9 +436,11 @@ mysql.kdevprj
mysql.proj
mysqld.S
mysqld.sym
+mysys/#mf_iocache.c#
mysys/charset2html
mysys/getopt.c
mysys/getopt1.c
+mysys/ste5KbMa
mysys/test_charset
mysys/test_dir
mysys/test_io_cache
@@ -511,33 +557,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-bdb/build_win32/db_config.h
-bdb/build_win32/db_cxx.h
-bdb/build_win32/db_perf.dsp
-bdb/build_win32/db_test.dsp
-bdb/build_win32/libdb.def
-bdb/dbinc_auto/*.*
-bdb/dbreg/dbreg_auto.c
-bdb/dist/template/rec_dbreg
-bdb/dist/template/rec_fileops
-bdb/examples_c/ex_apprec/ex_apprec_auto.c
-bdb/examples_c/ex_apprec/ex_apprec_auto.h
-bdb/examples_c/ex_apprec/ex_apprec_template
-bdb/fileops/fileops_auto.c
-bdb/java/src/com/sleepycat/db/Db.java
-bdb/java/src/com/sleepycat/db/DbBtreeStat.java
-bdb/java/src/com/sleepycat/db/DbHashStat.java
-bdb/java/src/com/sleepycat/db/DbLockStat.java
-bdb/java/src/com/sleepycat/db/DbLogStat.java
-bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
-bdb/java/src/com/sleepycat/db/DbQueueStat.java
-bdb/java/src/com/sleepycat/db/DbRepStat.java
-bdb/java/src/com/sleepycat/db/DbTxnStat.java
-bdb/libdb_java/java_stat_auto.c
-bdb/libdb_java/java_stat_auto.h
-bdb/rpc_server/c/db_server_proc.c
-bdb/rpc_server/c/db_server_proc.sed
-bdb/rpc_server/c/db_server_svc.c
-bdb/rpc_server/c/db_server_xdr.c
-bdb/rpc_server/c/gen_db_server.c
-bdb/test/TESTS
diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am
index 438b3a528cd..9c1ab24fde7 100644
--- a/BUILD/Makefile.am
+++ b/BUILD/Makefile.am
@@ -37,7 +37,7 @@ EXTRA_DIST = FINISH.sh \
compile-pentium-pgcc \
compile-solaris-sparc \
compile-solaris-sparc-debug \
- compile-solaris-sparc-fortre \
+ compile-solaris-sparc-forte \
compile-solaris-sparc-purify
# Don't update the files from bitkeeper
diff --git a/BUILD/compile-pentium-valgrind-max b/BUILD/compile-pentium-valgrind-max
new file mode 100755
index 00000000000..016b698a970
--- /dev/null
+++ b/BUILD/compile-pentium-valgrind-max
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium_cflags $debug_cflags -DHAVE_purify"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$pentium_configs $debug_configs"
+
+extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-embedded-server --with-openssl"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-solaris-sparc-forte b/BUILD/compile-solaris-sparc-forte
new file mode 100755
index 00000000000..afd106afc67
--- /dev/null
+++ b/BUILD/compile-solaris-sparc-forte
@@ -0,0 +1,39 @@
+#! /bin/sh
+
+gmake -k clean || true
+/bin/rm -f */.deps/*.P config.cache
+
+aclocal && autoheader && aclocal && automake && autoconf
+(cd bdb/dist && sh s_all)
+(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
+if [ -d gemini ]
+then
+ (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
+fi
+
+
+# Assume Forte is installed in /opt/SUNWSpro
+
+PATH=/opt/SUNWspro/bin/:$PATH
+
+# For "optimal" code for this computer add -fast to EXTRA
+# To compile 64 bit, add -xarch=v9 to EXTRA_64_BIT
+
+EXTRA_64_BIT="-xarch=v9" # Remove comment to get 64 bit binaries
+EXTRA="-fast" # Remove comment to target current machine
+
+#
+# The following should not need to be touched
+#
+
+STD="-mt -D_FORTEC_ $EXTRA $EXTRA_64_BIT"
+ASFLAGS="$EXTRA_64_BIT" \
+CC=cc-5.0 CFLAGS="-Xa -xstrconst $STD" \
+CXX=CC CXXFLAGS="-noex $STD" \
+./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
+
+gmake -j 4
+if [ $? = 0 ]
+then
+ make test
+fi
diff --git a/BUILD/compile-solaris-sparc-fortre b/BUILD/compile-solaris-sparc-fortre
deleted file mode 100755
index dca0412c979..00000000000
--- a/BUILD/compile-solaris-sparc-fortre
+++ /dev/null
@@ -1,19 +0,0 @@
-#! /bin/sh
-
-gmake -k clean || true
-/bin/rm -f */.deps/*.P config.cache
-
-aclocal && autoheader && aclocal && automake && autoconf
-(cd bdb/dist && sh s_all)
-(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
-if [ -d gemini ]
-then
- (cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
-fi
-
-PATH=/opt/SUNWspro/bin/:$PATH
-CC=cc CFLAGS="-Xa -fast -xO4 -native -xstrconst -mt -D_FORTREC_" \
-CXX=CC CXXFLAGS="-noex -xO4 -mt" \
-./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
-
-gmake -j 4
diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config
index 8305314e51b..ea30f368b52 100644
--- a/BitKeeper/etc/config
+++ b/BitKeeper/etc/config
@@ -42,7 +42,7 @@ single_host:
# discovers a problem which requires local intervention. Please make the
# contact information accurate so we can support you.
#
-contact: Sasha Pachev <sasha@mysql.com>
+contact: sys@mysql.com
#
# It is very important that this email address is filled out and accurate.
# If someone converts your repository to open logging (which you may not
@@ -51,7 +51,7 @@ contact: Sasha Pachev <sasha@mysql.com>
# response from anyone else at your location after 90 days, then open logging
# will be implicitly approved.
#
-email: sasha@mysql.com
+email: sys@mysql.com
#
# Add your street address if you like, it is optional.
#
diff --git a/BitKeeper/etc/gone b/BitKeeper/etc/gone
index 2c21b8e7e03..204044a2cc5 100644
--- a/BitKeeper/etc/gone
+++ b/BitKeeper/etc/gone
@@ -199,7 +199,9 @@ BK|sql-bench/Results/ATIS-mysql-3.21-Linux_2.2.1_i686|19700101030959|02022|660fb
BK|sql-bench/Results/ATIS-mysql-Linux_2.2.10_i686|19700101030959|02025|3fa4d167cceff7e8
BK|sql-bench/Results/ATIS-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02312|84ca3b85ff306133
BK|sql-bench/Results/ATIS-mysql-Linux_2.2.14_i686_xeon|19700101030959|02044|3e820c28bf4af63a
+BK|sql-bench/Results/ATIS-mysql-SunOS_5.5.1_sun4u|19700101030959|02031|dfb4c5f6b6db3b49
BK|sql-bench/Results/ATIS-mysql-SunOS_5.6_sun4m|19700101030959|02032|62028e0375b3b8b
+BK|sql-bench/Results/ATIS-mysql-SunOS_5.7_sun4u|19700101030959|02034|be0d9789776c5ed7
BK|sql-bench/Results/ATIS-mysql_3.21-Linux_2.0.35_i686|19700101030959|02036|c25425e045ca8dfc
BK|sql-bench/Results/ATIS-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02304|cbe120d860296d2f
BK|sql-bench/Results/ATIS-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02027|a74e7b82d3908fa9
@@ -263,7 +265,9 @@ BK|sql-bench/Results/RUN-mysql-3.21-Linux_2.2.1_i686|19700101030959|02050|f6fdd6
BK|sql-bench/Results/RUN-mysql-Linux_2.2.10_i686|19700101030959|02041|712f52be5d195406
BK|sql-bench/Results/RUN-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02038|8ee87b26b91c86fe
BK|sql-bench/Results/RUN-mysql-Linux_2.2.14_i686_xeon|19700101030959|02055|17854e751e1d9d1d
+BK|sql-bench/Results/RUN-mysql-SunOS_5.5.1_sun4u|19700101030959|02058|afbba182428e20df
BK|sql-bench/Results/RUN-mysql-SunOS_5.6_sun4m|19700101030959|02059|eafc8188345e262b
+BK|sql-bench/Results/RUN-mysql-SunOS_5.7_sun4u|19700101030959|02061|86e1dc0e25a8b8f
BK|sql-bench/Results/RUN-mysql_3.21-Linux_2.0.35_i686|19700101030959|02064|ea8672d8473435
BK|sql-bench/Results/RUN-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02310|a902e1a967d79c42
BK|sql-bench/Results/RUN-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02030|413ab3b8a99e61e9
@@ -273,7 +277,9 @@ BK|sql-bench/Results/alter-table-mysql-3.21-Linux_2.2.1_i686|19700101030959|0207
BK|sql-bench/Results/alter-table-mysql-Linux_2.2.10_i686|19700101030959|02081|93b78a85b720a186
BK|sql-bench/Results/alter-table-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02314|4ae4b989301df98b
BK|sql-bench/Results/alter-table-mysql-Linux_2.2.14_i686_xeon|19700101030959|02057|64cc4b874cd6fabf
+BK|sql-bench/Results/alter-table-mysql-SunOS_5.5.1_sun4u|19700101030959|02087|9d7e75667fcb29ec
BK|sql-bench/Results/alter-table-mysql-SunOS_5.6_sun4m|19700101030959|02088|8a1bd6589a189890
+BK|sql-bench/Results/alter-table-mysql-SunOS_5.7_sun4u|19700101030959|02090|ce74c2f623d3bb3
BK|sql-bench/Results/alter-table-mysql_3.21-Linux_2.0.35_i686|19700101030959|02092|762639f2560976bd
BK|sql-bench/Results/alter-table-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02316|1390155aad5b6e86
BK|sql-bench/Results/alter-table-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02317|9090bebb62ef164b
@@ -283,7 +289,9 @@ BK|sql-bench/Results/big-tables-mysql-3.21-Linux_2.2.1_i686|19700101030959|02106
BK|sql-bench/Results/big-tables-mysql-Linux_2.2.10_i686|19700101030959|02109|99daa1c5370d077d
BK|sql-bench/Results/big-tables-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02315|2804ec3c95be436a
BK|sql-bench/Results/big-tables-mysql-Linux_2.2.14_i686_xeon|19700101030959|02074|290c2c3de9d8e6b
+BK|sql-bench/Results/big-tables-mysql-SunOS_5.5.1_sun4u|19700101030959|02115|7d7b6c0bf58b9b79
BK|sql-bench/Results/big-tables-mysql-SunOS_5.6_sun4m|19700101030959|02116|f351a7f3e1e2257e
+BK|sql-bench/Results/big-tables-mysql-SunOS_5.7_sun4u|19700101030959|02118|ebc379b231312bbe
BK|sql-bench/Results/big-tables-mysql_3.21-Linux_2.0.35_i686|19700101030959|02120|190e827e569c99a4
BK|sql-bench/Results/big-tables-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02318|c5eabcb89ceac698
BK|sql-bench/Results/big-tables-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02319|856d503725373684
@@ -293,7 +301,9 @@ BK|sql-bench/Results/connect-mysql-3.21-Linux_2.2.1_i686|19700101030959|02134|c0
BK|sql-bench/Results/connect-mysql-Linux_2.2.10_i686|19700101030959|02137|c92505d77e19d5ec
BK|sql-bench/Results/connect-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02084|e7e2959b7387251f
BK|sql-bench/Results/connect-mysql-Linux_2.2.14_i686_xeon|19700101030959|02071|ea19dc3ec55b3618
+BK|sql-bench/Results/connect-mysql-SunOS_5.5.1_sun4u|19700101030959|02142|a9493110fe62e0b1
BK|sql-bench/Results/connect-mysql-SunOS_5.6_sun4m|19700101030959|02143|a10e3ddfa26a3e7f
+BK|sql-bench/Results/connect-mysql-SunOS_5.7_sun4u|19700101030959|02145|c67beb9e9d2cf32e
BK|sql-bench/Results/connect-mysql_3.21-Linux_2.0.35_i686|19700101030959|02146|650abd213e6828c6
BK|sql-bench/Results/connect-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02320|ce69cc65bc827b5c
BK|sql-bench/Results/connect-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02066|f801e08429a4f7c6
@@ -303,7 +313,9 @@ BK|sql-bench/Results/create-mysql-3.21-Linux_2.2.1_i686|19700101030959|02158|515
BK|sql-bench/Results/create-mysql-Linux_2.2.10_i686|19700101030959|02161|9e7822f66df6aa76
BK|sql-bench/Results/create-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02102|34ded91c5fc25de9
BK|sql-bench/Results/create-mysql-Linux_2.2.14_i686_xeon|19700101030959|02139|50d15991293030ef
+BK|sql-bench/Results/create-mysql-SunOS_5.5.1_sun4u|19700101030959|02166|bbb5de66fc56de7b
BK|sql-bench/Results/create-mysql-SunOS_5.6_sun4m|19700101030959|02221|9233114ae6f8c5f
+BK|sql-bench/Results/create-mysql-SunOS_5.7_sun4u|19700101030959|02223|7ee13bfcafeab498
BK|sql-bench/Results/create-mysql_3.21-Linux_2.0.35_i686|19700101030959|02225|df1b037d17b33587
BK|sql-bench/Results/create-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02321|e985e71d552ff09e
BK|sql-bench/Results/create-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02099|483dcf223d5abf81
@@ -313,7 +325,9 @@ BK|sql-bench/Results/insert-mysql-3.21-Linux_2.2.1_i686|19700101030959|02239|fd0
BK|sql-bench/Results/insert-mysql-Linux_2.2.10_i686|19700101030959|02242|763edf9aec633f51
BK|sql-bench/Results/insert-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02130|5be3d6f299738a31
BK|sql-bench/Results/insert-mysql-Linux_2.2.14_i686_xeon|19700101030959|02141|c683ee4b9d214298
+BK|sql-bench/Results/insert-mysql-SunOS_5.5.1_sun4u|19700101030959|02247|8a9ae41f9a79f79
BK|sql-bench/Results/insert-mysql-SunOS_5.6_sun4m|19700101030959|02248|3402d060ae20e19
+BK|sql-bench/Results/insert-mysql-SunOS_5.7_sun4u|19700101030959|02250|78efa132c6e252b9
BK|sql-bench/Results/insert-mysql_3.21-Linux_2.0.35_i686|19700101030959|02252|60c0965dff31db07
BK|sql-bench/Results/insert-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02322|ed252140ff399961
BK|sql-bench/Results/insert-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02114|29a3b8a1ca8aa9d
@@ -323,7 +337,9 @@ BK|sql-bench/Results/select-mysql-3.21-Linux_2.2.1_i686|19700101030959|02265|ed3
BK|sql-bench/Results/select-mysql-Linux_2.2.10_i686|19700101030959|02268|a2e264d777b787d
BK|sql-bench/Results/select-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02227|308117295c3bc096
BK|sql-bench/Results/select-mysql-Linux_2.2.14_i686_xeon|19700101030959|02152|ead3f11b46ac626f
+BK|sql-bench/Results/select-mysql-SunOS_5.5.1_sun4u|19700101030959|02273|c9a1a498a052e268
BK|sql-bench/Results/select-mysql-SunOS_5.6_sun4m|19700101030959|02274|4da215905bce988d
+BK|sql-bench/Results/select-mysql-SunOS_5.7_sun4u|19700101030959|02276|632c92971c61e34a
BK|sql-bench/Results/select-mysql_3.21-Linux_2.0.35_i686|19700101030959|02278|5fadbac5f98696a
BK|sql-bench/Results/select-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02323|e8c0871a668a610d
BK|sql-bench/Results/select-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02127|963a98ed526e2be4
@@ -333,7 +349,9 @@ BK|sql-bench/Results/wisconsin-mysql-3.21-Linux_2.2.1_i686|19700101030959|02290|
BK|sql-bench/Results/wisconsin-mysql-Linux_2.2.10_i686|19700101030959|02288|301a82b12a84922b
BK|sql-bench/Results/wisconsin-mysql-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02280|d01900af34fb33b8
BK|sql-bench/Results/wisconsin-mysql-Linux_2.2.14_i686_xeon|19700101030959|02154|7525b23938631801
+BK|sql-bench/Results/wisconsin-mysql-SunOS_5.5.1_sun4u|19700101030959|02297|379705afa2e12378
BK|sql-bench/Results/wisconsin-mysql-SunOS_5.6_sun4m|19700101030959|02298|ec61b14072715dc8
+BK|sql-bench/Results/wisconsin-mysql-SunOS_5.7_sun4u|19700101030959|02300|f27927f8c64ea8ad
BK|sql-bench/Results/wisconsin-mysql_3.21-Linux_2.0.35_i686|19700101030959|02302|31703d40ea6b4f66
BK|sql-bench/Results/wisconsin-mysql_fast-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02324|ec075a89dbdbbe6a
BK|sql-bench/Results/wisconsin-pg-Linux_2.2.14_5.0_i686-cmp-mysql,pg|19700101030959|02325|233d5aa529979990
@@ -727,6 +745,8 @@ mwagner@evoq.home.mwagner.org|mysql-test/xml/tests/sel000029.xml|20001017133713|
mwagner@evoq.home.mwagner.org|mysql-test/xml/tests/sel000030.xml|20001017133600|63205|c2b25781eefaee9
mwagner@evoq.home.mwagner.org|mysql-test/xml/xsl/README|20001013051514|26509|cd4bb681e5a0cd10
mwagner@evoq.home.mwagner.org|mysql-test/xml/xsl/mysqltest.xsl|20001013051514|27425|1b8f6ec4f1b5f634
+mwagner@work.mysql.com|mysql-test/r/3.23/sel000001.result|20001010091454|28284|383913ae4505ec86
+mwagner@work.mysql.com|mysql-test/r/3.23/sel000002.result|20001010091454|29230|d1787e6fd5dbc1cc
nick@nick.leippe.com|mysql-test/r/rpl_empty_master_crash.result|20020531235552|47718|615f521be2132141
nick@nick.leippe.com|mysql-test/t/rpl_empty_master_crash.test|20020531235552|52328|99464e737639ccc6
sasha@mysql.sashanet.com|BitKeeper/etc/logging_ok|20000801000905|12967|5b7d847a2158554
@@ -734,19 +754,36 @@ sasha@mysql.sashanet.com|build-tags|20011125054855|05181|7afb7e785b80f97
sasha@mysql.sashanet.com|build-tags|20011201050944|25384|b6f6fff142121618
sasha@mysql.sashanet.com|libmysql_r/acconfig.h|20001128060846|51084|65f1202b3b5c345f
sasha@mysql.sashanet.com|mysql-test/README.gcov|20001012045950|28177|5a6da067a30780ce
+sasha@mysql.sashanet.com|mysql-test/README.gcov|20001214012355|41825|2de7575ca81155e5
sasha@mysql.sashanet.com|mysql-test/README|20001010001022|12739|108667adaeabe3f5
sasha@mysql.sashanet.com|mysql-test/r/3.23/alt000001.result|20001122072330|24729|393103dbf15f35c9
+sasha@mysql.sashanet.com|mysql-test/r/3.23/ins000001.result|20001018175743|49824|f45c599efdf8352b
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000001.a.result|20001118063528|39426|2987b17db06808c3
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000001.b.result|20001118063528|44057|62e1fa91167cacc3
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000002.result|20001118063528|46039|109f5ceed1e0d64
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000003.result|20001118063528|48148|68d6ee00beaa011
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000004.a.result|20001118063528|50132|3415f066cb91c460
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000004.b.result|20001118063528|52094|352b35351551485
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000005.result|20001118063528|54071|a50962bc2340ab9a
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000006.result|20001118063528|56081|5653051e8ce6b4aa
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000007.result|20001121063807|21606|e0c3b6134e0884da
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000008.result|20001121063807|23636|c5cfee19ca5a7da9
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000009.result|20001121063807|25633|ed8042446ab97926
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000010.result|20001122072330|29430|3228109b8965b0f8
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000011.result|20001125024912|48851|c29dce30aa97f265
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000012.result|20001126062901|05938|35d6596da7b90fc5
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000012.status.result|20001126062901|09395|bbbd650b5beea32f
+sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000013.result|20001202171150|03876|ac5024e6cf6daac6
sasha@mysql.sashanet.com|mysql-test/r/3.23/rpl000013.status.result|20001202171150|06069|6bee190c298cc9fd
+sasha@mysql.sashanet.com|mysql-test/r/3.23/sel000003.result|20001011230020|64653|d7b657b1e3a286a7
+sasha@mysql.sashanet.com|mysql-test/r/3.23/sel000100.res|20001205131218|23520|84ed46856cb3a69f
sasha@mysql.sashanet.com|mysql-test/r/3.23/shw000001.result|20001121234128|16652|8b20b03d8319b9a5
sasha@mysql.sashanet.com|mysql-test/r/binlog-backup-restore.result|20010424233926|16010|605de78abda64d27
sasha@mysql.sashanet.com|mysql-test/r/df_crash.result|20010406010433|59989|4a3dbee64843953d
sasha@mysql.sashanet.com|mysql-test/r/identity.result|20010910233028|16331|e41453a364242503
sasha@mysql.sashanet.com|mysql-test/r/mrg000002.result|20001212152450|11492|745be0854aaaaf5e
+sasha@mysql.sashanet.com|mysql-test/r/slave-running.result|20001208141122|24303|f73e49462cf59e1f
+sasha@mysql.sashanet.com|mysql-test/r/slave-stopped.result|20001208141122|28916|25c134b1a4f1993a
sasha@mysql.sashanet.com|mysql-test/std_data/m.MRG|20001212152450|17736|3f5632c37af00f18
sasha@mysql.sashanet.com|mysql-test/std_data/m.frm|20001212152450|13897|e351dfe0b6824c0c
sasha@mysql.sashanet.com|mysql-test/std_data/select-key.master|20001009234916|07315|e6b83af25df0ce5
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 8134a08ea5e..c424926a248 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -16,6 +16,7 @@ bar@gw.udmsearch.izhnet.ru
bell@sanja.is.com.ua
bk@admin.bk
davida@isil.mysql.com
+gluh@gluh.(none)
heikki@donna.mysql.fi
heikki@hundin.mysql.fi
heikki@rescue.
@@ -41,6 +42,7 @@ miguel@hegel.local
miguel@light.
miguel@light.local
monty@bitch.mysql.fi
+monty@butch.
monty@donna.mysql.fi
monty@hundin.mysql.fi
monty@mashka.mysql.fi
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index a29bd99191d..8d647ef0d82 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -8,13 +8,13 @@ use Getopt::Long;
$opt_distribution=$opt_user=$opt_config_env="";
$opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix="";
$opt_tmp=$opt_version_suffix="";
-$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=0;
+$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_debug=0;
$opt_innodb=$opt_bdb=$opt_raid=$opt_libwrap=0;
GetOptions(
"bdb",
"build-thread=i",
- "config-env=s",
+ "config-env=s" => \@config_env,
"config-options=s" => \@config_options,
"dbd-options=s",
"debug",
@@ -45,6 +45,7 @@ GetOptions(
"use-old-distribution",
"user=s",
"version-suffix=s",
+ "with-debug",
"with-low-memory",
"with-other-libc=s",
"with-small-disk",
@@ -53,11 +54,6 @@ GetOptions(
usage() if ($opt_help);
usage() if (!$opt_distribution);
-if ($opt_bdb && $opt_version_suffix eq "")
-{
- $opt_version_suffix="-max";
-}
-
if (@make_options > 0)
{
chomp(@make_options);
@@ -70,6 +66,12 @@ if (@config_options > 0)
$opt_config_options= join(" ", @config_options);
}
+if (@config_env > 0)
+{
+ chomp(@config_env);
+ $opt_config_env= join(" ", @config_env);
+}
+
chomp($host=`hostname`);
$full_host_name=$host;
$connect_option= ($opt_tcpip ? "--host=$host" : "");
@@ -208,6 +210,7 @@ if ($opt_stage <= 1)
$opt_config_options.= " --disable-shared" if (!$opt_enable_shared); # Default for binary versions
$opt_config_options.= " --with-berkeley-db" if ($opt_bdb);
$opt_config_options.= " --with-client-ldflags=-all-static" if ($opt_static_client);
+ $opt_config_options.= " --with-debug" if ($opt_with_debug);
$opt_config_options.= " --with-libwrap" if ($opt_libwrap);
$opt_config_options.= " --with-low-memory" if ($opt_with_low_memory);
$opt_config_options.= " --with-mysqld-ldflags=-all-static" if ($opt_static_server);
@@ -258,7 +261,7 @@ if ($opt_stage <= 3)
log_system("rm -fr mysql-3* mysql-4* $pwd/$host/*.tar.gz");
log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat");
- $flags.= "--no-strip" if ($opt_no_strip);
+ $flags.= "--no-strip" if ($opt_no_strip || $opt_with_debug);
check_system("scripts/make_binary_distribution --tmp=$opt_tmp --suffix=$opt_suffix $flags",".tar.gz created");
safe_system("mv mysql*.tar.gz $pwd/$host");
if (-f "client/.libs/mysqladmin")
@@ -381,13 +384,15 @@ if ($opt_stage <= 9 && !$opt_no_test)
log_system("rm -f output/*");
$tmp= $opt_fast_benchmark ? "--fast --user root --small-test" : "";
check_system("perl ./run-all-tests --log --die-on-errors $connect_option $tmp","RUN-mysql");
+ # Run additional fast test with dynamic-row tables
+ check_system("perl ./run-all-tests --log --suffix=\"_dynamic_rows\" --die-on-errors $connect_option --fast --user=root --small-test --create-options=\"row_format=dynamic\"","RUN-mysql");
if ($opt_innodb)
{
- check_system("perl ./run-all-tests --log --suffix=\"_innodb\" --die-on-errors $connect_option $tmp --create-option=\"type=innodb\"","RUN-mysql");
+ check_system("perl ./run-all-tests --log --suffix=\"_innodb\" --die-on-errors $connect_option $tmp --create-options=\"type=innodb\"","RUN-mysql");
}
if ($opt_bdb)
{
- check_system("perl ./run-all-tests --log --suffix=\"_bdb\" --die-on-errors $connect_option $tmp --create-option=\"type=bdb\"","RUN-mysql");
+ check_system("perl ./run-all-tests --log --suffix=\"_bdb\" --die-on-errors $connect_option $tmp --create-options=\"type=bdb\"","RUN-mysql");
}
}
@@ -498,6 +503,9 @@ If user is empty then no mail is sent.
--version-suffix suffix
Set name suffix (e.g. 'com' or '-max') for a distribution
+--with-debug
+Build binaries with debug information (implies "--no-strip")
+
--with-low-memory
Use less memory when compiling.
@@ -528,7 +536,7 @@ sub abort
print TMP "To: $email\n";
print TMP "Subject: $ver$opt_version_suffix compilation failed\n\n";
close TMP;
- system("tail -40 $log > $log.mail");
+ system("tail -n 40 $log > $log.mail");
system("cat $mail_header_file $log.mail | $sendmail -t -f $email");
unlink($mail_header_file);
unlink("$log.mail");
@@ -604,7 +612,7 @@ sub which
my(@progs)=@_;
foreach $prog (@progs)
{
- chomp($found=`which $prog | head -1`);
+ chomp($found=`which $prog | head -n 1`);
if ($? == 0 && $found ne "" && index($found," ") == -1)
{
$found =~ s|/+|/|g; # Make nicer output
diff --git a/Docs/internals.texi b/Docs/internals.texi
index 871e51c50bd..7e364774e39 100644
--- a/Docs/internals.texi
+++ b/Docs/internals.texi
@@ -1,5 +1,5 @@
\input texinfo @c -*-texinfo-*-
-@c Copyright 2002 MySQL AB, TcX AB, Detron HB and Monty Program KB
+@c Copyright 2002 MySQL AB
@c
@c %**start of header
@setfilename internals.info
@@ -545,6 +545,8 @@ Print query.
* basic packets::
* communication::
* fieldtype codes::
+* protocol functions::
+* protocol version 2::
@end menu
@node raw packet without compression, raw packet with compression, protocol, protocol
@@ -755,7 +757,7 @@ For details, see @file{sql/net_pkg.cc::send_ok()}.
n data
-@node fieldtype codes, , communication, protocol
+@node fieldtype codes, protocol functions, communication, protocol
@section Fieldtype Codes
@example
@@ -779,6 +781,797 @@ Time 03 08 00 00 |01 0B |03 00 00 00
Date 03 0A 00 00 |01 0A |03 00 00 00
@end example
+@node protocol functions, protocol version 2, fieldtype codes, protocol
+@section Functions used to implement the protocol
+
+This should be merged with the above one and changed to texi format
+
+Raw packets
+-----------
+
+- The my_net_xxxx() functions handles the packaging of a stream of data
+ into a raw packet that contains a packet number, length and data.
+
+- This is implemented for the server in sql/net_serv.cc.
+ The client file, libmysql/net.c, is symlinked to this file
+
+The important functions are:
+
+my_net_write() Store a packet (= # number of bytes) to be sent
+net_flush() Send the packets stored in the buffer
+net_write_command() Send a command (1 byte) + packet to the server.
+my_net_read() Read a packet
+
+
+Include files
+-------------
+
+- include/mysql.h is included by all MySQL clients. It includes the
+ MYSQL and MYSQL_RES structures.
+- include/mysql_com.h is include by mysql.h and mysql_priv.h (the
+ server) and includes a lot of common functions and structures to
+ handle the client/server protocol.
+
+
+Packets from server to client:
+-----------------------------
+
+sql/net_pkg.cc:
+
+ - Sending of error packets
+ - Sending of OK packets (= end of data)
+ - Storing of values in a packet
+
+
+sql/sql_base.cc:
+
+ - Function send_fields() sends the field description to the client.
+
+sql/sql_show.cc:
+
+ - Sends results for a lot of SHOW commands, including:
+ SHOW DATABASES [like 'wildcard']
+ SHOW TABLES [like 'wildcard']
+
+
+Packets from client to server:
+------------------------------
+
+This is done in libmysql/libmysql.c
+
+The important ones are:
+
+- mysql_real_connect() Connects to a mysqld server
+- mysql_real_query() Sends a query to the server and
+ reads the ok packet or columns header.
+- mysql_store_result() Read a result set from the server to memory
+- mysql_use_result() Read a result set row by row from the server.
+
+- net_safe_read() Read a packet from the server with
+ error handling.
+- net_field_length() Reads the length of a packet string.
+- simple_command() Sends a command/query to the server.
+
+
+
+Connecting to mysqld (the MySQL server)
+---------------------------------------
+
+- On the client side: libmysql/libmysql.c::mysql_real_connect().
+- On the server side: sql/sql_parse.cc::check_connections()
+
+The packets sent during a connection are as follows
+
+Server: Send greeting package (includes server capabilites, server
+ version and a random string of bytes to be used to scramble
+ the password.
+Client: Sends package with client capabilites, user name, scrambled
+ password, database name
+
+Server: Sends ok package or error package.
+
+Client: If init command specified, send it t the server and read
+ ok/error package.
+
+
+Password functions
+------------------
+
+The passwords are scrambled to a random number and are stored in hex
+format on the server.
+
+The password handling is done in sql/password.c. The important
+function is 'scramble()', which takes the a password in clear text
+and uses this to 'encrypt' the random string sent by the server
+to a new message.
+
+The encrypted message is sent to the server which uses the stored
+random number password to encrypt the random string sent to the
+client. If this is equal to the new message the client sends to the
+server then the password is accepted.
+
+@node protocol version 2, , protocol functions, protocol
+@section Another description of the protocol
+
+This should be merged with the above one and changed to texi format.
+
+*****************************
+*
+* PROTOCOL OVERVIEW
+*
+*****************************
+
+The MySQL protocol is relatively simple, and is designed for high performance
+through minimisation of overhead, and extensibility through versioning and
+options flags. It is a request-response protocol, and does not allow
+multitasking or multiplexing over a single connection. There are two packet
+formats, 'raw' and 'compressed' (which is used when both client and
+server support zlib compression, and the client requests that data be
+compressed):
+
+* RAW PACKET, shorter than 16 M *
+
++-----------------------------------------------+
+| Packet Length | Packet no | Data |
+| 3 Bytes | 1 Byte | n Bytes |
++-----------------------------------------------+
+^ ^
+| 'HEADER' |
++-------------------------------+
+
+
+ * Packet Length: Calculated with int3store. See include/global.h for
+ details. The basic computation is length = byte1 +
+ (256 * byte2) + (256 * 256 * byte3). The max packetsize
+ can be 16 MB.
+
+ * Packet no: The packet number is incremented for each sent packet.
+ The first packet for each query from the client
+ starts with 0.
+
+ * Data: Specific to the operation being performed. Most often
+ used to send string data, such as a SQL query.
+
+* COMPRESSED PACKET *
+
++---------------------------------------------------+-----------------+
+| Packet Length | Packet no | Uncomp. Packet Length | Compressed Data |
+| 3 Bytes | 1 Byte | 3 Bytes | n bytes |
++---------------------------------------------------+-----------------+
+^ ^
+| 'HEADER' |
++---------------------------------------------------+
+
+ * Packet Length: Calculated with int3store. See include/my_global.h for
+ details. The basic computation is length = byte1 +
+ (256 * byte2) + (256 * 256 * byte3). The max packetsize
+ can be 16 MB.
+
+ * Packet no: The packet number is incremented for each sent packet.
+ The first packet starts with 0.
+
+ * Uncomp. Packet Length: The length of the original, uncompressed packet
+ If this is zero then the data is not compressed.
+
+ * Compressed Data: The original packet, compressed with zlib compression
+
+
+When using the compressed protocol, the client/server will only compress
+send packets where the new packet is smaller than the not compressed one.
+In other words, some packets may be compressed while others will not.
+
+The 'compressed data' is one or more packets in *RAW PACKET* format.
+
+*****************************
+*
+* FLOW OF EVENTS
+*
+*****************************
+
+To understand how a client communicates with a MySQL server, it is easiest
+to start with a high-level flow of events. Each event section will then be
+followed by details of the exact contents of each type of packet involved
+in the event flow.
+
+* *
+* CONNECTION ESTABLISHMENT *
+* *
+
+Clients connect to the server via a TCP/IP socket (port 3306 by default), a
+Unix Domain Socket, or named pipes (on Windows). Once connected, the
+following connection establishment sequence is followed:
+
++--------+ +--------+
+| Client | | Server |
++--------+ +--------+
+ | |
+ | Handshake initialisation, including MySQL server version, |
+ | protocol version and options supported, as well as the seed |
+ | for the password hash |
+ | |
+ | <-------------------------------------------------------------- |
+ | |
+ | Client options supported, max packet size for client |
+ | username, password crypted with seed from server, database |
+ | name. |
+ | |
+ | --------------------------------------------------------------> |
+ | |
+ | 'OK' packet if authentication succeeds, 'ERROR' packet if |
+ | authentication fails. |
+ | |
+ | <-------------------------------------------------------------- |
+ | |
+
+
+
+* HANDSHAKE INITIALISATION PACKET *
+
+
++--------------------------------------------------------------------+
+| Header | Prot. Version | Server Version String | 0x00 |
+| | 1 Byte | n bytes | 1 byte |
+|--------------------------------------------------------------------|
+| Thread Number | Crypt Seed | 0x00 | CLIENT_xxx options |
+| | | | supported by server |
+| 4 Bytes | 8 Bytes | 1 Byte | 2 Bytes |
+|--------------------------------------------------------------------|
+| Server charset no. | Server status variables | 0x00 padding |
+| 1 Byte | 2 Bytes | 13 bytes |
++--------------------------------------------------------------------+
+
+ * Protocol version (currently '10')
+ * Server Version String (e.g. '4.0.5-beta-log'). Can be any length as
+ it's followed by a 0 byte.
+ * Thread Number - ID of server thread handling this connection
+ * Crypt seed - seed used to crypt password in auth packet from client
+ * CLIENT_xxx options - see include/mysql_com.h
+ * Server charset no. - Index of charset in use by server
+ * Server status variables - see include/mysql_com.h
+ * The padding bytes are reserverd for future extensions to the protocol
+
+* CLIENT AUTH PACKET *
+
+
++--------------------------------------------------------------------+
+| Header | CLIENT_xxx options supported | max_allowed_packet |
+| | by client | for client |
+| | 2 Bytes | 3 bytes |
+|--------------------------------------------------------------------|
+| User Name | 0x00 | Crypted Password | 0x00 | Database Name |
+| n Bytes | 1 Byte | 8 Bytes | 1 Byte | n Bytes |
+|--------------------------------------------------------------------|
+| 0x00 |
+| 1 Byte |
++--------------------------------------------------------------------+
+
+ * CLIENT_xxx options that this client supports:
+
+#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
+#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
+#define CLIENT_LONG_FLAG 4 /* Get all column flags */
+#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
+#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */
+#define CLIENT_COMPRESS 32 /* Can use compression protocol */
+#define CLIENT_ODBC 64 /* Odbc client */
+#define CLIENT_LOCAL_FILES 128 /* Can use LOAD DATA LOCAL */
+#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */
+#define CLIENT_INTERACTIVE 1024 /* This is an interactive client */
+#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
+#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
+#define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */
+
+ * max_allowed_packet for the client (in 'int3store' form)
+ * User Name - user to authenticate as. Is followed by a null byte.
+ * Crypted Password - password crypted with seed given in packet from
+ server, see scramble() in sql/password.c
+ * Database name (optional) - initial database to use once connected
+ Is followed by a null byte
+
+At the end of every client/server exchange there is either an 'OK' packet
+or an 'ERROR' packet sent from the server. To determine whether a packet is
+an 'OK' packet, or an 'ERROR' packet, check if the first byte (after the
+header) is 0xFF. If it has the value of 0xFF, the packet is an 'ERROR'
+packet.
+
+
+* OK PACKET *
+
+For details, see sql/net_pkg.cc::send_ok()
+
++-----------------------------------------------+
+| Header | No of Rows | Affected Rows |
+| | 1 Byte | 1-9 Byte |
+|-----------------------------------------------|
+| ID (last_insert_id) | Status | Length |
+| 1-9 Byte | 2 Byte | 1-9 Byte |
+|-----------------------------------------------|
+| Messagetext |
+| n Byte |
++-----------------------------------------------+
+
+ * Number of rows, always 0
+ * Affected rows
+ * ID (last_insert_id) - value for auto_increment column (if any)
+ * Status (usually 0)
+
+In general, in the MySQL protocol, fields in a packet that that
+represent numeric data, such as lengths, that are labeled as '1-9'
+bytes can be decoded by the following logic:
+
+ If the first byte is '251', the
+ corresponding column value is NULL (only appropriate in
+ 'ROW DATA' packets).
+
+ If the first byte is '252', the value stored can be read
+ from the following 2 bytes as a 16-bit integer.
+
+
+ If the first byte is '253' the value stored can be read
+ from the following 4 bytes as a 32-bit long integer
+
+
+ If the first byte is '254', the value stored can be read
+ from the following 8 bytes as a 64-byte long
+
+ Otherwise (values 0-250), the value stored is the value of the
+ first byte itself.
+
+
+If the OK-packet includes a message:
+
+ * Length of message
+ * Message Text
+
+
+* ERROR PACKET *
+
++-----------------------------------------------+
+| Header | Status code | Error no |
+| | 1 Byte | 2 Byte |
+|-----------------------------------------------|
+| Messagetext | |
+| n Byte | |
++-----------------------------------------------+
+
+ * Status code (0xFF = ERROR)
+ * Error number (is only sent to 3.23 and newer clients)
+ * Error message text (ends at end of packet)
+
+Note that the error message is not null terminated.
+The client code can however assume that the packet ends with a null
+as my_net_read() will always add an end-null to all read packets to
+make things easier for the client.
+
+Example:
+
+Packet dump of client connecting to server:
+
++------------------------- Protocol Version (10)
+|
+| +---------------------- Server Version String (0x00 terminated)
+| |
+| |
+0a 34 2e 30 2e 35 2d 62 . 4 . 0 . 5 - b
+65 74 61 2d 6c 6f 67 00 e t a - l o g .
+15 00 00 00 2b 5a 65 6c . . . . + Z e l
+ | |
+ | +------------ First 4 bytes of crypt seed
+ |
+ +------------------------ Thread Number
+
++------------------------- Last 4 bytes of crypt seed
+|
+| +-------- CLIENT_XXX Options supported by server
+| |
+| +-+--+ +--- Server charset index
+| | | |
+6f 69 41 46 00 2c 28 08 o i A F . , ( .
+02 00 00 00 00 00 00 00 . . . . . . . .
+| |
+| +---------------------- 0x00 padding begins
+|
++------------------------- Server status (0x02 =
+ SERVER_STATUS_AUTOCOMMIT)
+
+00 00 00 00 00 00 00 00 . . . . . . . .
+
+* Client Authentication Response (Username 'test', no database
+ selected) *
+
+ +--------------------- Packet Length (0x13 = 19 bytes)
+ |
+ | +--------------- Packet Sequence #
+ | |
+ | | +----------- CLIENT_XXX Options supported by client
+ | |
++---+---+ | +-+-+
+| | | | |
+13 00 00 01 03 00 1e 00 . . . . . . . .
+00 74 65 73 74 00 48 5e . t e s t . H ^
+ | | |
+ +----+-----+ +------- Scrambled password, 0x00 terminated
+ |
+ +----------------- Username, 0x00 terminated
+
+57 4a 4e 41 4a 4e 00 00 W J N A J N . .
+00 .
+
+
+>From this point on, the server waits for 'commands' from the client
+which include queries, database shutdown, quit, change user, etc (see
+the COM_xxxx values in include/mysql_com.h for the latest
+command codes).
+
+* *
+* COMMAND PROCESSING *
+* *
+
++--------+ +--------+
+| Client | | Server |
++--------+ +--------+
+ | |
+ | A command packet, with a command code, and string data |
+ | when appropriate (e.g. a query), (see the COM_xxxx values |
+ | in include/mysql_com.h for the command codes) |
+ | |
+ | --------------------------------------------------------------> |
+ | |
+ | A 'RESULT' packet if the command completed successfully, |
+ | an 'ERROR' packet if the command failed. 'RESULT' packets |
+ | take different forms (see the details following this chart) |
+ | depending on whether or not the command returns rows. |
+ | |
+ | <-------------------------------------------------------------- |
+ | |
+ | n 'FIELD PACKET's (if rows are returned) |
+ | |
+ | <-------------------------------------------------------------- |
+ | |
+ | 'LAST DATA' packet |
+ | |
+ | <-------------------------------------------------------------- |
+ | |
+ | n 'ROW PACKET's (if rows are returned) |
+ | |
+ | <-------------------------------------------------------------- |
+ | |
+ | 'LAST DATA' packet |
+ | |
+ | <-------------------------------------------------------------- |
+ | |
+
+
+* Command Packet *
+
++------------------------------------------------------+
+| Header | Command type | Query (if applicable) |
+| | 1 Byte | n Bytes |
++------------------------------------------------------+
+
+ * Command type: (e.g.0x03 = query, see the COM_xxxx values in
+ include/mysql_com.h)
+ * Query (if applicable)
+
+Note that my_net_read() null-terminates all packets on the
+receiving side of the channel to make it easier for the code
+examining the packets.
+
+The current command codes are:
+
+ 0x00 COM_SLEEP
+ 0x01 COM_QUIT
+ 0x02 COM_INIT_DB
+ 0x03 COM_QUERY
+ 0x04 COM_FIELD_LIST
+ 0x05 COM_CREATE_DB
+ 0x06 COM_DROP_DB
+ 0x07 COM_REFRESH
+ 0x08 COM_SHUTDOWN
+ 0x09 COM_STATISTICS
+ 0x0a COM_PROCESS_INFO
+ 0x0b COM_CONNECT
+ 0x0c COM_PROCESS_KILL
+ 0x0d COM_DEBUG
+ 0x0e COM_PING
+ 0x0f COM_TIME
+ 0x10 COM_DELAYED_INSERT
+ 0x11 COM_CHANGE_USER
+ 0x12 COM_BINLOG_DUMP
+ 0x13 COM_TABLE_DUMP
+ 0x14 COM_CONNECT_OUT
+ 0x15 COM_REGISTER_SLAVE
+
+* Result Packet *
+
+Result packet for a command returning _no_ rows:
+
++-----------------------------------------------+
+| Header | Field Count | Affected Rows |
+| | 1-9 Bytes | 1-9 Bytes |
+|-----------------------------------------------|
+| ID (last_insert_id) | Server Status |
+| 1-9 Bytes | 2 Bytes |
++-----------------------------------------------+
+
+ * Field Count: Has value of '0' for commands returning _no_ rows
+ * Affected rows: Count of rows affected by INSERT/UPDATE/DELETE, etc.
+ * ID: value of auto_increment column in row (if any). 0 if
+ * Server Status: Usually 0
+
+Result packet for a command returning rows:
+
++-------------------------------+
+| Header | Field Count |
+| | 1-9 Bytes |
++-------------------------------+
+
+ * Field Count: number of columns/fields in result set,
+ (packed with net_store_length() in sql/net_pkg.cc)
+
+This is followed by as many packets as the number of fields ('Field Count')
+that contain the metadata for each column/field (see unpack_fields() in
+libmysql/libmysql.c):
+
+
+* FIELD PACKET *
+
++-----------------------------------------------+
+| Header | Table Name |
+| | length-coded-string |
+|-----------------------------------------------|
+| Field Name |
+| length-code-string |
+|-----------------------------------------------|
+| Display length of field
+| length-coded-binary (4 bytes) |
+|-----------------------------------------------|
+| Field Type (enum_field_types in mysql_com.h) |
+| length-coded-binary (2 bytes) |
+|-----------------------------------------------|
+| Field Flags | Decimal Places|
+| length-coded-binary (3 bytes) | 1 Byte |
++--------------+-------------+------------------+
+
+ * A length coded string is a string where we first have a packet
+ length (1-9 bytes, packed_with net_store_length()) followed
+ by a string.
+ * A length coded binary is a length (1 byte) followed by an integer
+ value in low-byte-first order. For the moment this type is always
+ fixed length in this packet.
+
+ * Table Name - the name of the table the column comes from
+ * Field Name - the name of the column/field
+ * Display length of field - length of field
+ * Field Type - Type of field, see enum_field_types in
+ include/mysql_com.h
+
+ Current field types are:
+
+ 0x00 FIELD_TYPE_DECIMAL
+ 0x01 FIELD_TYPE_TINY
+ 0x02 FIELD_TYPE_SHORT
+ 0x03 FIELD_TYPE_LONG
+ 0x04 FIELD_TYPE_FLOAT
+ 0x05 FIELD_TYPE_DOUBLE
+ 0x06 FIELD_TYPE_NULL
+ 0x07 FIELD_TYPE_TIMESTAMP
+ 0x08 FIELD_TYPE_LONGLONG
+ 0x09 FIELD_TYPE_INT24
+ 0x0a FIELD_TYPE_DATE
+ 0x0b FIELD_TYPE_TIME
+ 0x0c FIELD_TYPE_DATETIME
+ 0x0d FIELD_TYPE_YEAR
+ 0x0e FIELD_TYPE_NEWDATE
+ 0xf7 FIELD_TYPE_ENUM
+ 0xf8 FIELD_TYPE_SET
+ 0xf9 FIELD_TYPE_TINY_BLOB
+ 0xfa FIELD_TYPE_MEDIUM_BLOB
+ 0xfb FIELD_TYPE_LONG_BLOB
+ 0xfc FIELD_TYPE_BLOB
+ 0xfd FIELD_TYPE_VAR_STRING
+ 0xfe FIELD_TYPE_STRING
+ 0xff FIELD_TYPE_GEOMETRY
+
+ * Field Flags - NOT_NULL_FLAG, PRI_KEY_FLAG, xxx_FLAG in
+ include/mysql_com.h
+
+
+Note that the packet format in 4.1 has slightly changed to allow more values.
+
+
+* ROW PACKET *
+
++-----------------------------------------------+
+| Header | Data Length | Column Data | ....for each column
+| | 1-9 Bytes | n Bytes |
++-----------------------------------------------+
+
+ * Data Length: (packed with net_store_length() in sql/net_pkg.cc)
+
+ If 'Data Length' == 0, this is an 'ERROR PACKET'.
+
+ * Column Data: String representation of data. MySQL always sends result set
+ data as strings.
+
+* LAST DATA PACKET *
+
+Packet length is < 9 bytes, and first byte is 0xFE
+
++--------+
+| 0xFE |
+| 1 Byte |
++--------+
+
+Examples:
+
+***********
+*
+* INITDB Command
+*
+***********
+
+A client issuing an 'INITDB' (select the database to use) command,
+followed by an 'OK' packet with no rows and no affected rows from
+the server:
+
+* INITDB (select database to use) 'COMMAND' Packet *
+
+ +--------------------- Packet Length (5 bytes)
+ |
+ | +--------------- Packet Sequence #
+ | |
+ | | +------------ Command # (INITDB = 0x02)
+ | |
++---+---+ | | +---------- Beginning of query data
+| | | | |
+05 00 00 00 02 74 65 73 . . . . . t e s
+74 t
+
+* 'OK' Packet with no rows, and no rows affected *
+
+ +--------------------- Packet Length (3 bytes)
+ |
+ | +--------------- Packet Sequence #
+ | |
++---+---+ |
+| | |
+03 00 00 01 00 00 00 . . . . . . .
+
+
+***********
+*
+* SELECT query example
+*
+***********
+
+Client issuing a 'SELECT *' query on the following table:
+
+ CREATE TABLE number_test (minBigInt bigint,
+ maxBigInt bigint,
+ testBigInt bigint)
+
+* 'COMMAND' Packet with QUERY (select ...) *
+
+ +--------------------- Packet Length (26)
+ |
+ | +--------------- Packet Sequence #
+ | |
+ | | +------------ Command # (QUERY = 0x03)
+ | |
++---+---+ | | +---------- Beginning of query data
+| | | | |
+1a 00 00 00 03 53 45 4c . . . . . S E L
+45 43 54 20 2a 20 66 72 E C T . * . f r
+6f 6d 20 6e 75 6d 62 65 o m . n u m b e
+72 5f 74 65 73 74 r _ t e s t
+
+
+and receiving an 'OK' packet with a 'FIELD COUNT' of 3
+
+
+* 'OK' Packet with 3 fields *
+
+ +--------------------- Packet Length (3 bytes)
+ |
+ | +--------------- Packet Sequence #
+ | |
++---+---+ |
+| | |
+01 00 00 01 03 . . . . .
+
+Followed immediately by 3 'FIELD' Packets. Note, the individual packets
+are delimitted by =======, so that all fields can be annotated in the first
+'FIELD' packet example:
+
+=============================================================
+
+ +--------------------- Packet Length (0x1f = 31 bytes)
+ |
+ | +--------------- Packet Sequence #
+ | |
+ | | +------------ Block Length (0x0b = 11 bytes)
+ | | |
++---+---+ | | +--------- Table Name (11 bytes long)
+| | | | |
+1f 00 00 02 0b 6e 75 6d . . . . . n u m
+62 65 72 5f 74 65 73 74 b e r _ t e s t
+
+ +------------------------ Block Length (9 bytes)
+ |
+ | +--------------------- Column Name (9 bytes long)
+ | |
+09 6d 69 6e 42 69 67 49 . m i n B i g I
+6e 74 03 14 00 00 01 08 n t . . . . . .
+ | | | | |
+ | +---+---+ | +--- Field Type (0x08 = FIELD_TYPE_LONGLONG)
+ | | |
+ | | +------ Block Length (1)
+ | |
+ | +--------------- Display Length (0x14 = 20 chars)
+ |
+ +------------------ Block Length (3)
+
+ +------------------------ Block Length (2)
+ |
+ | +-------------------- Field Flags (0 - no flags set)
+ | |
+ | +---+ +--------------- Decimal Places (0)
+ | | | |
+02 00 00 00 . . . .
+
+=============================================================
+
+'FIELD' packet for the 'number_Test.maxBigInt' column
+
+1f 00 00 03 0b 6e 75 6d . . . . . n u m
+62 65 72 5f 74 65 73 74 b e r _ t e s t
+09 6d 61 78 42 69 67 49 . m a x B i g I
+6e 74 03 14 00 00 01 08 n t . . . . . .
+02 00 00 00 . . . .
+
+=============================================================
+
+'FIELD' packet for the 'number_test.testBigInt' column
+
+20 00 00 04 0b 6e 75 6d . . . . . n u m
+62 65 72 5f 74 65 73 74 b e r _ t e s t
+0a 74 65 73 74 42 69 67 . t e st B i g
+49 6e 74 03 14 00 00 01 I n t . . . . .
+08 02 00 00 00 . . . . .
+=============================================================
+
+Followed immediately by one 'LAST DATA' packet:
+
+fe 00 . .
+
+Followed immediately by 'n' row packets (in this case, only
+one packet is sent from the server, for simplicity's sake):
+
+
+ +--------------------- Packet Length (0x52 = 82 bytes)
+ |
+ | +--------------- Packet Sequence #
+ | |
+ | | +------------ Data Length (0x14 = 20 bytes)
+ | | |
++---+---+ | | +--------- String Data '-9223372036854775808'
+| | | | | (repeat Data Length/Data sequence)
+
+52 00 00 06 14 2d 39 32 . . . . . - 9 2
+32 33 33 37 32 30 33 36 2 3 3 7 2 0 3 6
+38 35 34 37 37 35 38 30 8 5 4 7 7 5 8 0
+38 13 39 32 32 33 33 37 8 . 9 2 2 3 3 7
+32 30 33 36 38 35 34 37 2 0 3 6 8 5 4 7
+37 35 38 30 37 0a 36 31 7 5 8 0 7 . 6 1
+34 37 34 38 33 36 34 37 4 7 4 8 3 6 4 7
+
+Followed immediately by one 'LAST DATA' packet:
+
+fe 00 . .
+
+
+
@c The Index was empty, and ugly, so I removed it. (jcole, Sep 7, 2000)
@c @node Index
@@ -786,6 +1579,276 @@ Date 03 0A 00 00 |01 0A |03 00 00 00
@c @printindex fn
+@node 4.1 protocol,,,
+@subchapter MySQL 4.1 protocol
+
+@node 4.1 protocol changes,,,
+@section Changes to 4.0 protocol in 4.1
+
+All basic package handling is identical to 4.0. When communication
+with an old 4.0 or 3.x client we will use the old protocol.
+
+The new things that we support with 4.1 are:
+
+@itemize @bullet
+@item
+Warnings
+@item
+Prepared statements
+@item
+Binary protocol (will be much faster than the current protocol that
+converts everything to strings)
+@end itemize
+
+
+What has changed in 4.1 are:
+
+@itemize @bullet
+@item
+A lot of new field information (database, real table name etc)
+@item
+The 'ok' packet has more status fields
+@item
+The 'end' packet (send last for each result set) now contains some
+extra information
+@item
+New protocol for prepared statements. In this case all parameters and
+results will sent as binary (low-byte-first).
+@end itemize
+
+
+@node 4.1 field package,,,
+@section 4.1 field description package
+
+The field description package is sent as a response to a query that
+contains a result set. It can be distinguished from a ok package by
+the fact that the first byte can't be 0 for a field package.
+@xref {4.1 ok package}.
+
+The header package has the following structure:
+
+@multitable @columnfractions .10 .90
+@item Size @tab Comment
+@item 1-9 @tab Number of columns in result set (never 0)
+@item 1-9 @tab Extra information sent be some command (SHOW COLUMNS
+uses this to send the number of rows in the table)
+@end multitable
+
+This package is always followed by a field description set.
+@xref{4.1 field desc}.
+
+@node 4.1 field desc,,,
+@section 4.1 field description result set
+
+The field description result set contains the meta info for a result set.
+
+@multitable @columnfractions .20 .80
+@item Type @tab Comment
+@item string @tab Database name
+@item string @tab Table name alias (or table name if no alias)
+@item string @tab Real table name
+@item string @tab Alias for column name (or column name if not used)
+@item 3 byte int @tab Length of column definition
+@item 1 byte int @tab Enum value for field type
+@item 3 byte int @tab 2 byte column flags (NOT_NULL_FLAG etc..) + 1 byte number of decimals.
+@item string int @tab Default value, only set when using mysql_list_fields().
+@end multitable
+
+
+@node 4.1 ok package,,,
+@section 4.1 ok package
+
+The ok package is the first that is sent as an response for a query
+that didn't return a result set.
+
+The ok package has the following structure:
+
+@multitable @columnfractions .10 .90
+@item Size @tab Comment
+@item 1 @tab 0 ; Marker for ok package
+@item 1-9 @tab Affected rows
+@item 1-9 @tab Last insert id (0 if one wasn't used)
+@item 2 @tab Server status; Can be used by client to check if we are inside an transaction
+@item 2 @tab Warning count
+@item 1-9 @tab Message length (optional)
+@item xxx @tab Message (optional)
+@end multitable
+
+Size 1-9 means that the parameter is packed in to 1-9 bytes depending on
+the value. (See function sql/net_pkg.cc::net_store_length).
+
+The message is optional. For example for multi line INSERT it
+contains a string for how many rows was inserted / deleted.
+
+
+@node 4.1 end package,,,
+@section 4.1 end package
+
+The end package is sent as the last package for
+
+@itemize @bullet
+@item
+End of field information
+@item
+End of parameter type information
+@item
+End of result set
+@end itemize
+
+The end package has the following structure:
+
+@multitable @columnfractions .10 .90
+@item Size @tab Comment
+@item 1 @tab 254 ; Marker for EOF package
+@item 2 @tab Warning count
+@item 2 @tab Status flags (For flags like SERVER_STATUS_MORE_RESULTS)
+@end multitable
+
+Note that a normal package may start with byte 254, which means
+'length stored in 9 bytes'. One can different between these cases
+by checking the packet length < 9 bytes (in which case it's and end
+packet).
+
+
+@node 4.1 error package
+@section 4.1 error package.
+
+The error package is sent when something goes wrong.
+The error package has the following structure:
+
+@multitable @columnfractions .10 .90
+@item Size @tab Comment
+@item 1 @tab 255 Error package marker
+@item 1-255 @tab Null terminated error message
+@end multitable
+
+The client/server protocol is designed in such a way that a package
+can only start with 255 if it's an error package.
+
+
+@node 4.1 prep init,,,
+@section 4.1 prepared statement init package
+
+This is the return package when one sends a query with the COM_PREPARE
+command.
+
+@multitable @columnfractions .10 .90
+@item Size @tab Comment
+@item 4 @tab Statement handler id
+@item 2 @tab Number of columns in result set
+@item 2 @tab Number of parameters in query
+@end multitable
+
+After this, there is a packet that contains the following for each
+parameter in the query:
+
+@multitable @columnfractions .10 .90
+@item Size @tab Comment
+@item 2 @tab Enum value for field type. (MYSQL_TYPE_UNKNOWN if not known)
+@item 2 @tab 2 byte column flags (NOT_NULL_FLAG etc)
+@item 1 @tab Number of decimals
+@item 4 @tab Max column length.
+@end itemize
+
+Note that the above is not yet in 4.1 but will be added this month.
+
+As MySQL can have a parameter 'anywhere' it will in many cases not be
+able to provide the optimal information for all parameters.
+
+If number of columns, in the header package, is not 0 then the
+prepared statement will contain a result set. In this case the package
+is followed by a field description result set. @xref{4.1 field descr}.
+
+
+@node 4.1 long data,,,
+@section 4.1 long data handling
+
+This is used by mysql_send_long_data() to set any parameter to a string
+value. One can call mysql_send_long_data() multiple times for the
+same parameter; The server will concatenate the results to a one big
+string.
+
+The server will not require an end package for the string.
+mysql_send_long_data() is responsible updating a flag that all data
+has been sent. (Ie; That the last call to mysql_send_long_data() has
+the 'last_data' flag set).
+
+This package is sent from client -> server:
+
+@multitable @columnfractions .10 .90
+@item Size @tab Comment
+@item 4 @tab Statement handler
+@item 2 @tab Parameter number
+@item 2 @tab Type of parameter (not used at this point)
+@item # @tab data (Rest of package)
+@end itemize
+
+The server will NOT send an @code{ok} or @code{error} package in
+responce for this. If there is any errors (like to big string), one
+will get the error when calling execute.
+
+@node 4.1 execute,,,
+@section 4.1 execute
+
+On execute we send all parameters to the server in a COM_EXECUTE
+package.
+
+The package contains the following information:
+
+@multitable @columnfractions .30 .70
+@item Size @tab Comment
+@item (param_count+7)/8 @tab Null bit map
+@item 1 @tab new_parameter_bound flag. Is set to 1 for first
+execute or if one has rebound the parameters.
+@item 2*param_count @tab Type of parameters (only given if new_parameter_bound flag is 1)
+@item # @tab Parameter data, repeated for each parameter that are
+NOT NULL and not used with mysql_send_long_data().
+@end itemize
+
+The null-bit-map is for all parameters (including parameters sent with
+'mysql_send_long_data). If parameter 0 is NULL, then bit 0 in the
+null-bit-map should be 1 (ie: first byte should be 1)
+
+The parameters are stored the following ways:
+
+@multitable @columnfractions .20 .10 .70
+@item Type @tab Size @tab Comment
+@item tynyint @tab 1 @tab One byte integer
+@item short @tab 2 @tab
+@item int @tab 4 @tab
+@item longlong @tab 8 @tab
+@item float @tab 4 @tab
+@item double @tab 8 @tab
+@item string @tab 1-9 + # @tab Packed string length + string
+@end multitable
+
+The result for this will be either an ok package or a binary result
+set.
+
+@node 4.1 binary result,,,
+@section 4.1 binary result set
+
+A binary result are sent the following way.
+
+For each result row:
+
+@itemize
+@item
+null bit map with first two bits set to 01 (bit 0,1 value 1)
+@item
+parameter data, repeated for each not null parameter.
+@end itemize
+
+The idea with the reserving two bits in the null map is that we can
+use standard error (first byte 255) and ok packages (first byte 0)
+to end a result sets.
+
+Except that the null-bit-map is shifted two steps, the server is
+sending the data to the client the same way that the server is sending
+bound parameters to the client. The server is always sending the data
+as type given for 'column type' for respective column. It's up to the
+client to convert the parameter to the requested type.
+
@node Fulltext Search, , protocol, Top
@chapter Fulltext Search in MySQL
@@ -794,10 +1857,10 @@ fulltext search algorithms.
Now it's just unsorted notes.
@menu
-* Weighting in boolean mode::
+* Weighting in boolean mode::
@end menu
-@node Weighting in boolean mode, , , Fulltext Search
+@node Weighting in boolean mode, , Fulltext Search, Fulltext Search
@section Weighting in boolean mode
The basic idea is as follows: in expression
diff --git a/Docs/manual.texi b/Docs/manual.texi
index c39da1e37d1..283ad00d80f 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -8202,6 +8202,10 @@ The following startup variables/options have been renamed:
The startup options @code{record_buffer}, @code{sort_buffer} and
@code{warnings} will still work in MySQL 4.0 but are deprecated.
@item
+The mysqld option @code{--safe_show_database} doesn't work anymore. One
+should instead give the @code{SHOW DATABASES} privileges to everyone that
+need to see all databases.
+@item
The following SQL variables have changed name.
@c arjen note: New table, not yet measured for O'Reilly/DocBook.
@multitable @columnfractions .50 .50
@@ -19879,7 +19883,6 @@ differ somewhat:
| query_cache_limit | 1048576 |
| query_cache_size | 0 |
| query_cache_type | ON |
-| safe_show_database | OFF |
| server_id | 0 |
| slave_net_timeout | 3600 |
| skip_external_locking | ON |
@@ -20314,7 +20317,8 @@ This may be set (only numeric) to
Don't show databases for which the user doesn't have any database or
table privileges. This can improve security if you're concerned about
people being able to see what databases other users have. See also
-@code{skip_show_database}.
+@code{skip_show_database}. This option is deprecated as one should instead
+use the @code{SHOW DATABASES} privilege instead.
@item @code{server_id}
The value of the @code{--server-id} option.
@@ -20327,7 +20331,7 @@ Is ON if we only allow local (socket) connections.
@item @code{skip_show_database}
This prevents people from doing @code{SHOW DATABASES} if they don't have
-the @code{PROCESS} privilege. This can improve security if you're
+the @code{SHOW DATABASE} privilege. This can improve security if you're
concerned about people being able to see what databases other users
have. See also @code{safe_show_database}.
@@ -23506,17 +23510,21 @@ will be logged in the execution order.
Updates to non-transactional tables are stored in the binary log
immediately after execution. For transactional tables such as @code{BDB}
or @code{InnoDB} tables, all updates (@code{UPDATE}, @code{DELETE}
-or @code{INSERT}) that change tables are cached until a @code{COMMIT}.
+or @code{INSERT}) that change tables are cached until a @code{COMMIT} command
+is sent to the server. At this point mysqld writes the whole transaction to
+the binary log before the @code{COMMIT} is executed.
Every thread will, on start, allocate a buffer of @code{binlog_cache_size}
to buffer queries. If a query is bigger than this, the thread will open
-a temporary file to handle the bigger cache. The temporary file will
+a temporary file to store the transcation. The temporary file will
be deleted when the thread ends.
-The @code{max_binlog_cache_size} can be used to restrict the total size used
-to cache a multi-query transaction.
+The @code{max_binlog_cache_size} (default 4G) can be used to restrict
+the total size used to cache a multi-query transaction. If a transaction is
+bigger than this it will fail and roll back.
If you are using the update or binary log, concurrent inserts will
-not work together with @code{CREATE ... SELECT} and @code{INSERT ... SELECT}.
+be converted to normal inserts when using @code{CREATE ... SELECT} and
+@code{INSERT ... SELECT}.
This is to ensure that you can recreate an exact copy of your tables by
applying the log on a backup.
@@ -23683,7 +23691,7 @@ started}, your slaves may fail.
Please see the following table for an indication of master-slave
compatibility between different versions. With regard to version 4.0,
-we recommend using same version on both sides.
+we recommend using at least 4.0.4 on both sides.
@c FIX arjen 2002-07-17 new table, not yet measured for XML/DocBook.
@multitable @columnfractions .10 .15 .15 .10 .10 .10
@@ -24350,7 +24358,7 @@ may be used with @code{IO_THREAD} and @code{SQL_THREAD} options. (Slave)
@tab Re-enables update logging if the user has the @code{SUPER} privilege.
Ignored otherwise. (Master)
-@item @code{GLOBAL SET SQL_SLAVE_SKIP_COUNTER=n}
+@item @code{SET GLOBAL SQL_SLAVE_SKIP_COUNTER=n}
@tab Skip the next @code{n} events from the master. Only valid when
the slave thread is not running, otherwise, gives an error. Useful for
recovering from replication glitches.
@@ -25510,7 +25518,7 @@ temporary table to hold the result. This typically happens if you do an
@code{ORDER BY} on a different column set than you did a @code{GROUP
BY} on.
-@item Where used
+@item Using where (was @code{where used})
A @code{WHERE} clause will be used to restrict which rows will be
matched against the next table or sent to the client. If you don't have
this information and the table is of type @code{ALL} or @code{index},
@@ -25670,7 +25678,7 @@ Executing the @code{EXPLAIN} statement again produces this result:
@example
table type possible_keys key key_len ref rows Extra
-tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used
+tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 Using where
do ALL PRIMARY NULL NULL NULL 2135
range checked for each record (key map: 1)
et_1 ALL PRIMARY NULL NULL NULL 74
@@ -25696,7 +25704,7 @@ Now @code{EXPLAIN} produces the output shown here:
@example
table type possible_keys key key_len ref rows Extra
et ALL PRIMARY NULL NULL NULL 74
-tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 where used
+tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 Using where
ClientID,
ActualPC
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
@@ -25719,7 +25727,7 @@ Now the join is perfect, and @code{EXPLAIN} produces this result:
@example
table type possible_keys key key_len ref rows Extra
-tt ALL AssignedPC NULL NULL NULL 3872 where used
+tt ALL AssignedPC NULL NULL NULL 3872 Using where
ClientID,
ActualPC
et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
@@ -28868,7 +28876,6 @@ and if you can use @code{GLOBAL} or @code{SESSION} with them.
@item read_buffer_size @tab num @tab GLOBAL | SESSION
@item read_rnd_buffer_size @tab num @tab GLOBAL | SESSION
@item rpl_recovery_rank @tab num @tab GLOBAL
-@item safe_show_database @tab bool @tab GLOBAL
@item server_id @tab num @tab GLOBAL
@item slave_compressed_protocol @tab bool @tab GLOBAL
@item slave_net_timeout @tab num @tab GLOBAL
@@ -38698,8 +38705,8 @@ SUM_OVER_ALL_KEYS(max_length_of_key + sizeof(char*) * 2)
* Table and index:: Table and Index Structures
* File space management:: File Space Management and Disk I/O
* Error handling:: Error Handling
-* InnoDB change history:: InnoDB Change History
* InnoDB restrictions:: Restrictions on InnoDB Tables
+* InnoDB change history:: InnoDB Change History
* InnoDB contact information:: InnoDB Contact Information.
@end menu
@@ -50735,6 +50742,7 @@ this means that the version has not yet been released!
@c Please don't add a new version here without also updating ../configure.in!
@menu
+* News-4.1.x::
* News-4.0.x:: Changes in release 4.0.x (Beta)
* News-3.23.x:: Changes in release 3.23.x (Stable)
* News-3.22.x:: Changes in release 3.22.x (Older; Still supported)
@@ -50744,7 +50752,77 @@ this means that the version has not yet been released!
@end menu
-@node News-4.0.x, News-3.23.x, News, News
+@node News-4.1.x, News-4.0.x, News, News
+@appendixsec Changes in release 4.1.x (Alpha)
+
+@cindex changes, version 4.1
+
+Version 4.1 of the MySQL server includes many enhancements and new features:
+
+@itemize @bullet
+@item
+Sub selects: @code{SELECT * from t1 where t1.a=(SELECT t2.b FROM t2)}.
+@item
+Character sets to be defined per column, table and database.
+@item
+Unicode (UTF8) support.
+@item
+Derived tables: @code{SELECT a from t1, (select * from t2) WHERE t1.a=t2.a}
+@item
+@code{BTREE} index on @code{HEAP} tables.
+@item
+Support for GIS (Geometrical data).
+@item
+@code{SHOW WARNINGS}; Shows warnings for the last command.
+@end itemize
+
+For a full list of changes, please refer to the changelog sections for
+each individual 4.1.x release.
+
+@menu
+* News-4.1.0::
+@end menu
+
+@node News-4.1.0, , News-4.1.x, News-4.1.x
+@appendixsubsec Changes in release 4.1.0
+@itemize
+@item
+One can specify many temporary directories to be used in a round-robin
+fasion with: @code{--tmpdir=dirname1:dirname2:dirname3}.
+@item
+Sub selects: @code{SELECT * from t1 where t1.a=(SELECT t2.b FROM t2)}.
+@item
+Character sets to be defined per column, table and database.
+@item
+Unicode (UTF8) support.
+@item
+Derived tables: @code{SELECT a from t1, (select * from t2) WHERE t1.a=t2.a}
+@item
+@code{BTREE} index on @code{HEAP} tables.
+@item
+Faster embedded server.
+@item
+One can add a comment per column in @code{CREATE TABLE}.
+@item
+@code{SHOW FULL COLUMNS FROM table_name} shows column comments.
+@item
+@code{ALTER DATABASE}.
+@item
+Support for GIS (Geometrical data).
+@item
+@code{SHOW WARNINGS}; Shows warnings from the last command.
+@item
+One can specify a column type for a colum in @code{CREATE TABLE
+... SELECT} by defining the column in the @code{CREATE} part
+
+@example
+CREATE TABLE foo (a tinyint not null) SELECT b+1 AS 'a' FROM bar;
+@end example
+
+@end itemize
+
+
+@node News-4.0.x, News-3.23.x, News-4.1.x, News
@appendixsec Changes in release 4.0.x (Beta)
@cindex changes, version 4.0
@@ -50815,6 +50893,19 @@ each individual 4.0.x release.
@appendixsubsec Changes in release 4.0.5
@itemize
@item
+When one uses the @code{--open-files-limit=#} option to @code{mysqld_safe}
+it's now passed on to @code{mysqld}
+@item
+Fixed that @code{GROUP BY} on columns that may have a @code{NULL} value
+doesn't always use disk based temporary tables.
+@item
+Changed output from @code{EXPLAIN} from @code{'where used'} to
+@code{'Using where'} to make it more in line with other output.
+@item
+Removed variable @code{safe_show_database} as it was not used anymore.
+@item
+Read @code{--des-key-file} relative to database directory.
+@item
Small code improvement in multi-table updates
@item
Fixed a newly introduced bug that caused @code{ORDER BY ... LIMIT #}
@@ -51680,6 +51771,11 @@ not yet 100% confident in this code.
@appendixsubsec Changes in release 3.23.54
@itemize
@item
+Allow one to start multiple MySQL servers on windows (code backported
+from 4.0.2).
+@item
+Fixed that @code{--core-file} works on Linux (at least on kernel 2.4.18).
+@item
Fixed a problem with BDB and @code{ALTER TABLE}.
@item
Fixed reference to freed memory when doing complicated @code{GROUP BY
@@ -51765,6 +51861,11 @@ Changed initialisation of @code{RND()} to make it less predicatable.
Fixed problem with @code{GROUP BY} on result with expression that created a
@code{BLOB} field.
@item
+Fixed problem with @code{GROUP BY} on columns that have NULL values. To
+solve this we now create an MyISAM temporary table when doing a group by
+on a possible NULL item. In MySQL 4.0.5 we can again use in memory HEAP
+tables for this case.
+@item
Fixed problem with privilege tables when downgrading from 4.0.2 to 3.23.
@item
Fixed thread bug in @code{SLAVE START}, @code{SLAVE STOP} and automatic repair
@@ -52506,8 +52607,9 @@ long as @code{server-id} is set and valid @file{master.info} is present.
Partial updates (terminated with kill) are now logged with a special error
code to the binary log. Slave will refuse to execute them if the error code
indicates the update was terminated abnormally, and will have to be recovered
-with @code{SET SQL_SLAVE_SKIP_COUNTER=1; SLAVE START} after a manual sanity
-check/correction of data integrity.
+with @code{SET SQL_SLAVE_SKIP_COUNTER=1; SLAVE START} after a manual
+sanity check/correction of data integrity. Update: In 4.0.3 and above
+you have to use @code{SET GLOBAL}.
@item
Fixed bug that erroneously logged a drop of internal temporary table
on thread termination to the binary log -- this bug affected replication.
diff --git a/acconfig.h b/acconfig.h
index cf276d0b848..e969a635a5b 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -274,7 +274,7 @@
#undef SPRINTF_RETURNS_INT
#undef SPRINTF_RETURNS_GARBAGE
-/* Needed to get large file supportat HPUX 10.20 */
+/* Needed to get large file support on HPUX 10.20 */
#undef __STDC_EXT__
#undef STACK_DIRECTION
diff --git a/acinclude.m4 b/acinclude.m4
index e94304649fb..7190593af27 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1190,5 +1190,142 @@ dnl ---------------------------------------------------------------------------
dnl END OF MYSQL_CHECK_INNODB SECTION
dnl ---------------------------------------------------------------------------
+dnl By default, many hosts won't let programs access large files;
+dnl one must use special compiler options to get large-file access to work.
+dnl For more details about this brain damage please see:
+dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
+
+dnl Written by Paul Eggert <eggert@twinsun.com>.
+
+dnl Internal subroutine of AC_SYS_LARGEFILE.
+dnl AC_SYS_LARGEFILE_FLAGS(FLAGSNAME)
+AC_DEFUN(AC_SYS_LARGEFILE_FLAGS,
+ [AC_CACHE_CHECK([for $1 value to request large file support],
+ ac_cv_sys_largefile_$1,
+ [if ($GETCONF LFS_$1) >conftest.1 2>conftest.2 && test ! -s conftest.2
+ then
+ ac_cv_sys_largefile_$1=`cat conftest.1`
+ else
+ ac_cv_sys_largefile_$1=no
+ ifelse($1, CFLAGS,
+ [case "$host_os" in
+ # HP-UX 10.20 requires -D__STDC_EXT__ with gcc 2.95.1.
+changequote(, )dnl
+ hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
+changequote([, ])dnl
+ if test "$GCC" = yes; then
+ ac_cv_sys_largefile_CFLAGS=-D__STDC_EXT__
+ fi
+ ;;
+ # IRIX 6.2 and later require cc -n32.
+changequote(, )dnl
+ irix6.[2-9]* | irix6.1[0-9]* | irix[7-9].* | irix[1-9][0-9]*)
+changequote([, ])dnl
+ if test "$GCC" != yes; then
+ ac_cv_sys_largefile_CFLAGS=-n32
+ fi
+ esac
+ if test "$ac_cv_sys_largefile_CFLAGS" != no; then
+ ac_save_CC="$CC"
+ CC="$CC $ac_cv_sys_largefile_CFLAGS"
+ AC_TRY_LINK(, , , ac_cv_sys_largefile_CFLAGS=no)
+ CC="$ac_save_CC"
+ fi])
+ fi
+ rm -f conftest*])])
+
+dnl Internal subroutine of AC_SYS_LARGEFILE.
+dnl AC_SYS_LARGEFILE_SPACE_APPEND(VAR, VAL)
+AC_DEFUN(AC_SYS_LARGEFILE_SPACE_APPEND,
+ [case $2 in
+ no) ;;
+ ?*)
+ case "[$]$1" in
+ '') $1=$2 ;;
+ *) $1=[$]$1' '$2 ;;
+ esac ;;
+ esac])
+
+dnl Internal subroutine of AC_SYS_LARGEFILE.
+dnl AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, CACHE-VAR, COMMENT, CODE-TO-SET-DEFAULT)
+AC_DEFUN(AC_SYS_LARGEFILE_MACRO_VALUE,
+ [AC_CACHE_CHECK([for $1], $2,
+ [$2=no
+changequote(, )dnl
+ for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
+ case "$ac_flag" in
+ -D$1)
+ $2=1 ;;
+ -D$1=*)
+ $2=`expr " $ac_flag" : '[^=]*=\(.*\)'` ;;
+ esac
+ done
+ $4
+changequote([, ])dnl
+ ])
+ if test "[$]$2" != no; then
+ AC_DEFINE_UNQUOTED([$1], [$]$2, [$3])
+ fi])
+
+AC_DEFUN(MYSQL_SYS_LARGEFILE,
+ [AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_ARG_ENABLE(largefile,
+ [ --disable-largefile Omit support for large files])
+ if test "$enable_largefile" != no; then
+ AC_CHECK_TOOL(GETCONF, getconf)
+ AC_SYS_LARGEFILE_FLAGS(CFLAGS)
+ AC_SYS_LARGEFILE_FLAGS(LDFLAGS)
+ AC_SYS_LARGEFILE_FLAGS(LIBS)
+
+ for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
+ case "$ac_flag" in
+ no) ;;
+ -D_FILE_OFFSET_BITS=*) ;;
+ -D_LARGEFILE_SOURCE | -D_LARGEFILE_SOURCE=*) ;;
+ -D_LARGE_FILES | -D_LARGE_FILES=*) ;;
+ -D?* | -I?*)
+ AC_SYS_LARGEFILE_SPACE_APPEND(CPPFLAGS, "$ac_flag") ;;
+ *)
+ AC_SYS_LARGEFILE_SPACE_APPEND(CFLAGS, "$ac_flag") ;;
+ esac
+ done
+ AC_SYS_LARGEFILE_SPACE_APPEND(LDFLAGS, "$ac_cv_sys_largefile_LDFLAGS")
+ AC_SYS_LARGEFILE_SPACE_APPEND(LIBS, "$ac_cv_sys_largefile_LIBS")
+
+ AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS,
+ ac_cv_sys_file_offset_bits,
+ [Number of bits in a file offset, on hosts where this is settable.],
+ [case "$host_os" in
+ # HP-UX 10.20 and later
+ hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
+ ac_cv_sys_file_offset_bits=64 ;;
+ # We can't declare _FILE_OFFSET_BITS here as this will cause
+ # compile errors as AC_PROG_CC adds include files in confdefs.h
+ # We solve this (until autoconf is fixed) by instead declaring it
+ # as define instead
+ solaris2.[8,9])
+ CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64"
+ CXXFLAGS="$CXXFLAGS -D_FILE_OFFSET_BITS=64"
+ ac_cv_sys_file_offset_bits=no ;;
+ esac])
+ AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE,
+ ac_cv_sys_largefile_source,
+ [Define to make fseeko etc. visible, on some hosts.],
+ [case "$host_os" in
+ # HP-UX 10.20 and later
+ hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
+ ac_cv_sys_largefile_source=1 ;;
+ esac])
+ AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES,
+ ac_cv_sys_large_files,
+ [Define for large files, on AIX-style hosts.],
+ [case "$host_os" in
+ # AIX 4.2 and later
+ aix4.[2-9]* | aix4.1[0-9]* | aix[5-9].* | aix[1-9][0-9]*)
+ ac_cv_sys_large_files=1 ;;
+ esac])
+ fi
+ ])
+
dnl ---------------------------------------------------------------------------
diff --git a/client/client_priv.h b/client/client_priv.h
index 1d17165f2b4..eb4473cb10f 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -17,7 +17,7 @@
/* Common defines for all clients */
#include <my_global.h>
-#include <my_sys.h>
+#include <my_sys.h>
#include <m_string.h>
#include <mysql.h>
#include <mysql_embed.h>
@@ -38,4 +38,4 @@ enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET,
OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH,
OPT_SSL_CIPHER, OPT_SHUTDOWN_TIMEOUT, OPT_LOCAL_INFILE,
OPT_PROMPT, OPT_IGN_LINES,OPT_TRANSACTION,OPT_MYSQL_PROTOCOL,
- OPT_SHARED_MEMORY_BASE_NAME };
+ OPT_SHARED_MEMORY_BASE_NAME, OPT_FRM };
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index b2100ac1596..4cf86eb31c7 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -176,7 +176,7 @@ static void dump_remote_file(NET* net, const char* fname)
}
-static my_bool
+extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
@@ -210,7 +210,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
print_version();
exit(0);
case '?':
- default:
usage();
exit(0);
}
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 6b56603946a..f9719f05bf3 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -34,7 +34,7 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
opt_compress = 0, opt_databases = 0, opt_fast = 0,
opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
- tty_password = 0;
+ tty_password = 0, opt_frm = 0;
static uint verbose = 0, opt_mysql_port=0;
static my_string opt_mysql_unix_port = 0;
static char *opt_password = 0, *current_user = 0, *default_charset = 0,
@@ -139,13 +139,17 @@ static struct my_option my_long_options[] =
{"user", 'u', "User for login if not current user.", (gptr*) &current_user,
(gptr*) &current_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"use-frm", OPT_FRM,
+ "When used with REPAIR, get table structure from .frm file, so the table can be repaired even if .MYI header is corrupted.",
+ (gptr*) &opt_frm, (gptr*) &opt_frm, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
+ 0},
{"verbose", 'v', "Print info about the various stages.", 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},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-
+
static const char *load_default_groups[] = { "mysqlcheck", "client", 0 };
@@ -234,7 +238,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_password = my_strdup(argument, MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
- start[1] = 0; /* Cut length of argument */
+ start[1] = 0; /* Cut length of argument */
}
else
tty_password = 1;
@@ -368,21 +372,25 @@ static int process_selected_tables(char *db, char **table_names, int tables)
return 1;
if (opt_all_in_1)
{
+ /*
+ We need table list in form `a`, `b`, `c`
+ that's why we need 4 more chars added to to each table name
+ space is for more readable output in logs and in case of error
+ */
char *table_names_comma_sep, *end;
int i, tot_length = 0;
for (i = 0; i < tables; i++)
- tot_length += strlen(*(table_names + i)) + 1;
+ tot_length += strlen(*(table_names + i)) + 4;
if (!(table_names_comma_sep = (char *)
- my_malloc((sizeof(char) * tot_length) + 1, MYF(MY_WME))))
+ my_malloc((sizeof(char) * tot_length) + 4, MYF(MY_WME))))
return 1;
for (end = table_names_comma_sep + 1; tables > 0;
tables--, table_names++)
{
- end = strmov(end, *table_names);
- *end++= ',';
+ end = strxmov(end, " `", *table_names, "`,", NullS);
}
*--end = 0;
handle_request_for_tables(table_names_comma_sep + 1, tot_length - 1);
@@ -409,22 +417,27 @@ static int process_all_tables_in_db(char *database)
if (opt_all_in_1)
{
+ /*
+ We need table list in form `a`, `b`, `c`
+ that's why we need 4 more chars added to to each table name
+ space is for more readable output in logs and in case of error
+ */
+
char *tables, *end;
uint tot_length = 0;
while ((row = mysql_fetch_row(res)))
- tot_length += strlen(row[0]) + 1;
+ tot_length += strlen(row[0]) + 4;
mysql_data_seek(res, 0);
- if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+1, MYF(MY_WME))))
+ if (!(tables=(char *) my_malloc(sizeof(char)*tot_length+4, MYF(MY_WME))))
{
mysql_free_result(res);
return 1;
}
for (end = tables + 1; (row = mysql_fetch_row(res)) ;)
{
- end = strmov(end, row[0]);
- *end++= ',';
+ end = strxmov(end, " `", row[0], "`,", NullS);
}
*--end = 0;
if (tot_length)
@@ -472,6 +485,7 @@ static int handle_request_for_tables(char *tables, uint length)
op = "REPAIR";
if (opt_quick) end = strmov(end, " QUICK");
if (opt_extended) end = strmov(end, " EXTENDED");
+ if (opt_frm) end = strmov(end, " USE_FRM");
break;
case DO_ANALYZE:
op = "ANALYZE";
@@ -483,10 +497,14 @@ static int handle_request_for_tables(char *tables, uint length)
if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME))))
return 1;
- sprintf(query, "%s TABLE %s %s", op, tables, options);
+ if (opt_all_in_1)
+ /* No backticks here as we added them before */
+ sprintf(query, "%s TABLE %s %s", op, tables, options);
+ else
+ sprintf(query, "%s TABLE `%s` %s", op, tables, options);
if (mysql_query(sock, query))
{
- sprintf(message, "when executing '%s TABLE `%s` %s", op, tables,options);
+ sprintf(message, "when executing '%s TABLE ... %s'", op, options);
DBerror(sock, message);
return 1;
}
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 4333058fad7..9534cc68ed4 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -305,7 +305,10 @@ static void short_usage(void)
static void write_header(FILE *sql_file, char *db_name)
{
if (opt_xml)
+ {
fprintf(sql_file,"<?xml version=\"1.0\"?>\n");
+ fprintf(sql_file,"<mysqldump>\n");
+ }
else
{
fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
@@ -319,6 +322,12 @@ static void write_header(FILE *sql_file, char *db_name)
return;
} /* write_header */
+static void write_footer(FILE *sql_file)
+{
+ if (opt_xml)
+ fprintf(sql_file,"</mysqldump>");
+ fputs("\n", sql_file);
+} /* write_footer */
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
@@ -1004,7 +1013,7 @@ static void dumpTable(uint numFields, char *table)
rownr=0;
init_length=(uint) strlen(insert_pat)+4;
if (opt_xml)
- fprintf(md_result_file, "\t<%s>\n", table);
+ fprintf(md_result_file, "\t<table name=\"%s\">\n", table);
if (opt_autocommit)
fprintf(md_result_file, "set autocommit=0;\n");
@@ -1094,9 +1103,9 @@ static void dumpTable(uint numFields, char *table)
/* change any strings ("inf","nan",..) into NULL */
char *ptr = row[i];
if (opt_xml)
- fprintf(md_result_file, "\t\t<%s>%s</%s>\n",
+ fprintf(md_result_file, "\t\t<field name=\"%s\">%s</field>\n",
field->name,
- !my_isalpha(system_charset_info,*ptr) ?ptr: "NULL",field->name);
+ !my_isalpha(system_charset_info, *ptr) ? ptr: "NULL");
else
fputs((!my_isalpha(system_charset_info,*ptr)) ?
ptr : "NULL", md_result_file);
@@ -1105,8 +1114,8 @@ static void dumpTable(uint numFields, char *table)
else
{
if (opt_xml)
- fprintf(md_result_file, "\t\t<%s>%s</%s>\n",
- field->name, "NULL", field->name);
+ fprintf(md_result_file, "\t\t<field name=\"%s\">%s</field>\n",
+ field->name, "NULL");
else
fputs("NULL", md_result_file);
}
@@ -1147,7 +1156,7 @@ static void dumpTable(uint numFields, char *table)
/* XML - close table tag and supress regular output */
if (opt_xml)
- fprintf(md_result_file, "\t</%s>\n", table);
+ fprintf(md_result_file, "\t</table>\n");
else if (extended_insert && row_break)
fputs(";\n", md_result_file); /* If not empty table */
fflush(md_result_file);
@@ -1179,7 +1188,7 @@ static void print_quoted_xml(FILE *output, char *fname, char *str, uint len)
{
const char *end;
- fprintf(output, "\t\t<%s>", fname);
+ fprintf(output, "\t\t<field name=\"%s\">", fname);
for (end = str + len; str != end; str++)
{
if (*str == '<')
@@ -1193,7 +1202,7 @@ static void print_quoted_xml(FILE *output, char *fname, char *str, uint len)
else
fputc(*str, output);
}
- fprintf(output, "</%s>\n", fname);
+ fprintf(output, "</field>\n");
}
static char *getTableName(int reset)
@@ -1248,13 +1257,8 @@ static int dump_databases(char **db_names)
int result=0;
for ( ; *db_names ; db_names++)
{
- /* XML edit - add database element */
- if (opt_xml)
- fprintf(md_result_file, "<%s>\n", *db_names);
if (dump_all_tables_in_db(*db_names))
result=1;
- if (opt_xml)
- fprintf(md_result_file, "</%s>\n", *db_names);
}
return result;
} /* dump_databases */
@@ -1267,7 +1271,7 @@ static int init_dumping(char *database)
DBerror(sock, "when selecting the database");
return 1; /* If --force */
}
- if (!path)
+ if (!path && !opt_xml)
{
if (opt_databases || opt_alldbs)
{
@@ -1313,6 +1317,8 @@ static int dump_all_tables_in_db(char *database)
if (init_dumping(database))
return 1;
+ if (opt_xml)
+ fprintf(md_result_file, "<database name=\"%s\">\n", database);
if (lock_tables)
{
DYNAMIC_STRING query;
@@ -1339,6 +1345,8 @@ static int dump_all_tables_in_db(char *database)
if (!dFlag && numrows > 0)
dumpTable(numrows,table);
}
+ if (opt_xml)
+ fprintf(md_result_file, "</database>\n");
if (lock_tables)
mysql_query(sock,"UNLOCK_TABLES");
return 0;
@@ -1375,12 +1383,16 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
DBerror(sock, "when doing refresh");
/* We shall countinue here, if --force was given */
}
+ if (opt_xml)
+ fprintf(md_result_file, "<database name=\"%s\">\n", db);
for (; tables > 0 ; tables-- , table_names++)
{
numrows = getTableStructure(*table_names, db);
if (!dFlag && numrows > 0)
dumpTable(numrows, *table_names);
}
+ if (opt_xml)
+ fprintf(md_result_file, "</database>\n");
if (lock_tables)
mysql_query(sock,"UNLOCK_TABLES");
return 0;
@@ -1514,7 +1526,7 @@ int main(int argc, char **argv)
}
}
dbDisconnect(current_host);
- fputs("\n", md_result_file);
+ 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));
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index dc1d37b98f6..df624a02c55 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -56,6 +56,7 @@ static my_string opt_mysql_unix_port=0;
int main(int argc, char **argv)
{
int error;
+ my_bool first_argument_uses_wildcards=0;
char *wild;
MYSQL mysql;
MY_INIT(argv[0]);
@@ -63,21 +64,37 @@ int main(int argc, char **argv)
get_options(&argc,&argv);
wild=0;
- if (argc && strcont(argv[argc-1],"*?%_"))
+ if (argc)
{
- char *pos;
-
- wild=argv[--argc];
- for (pos=wild ; *pos ; pos++)
- { /* Unix wildcards to sql */
- if (*pos == '*')
- *pos='%';
- else if (*pos == '?')
- *pos='_';
- }
+ char *pos= argv[argc-1], *to;
+ for (to= pos ; *pos ; pos++, to++)
+ {
+ switch (*pos)
+ {
+ case '*':
+ *pos= '%';
+ first_argument_uses_wildcards= 1;
+ break;
+ case '?':
+ *pos= '_';
+ first_argument_uses_wildcards= 1;
+ break;
+ case '%':
+ case '_':
+ first_argument_uses_wildcards= 1;
+ break;
+ case '\\':
+ pos++;
+ default: break;
+ }
+ *to= *pos;
+ }
+ *to= *pos; // just to copy a '\0' if '\\' was used
}
+ if (first_argument_uses_wildcards)
+ wild= argv[--argc];
else if (argc == 3) /* We only want one field */
- wild=argv[--argc];
+ wild= argv[--argc];
if (argc > 2)
{
@@ -99,7 +116,7 @@ int main(int argc, char **argv)
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif
if (!(mysql_real_connect(&mysql,host,user,opt_password,
- argv[0],opt_mysql_port,opt_mysql_unix_port,
+ (first_argument_uses_wildcards) ? "" : argv[0],opt_mysql_port,opt_mysql_unix_port,
0)))
{
fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 036130f2d80..9d724404edc 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -91,7 +91,7 @@
enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
- OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT};
+ OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC};
static int record = 0, opt_sleep=0;
static char *db = 0, *pass=0;
@@ -1850,6 +1850,9 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"silent", 's', "Suppress all normal output. Synonym for --quiet.",
(gptr*) &silent, (gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"skip-safemalloc", OPT_SKIP_SAFEMALLOC,
+ "Don't use the memory allocation checking", 0, 0, 0, GET_NO_ARG, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"sleep", 'T', "Sleep always this many seconds on sleep commands",
(gptr*) &opt_sleep, (gptr*) &opt_sleep, 0, GET_INT, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
@@ -1949,6 +1952,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (read_server_arguments(argument))
die(NullS);
break;
+ case OPT_SKIP_SAFEMALLOC:
+#ifdef SAFEMALLOC
+ sf_malloc_quick=1;
+#endif
+ break;
case 'V':
print_version();
exit(0);
@@ -2323,6 +2331,7 @@ static void var_from_env(const char* name, const char* def_val)
static void init_var_hash()
{
VAR* v;
+ DBUG_ENTER("init_var_hash");
if (hash_init(&var_hash, system_charset_info,
1024, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
@@ -2332,6 +2341,7 @@ static void init_var_hash()
var_from_env("BIG_TEST", opt_big_test ? "1" : "0");
v=var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "63",0);
hash_insert(&var_hash, (byte*)v);
+ DBUG_VOID_RETURN;
}
diff --git a/configure.in b/configure.in
index 5de157a49c9..2ac8e050ae5 100644
--- a/configure.in
+++ b/configure.in
@@ -72,12 +72,14 @@ case $MACHINE_TYPE in
esac
# Save some variables and the command line options for mysqlbug
+SAVE_ASFLAGS="$ASFLAGS"
SAVE_CFLAGS="$CFLAGS"
SAVE_CXXFLAGS="$CXXFLAGS"
SAVE_LDFLAGS="$LDFLAGS"
SAVE_CXXLDFLAGS="$CXXLDFLAGS"
CONF_COMMAND="$0 $ac_configure_args"
AC_SUBST(CONF_COMMAND)
+AC_SUBST(SAVE_ASFLAGS)
AC_SUBST(SAVE_CFLAGS)
AC_SUBST(SAVE_CXXFLAGS)
AC_SUBST(SAVE_LDFLAGS)
@@ -602,8 +604,9 @@ AC_ARG_ENABLE(assembler,
AC_MSG_CHECKING(if we should use assembler functions)
# For now we only support assembler on i386 and sparc systems
AM_CONDITIONAL(ASSEMBLER_x86, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "i386")
-AM_CONDITIONAL(ASSEMBLER_sparc, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparc")
-AM_CONDITIONAL(ASSEMBLER, test "$ASSEMBLER_x86_TRUE" = "" -o "$ASSEMBLER_sparc_TRUE" = "")
+AM_CONDITIONAL(ASSEMBLER_sparc32, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparc")
+AM_CONDITIONAL(ASSEMBLER_sparc64, test "$ENABLE_ASSEMBLER" = "yes" -a "$BASE_MACHINE_TYPE" = "sparcv9")
+AM_CONDITIONAL(ASSEMBLER, test "$ASSEMBLER_x86_TRUE" = "" -o "$ASSEMBLER_sparc32_TRUE" = "")
if test "$ASSEMBLER_TRUE" = ""
then
@@ -674,7 +677,7 @@ else
AC_MSG_RESULT([no])
fi
-AC_SYS_LARGEFILE
+MYSQL_SYS_LARGEFILE
# Types that must be checked AFTER large file support is checked
AC_TYPE_SIZE_T
@@ -917,8 +920,8 @@ case $SYSTEM_TYPE in
;;
*hpux10.20*)
echo "Enabling workarounds for hpux 10.20"
- CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
- CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
+ CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
+ CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHPUX10 -DSIGNAL_WITH_VIO_CLOSE -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT -DHAVE_POSIX1003_4a_MUTEX"
if test "$with_named_thread" = "no"
then
echo "Using --with-named-thread=-lpthread"
@@ -927,13 +930,19 @@ case $SYSTEM_TYPE in
;;
*hpux11.*)
echo "Enabling workarounds for hpux 11"
- CFLAGS="$CFLAGS -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
- CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
+ CFLAGS="$CFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
+ CXXFLAGS="$CXXFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
if test "$with_named_thread" = "no"
then
echo "Using --with-named-thread=-lpthread"
with_named_thread="-lpthread"
fi
+ # Fixes for HPUX 11.0 compiler
+ if test "$ac_cv_prog_gcc" = "no"
+ then
+ CFLAGS="$CFLAGS +DD64 -DHAVE_BROKEN_INLINE"
+ CXXFLAGS="$CXXFLAGS +DD64 +O2"
+ fi
;;
*rhapsody*)
if test "$ac_cv_prog_gcc" = "yes"
@@ -966,7 +975,8 @@ case $SYSTEM_TYPE in
;;
*freebsd*)
echo "Adding fix for interrupted reads"
- CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000"
+ CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
+ CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
;;
*netbsd*)
echo "Adding flag -Dunix"
diff --git a/dbug/dbug_add_tags.pl b/dbug/dbug_add_tags.pl
new file mode 100755
index 00000000000..141a2ed85f1
--- /dev/null
+++ b/dbug/dbug_add_tags.pl
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+
+die "No files specified\n" unless $ARGV[0];
+
+$ctags="exctags -x -f - --c-types=f -u";
+
+sub get_tag {
+ local $.; local $_=<TAGS>;
+ ($symbol, $line)= /^(.*\S)\s+function\s+(\d+)/;
+ $symbol=$1 if /\s(\S+)\s*\(/;
+ $line=1e50 unless $line;
+}
+
+while($src=shift)
+{
+ warn "==> $src\n";
+
+ $dst=$src.$$;
+ open(TAGS, "$ctags $src|") || die "Cannot exec('$ctags $src'): $!";
+ open(SRC, "<$src") || die "Cannot open $src: $!";
+ open(DST, ">$dst") || die "Cannot create $dst: $!";
+ select DST;
+
+ &get_tag;
+ $in_func=0;
+ while(<SRC>)
+ {
+ my $orig=$_;
+ if ($in_func)
+ {
+ if (/\breturn\b/ && !/\/\*.*\breturn\b.*\*\// && !/;/ )
+ {
+ $_.=<SRC> until /;/;
+ }
+ s/(?<=\s)return\s*;/DBUG_VOID_RETURN;/;
+ s/(?<=\s)return\s*(.+)\s*;/DBUG_RETURN(\1);/s;
+ $ret_line=$. if /DBUG_(VOID_)?RETURN/; #{{
+ print "$tab DBUG_VOID_RETURN;\n" if /^$tab}/ && $ret_line < $.-1;
+ $in_func=0 if /^$tab}/;
+ warn "$src:".($.-1)."\t$orig" if /\breturn\b/;
+ }
+ print;
+ next if $. < $line;
+ die "Something wrong: \$.=$., \$line=$line, \$symbol=$symbol\n" if $. > $line;
+ &get_tag && next if /^\s*inline /;
+ print $_=<SRC> until /{/; $tab=$`;
+ &get_tag && next if /}/; # skip one-liners
+ $semicolon=1;
+ while(<SRC>)
+ {
+ $skip=!$semicolon;
+ $semicolon= /;\s*$/;
+ print && next if $skip ||
+ (/^\s+\w+((::\w+)?|<\w+>)\s+\**\w+/ && !/^\s*return/);
+ last if /DBUG_ENTER/;
+ print "$tab DBUG_ENTER(\"$symbol\");\n";
+ print "\n" unless $_ eq "\n";
+ last;
+ }
+ $in_func=1;
+ &get_tag;
+ redo;
+ }
+ close SRC;
+ close DST;
+ close TAGS;
+ unlink("$src.orig");
+ rename($src, "$src.orig") || die "Cannot rename $src to $src.orig: $!";
+ rename($dst, $src) || die "Cannot rename $dst to $src: $!";
+}
+
+warn "All done!\n";
+
diff --git a/extra/Makefile.am b/extra/Makefile.am
index 58776144489..2d7dc95f616 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -18,7 +18,7 @@ INCLUDES = @MT_INCLUDES@ -I$(srcdir)/../include -I../include -I..
LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
-resolve_stack_dump mysql_install
+ resolve_stack_dump mysql_install
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/include/errmsg.h b/include/errmsg.h
index 5ac5ef9a4a7..703395a3742 100644
--- a/include/errmsg.h
+++ b/include/errmsg.h
@@ -61,26 +61,27 @@ extern const char *client_errors[]; /* Error messages */
#define CR_PROBE_SLAVE_HOSTS 2023
#define CR_PROBE_SLAVE_CONNECT 2024
#define CR_PROBE_MASTER_CONNECT 2025
+#define CR_SSL_CONNECTION_ERROR 2026
/* new 4.1 error codes */
-#define CR_INVALID_CONN_HANDLE 2026
-#define CR_NULL_POINTER 2027
-#define CR_NO_PREPARE_STMT 2028
-#define CR_NOT_ALL_PARAMS_BOUND 2029
-#define CR_DATA_TRUNCATED 2030
-#define CR_NO_PARAMETERS_EXISTS 2031
-#define CR_INVALID_PARAMETER_NO 2032
-#define CR_INVALID_BUFFER_USE 2033
-#define CR_UNSUPPORTED_PARAM_TYPE 2034
+#define CR_INVALID_CONN_HANDLE 2027
+#define CR_NULL_POINTER 2028
+#define CR_NO_PREPARE_STMT 2029
+#define CR_NOT_ALL_PARAMS_BOUND 2030
+#define CR_DATA_TRUNCATED 2031
+#define CR_NO_PARAMETERS_EXISTS 2032
+#define CR_INVALID_PARAMETER_NO 2033
+#define CR_INVALID_BUFFER_USE 2034
+#define CR_UNSUPPORTED_PARAM_TYPE 2035
-#define CR_SHARED_MEMORY_CONNECTION 2035
-#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2036
-#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2037
-#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2038
-#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2039
-#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2040
-#define CR_SHARED_MEMORY_MAP_ERROR 2041
-#define CR_SHARED_MEMORY_EVENT_ERROR 2042
-#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2043
-#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046
-#define CR_CONN_UNKNOW_PROTOCOL 2048
+#define CR_SHARED_MEMORY_CONNECTION 2036
+#define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2037
+#define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2038
+#define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2039
+#define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2040
+#define CR_SHARED_MEMORY_FILE_MAP_ERROR 2041
+#define CR_SHARED_MEMORY_MAP_ERROR 2042
+#define CR_SHARED_MEMORY_EVENT_ERROR 2043
+#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2044
+#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2045
+#define CR_CONN_UNKNOW_PROTOCOL 2046
diff --git a/include/my_alloc.h b/include/my_alloc.h
index 31f1fb7165f..a3dd35d7ea3 100644
--- a/include/my_alloc.h
+++ b/include/my_alloc.h
@@ -21,7 +21,8 @@
#ifndef _my_alloc_h
#define _my_alloc_h
-#define MAX_BLOCK_USAGE_BEFORE_DROP 10
+#define ALLOC_MAX_BLOCK_TO_DROP 4096
+#define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10
typedef struct st_used_mem
{ /* struct for once_alloc (block) */
diff --git a/include/my_base.h b/include/my_base.h
index 7e1df17b69d..b4e39952f22 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -301,8 +301,10 @@ enum data_file_type {
/* For number of records */
#ifdef BIG_TABLES
+#define rows2double(A) ulonglong2double(A)
typedef my_off_t ha_rows;
#else
+#define rows2double(A) (double) (A)
typedef ulong ha_rows;
#endif
diff --git a/include/my_global.h b/include/my_global.h
index d1b3c516555..749a326f86f 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -38,6 +38,14 @@
#define HAVE_ERRNO_AS_DEFINE
#endif /* __CYGWIN__ */
+/* Macros to make switching between C and C++ mode easier */
+#ifdef __cplusplus
+#define C_MODE_START extern "C" {
+#define C_MODE_END }
+#else
+#define C_MODE_START
+#define C_MODE_END
+#endif
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#include <config-win.h>
@@ -119,7 +127,12 @@
#define _H_STRINGS
#define _SYS_STREAM_H
/* #define _AIX32_CURSES */ /* XXX: this breaks AIX 4.3.3 (others?). */
-#endif
+#define ulonglong2double(A) my_ulonglong2double(A)
+#define my_off_t2double(A) my_ulonglong2double(A)
+C_MODE_START
+double my_ulonglong2double(unsigned long long A);
+C_MODE_END
+#endif /* _AIX */
#ifdef HAVE_BROKEN_SNPRINTF /* HPUX 10.20 don't have this defined */
#undef HAVE_SNPRINTF
@@ -128,6 +141,10 @@
#undef HAVE_PREAD
#undef HAVE_PWRITE
#endif
+#if defined(HAVE_BROKEN_INLINE) && !defined(__cplusplus)
+#undef inline
+#define inline
+#endif
#ifdef UNDEF_HAVE_GETHOSTBYNAME_R /* For OSF4.x */
#undef HAVE_GETHOSTBYNAME_R
@@ -240,7 +257,7 @@
#ifdef DONT_USE_FINITE /* HPUX 11.x has is_finite() */
#undef HAVE_FINITE
#endif
-#if defined(HPUX) && defined(_LARGEFILE64_SOURCE) && defined(THREAD)
+#if defined(HPUX10) && defined(_LARGEFILE64_SOURCE) && defined(THREAD)
/* Fix bug in setrlimit */
#undef setrlimit
#define setrlimit cma_setrlimit64
@@ -376,7 +393,9 @@ typedef int my_socket; /* File descriptor for sockets */
#endif
/* Type for fuctions that handles signals */
#define sig_handler RETSIGTYPE
+C_MODE_START
typedef void (*sig_return)();/* Returns type from signal */
+C_MODE_END
#if defined(__GNUC__) && !defined(_lint)
typedef char pchar; /* Mixed prototypes can take char */
typedef char puchar; /* Mixed prototypes can take char */
@@ -390,8 +409,10 @@ typedef int pbool; /* Mixed prototypes can't take char */
typedef int pshort; /* Mixed prototypes can't take short int */
typedef double pfloat; /* Mixed prototypes can't take float */
#endif
+C_MODE_START
typedef int (*qsort_cmp)(const void *,const void *);
typedef int (*qsort_cmp2)(void*, const void *,const void *);
+C_MODE_END
#ifdef HAVE_mit_thread
#define qsort_t void
#undef QSORT_TYPE_IS_VOID
@@ -1029,13 +1050,4 @@ typedef union {
#define statistic_add(V,C,L) (V)+=(C)
#endif
-/* Macros to make switching between C and C++ mode easier */
-#ifdef __cplusplus
-#define C_MODE_START extern "C" {
-#define C_MODE_END }
-#else
-#define C_MODE_START
-#define C_MODE_END
-#endif
-
-#endif /* _global_h */
+#endif /* my_global_h */
diff --git a/include/my_net.h b/include/my_net.h
index 2f5743923cf..ec985ded76b 100644
--- a/include/my_net.h
+++ b/include/my_net.h
@@ -71,7 +71,7 @@ void my_inet_ntoa(struct in_addr in, char *buf);
Handling of gethostbyname_r()
*/
-#if !defined(HPUX)
+#if !defined(HPUX10)
struct hostent;
#endif /* HPUX */
#if !defined(HAVE_GETHOSTBYNAME_R)
@@ -84,7 +84,7 @@ struct hostent *my_gethostbyname_r(const char *name,
struct hostent *result, char *buffer,
int buflen, int *h_errnop);
#define my_gethostbyname_r_free()
-#if !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) && !defined(HPUX)
+#if !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) && !defined(HPUX10)
#define GETHOSTBYNAME_BUFF_SIZE sizeof(struct hostent_data)
#endif /* !defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) */
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 9b7812b7cf2..f75ca8f601a 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -428,7 +428,7 @@ struct tm *localtime_r(const time_t *clock, struct tm *res);
#endif /* defined(__WIN__) */
-#if defined(HPUX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
+#if defined(HPUX10) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
#undef pthread_cond_timedwait
#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c))
int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
diff --git a/include/my_tree.h b/include/my_tree.h
index 99194907ef9..0e705e19bba 100644
--- a/include/my_tree.h
+++ b/include/my_tree.h
@@ -83,7 +83,6 @@ void *tree_search(TREE *tree, void *key, void *custom_arg);
int tree_walk(TREE *tree,tree_walk_action action,
void *argument, TREE_WALK visit);
int tree_delete(TREE *tree, void *key, void *custom_arg);
-
void *tree_search_key(TREE *tree, const void *key,
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
enum ha_rkey_function flag, void *custom_arg);
@@ -93,6 +92,9 @@ void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs,
int r_offs);
ha_rows tree_record_pos(TREE *tree, const void *key,
enum ha_rkey_function search_flag, void *custom_arg);
+
+#define TREE_ELEMENT_EXTRA_SIZE (sizeof(TREE_ELEMENT) + sizeof(void*))
+
#ifdef __cplusplus
}
#endif
diff --git a/include/myisam.h b/include/myisam.h
index acaf8bb7618..f11b18824d5 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -285,7 +285,7 @@ extern uint mi_get_pointer_length(ulonglong file_length, uint def);
#define T_VERBOSE (1L << 28)
#define T_VERY_SILENT (1L << 29)
#define T_WAIT_FOREVER (1L << 30)
-#define T_WRITE_LOOP (1L << 31)
+#define T_WRITE_LOOP ((ulong) 1L << 31)
#define T_REP_ANY (T_REP | T_REP_BY_SORT | T_REP_PARALLEL)
diff --git a/include/myisampack.h b/include/myisampack.h
index 51c9876c246..95793e2aaeb 100644
--- a/include/myisampack.h
+++ b/include/myisampack.h
@@ -214,7 +214,7 @@
#ifdef BIG_TABLES
#define mi_rowstore(T,A) mi_int8store(T,A)
-#define mi_rowkorr(T) mi_uint8korr(T)
+#define mi_rowkorr(T) mi_uint8korr(T)
#else
#define mi_rowstore(T,A) { mi_int4store(T,0); mi_int4store(((T)+4),A); }
#define mi_rowkorr(T) mi_uint4korr((T)+4)
diff --git a/include/queues.h b/include/queues.h
index 70cb99a1513..699705d0869 100644
--- a/include/queues.h
+++ b/include/queues.h
@@ -41,12 +41,13 @@ typedef struct st_queue {
#define queue_element(queue,index) ((queue)->root[index+1])
#define queue_end(queue) ((queue)->root[(queue)->elements])
#define queue_replaced(queue) _downheap(queue,1)
+typedef int (*queue_compare)(void *,byte *, byte *);
int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
- pbool max_at_top, int (*compare)(void *,byte *, byte *),
+ pbool max_at_top, queue_compare compare,
void *first_cmp_arg);
int reinit_queue(QUEUE *queue,uint max_elements,uint offset_to_key,
- pbool max_at_top, int (*compare)(void *,byte *, byte *),
+ pbool max_at_top, queue_compare compare,
void *first_cmp_arg);
void delete_queue(QUEUE *queue);
void queue_insert(QUEUE *queue,byte *element);
diff --git a/include/violite.h b/include/violite.h
index d73328b72be..b8bfb2183a2 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -188,7 +188,7 @@ struct st_VioSSLConnectorFd
SSL_METHOD* ssl_method_;
};
-void sslaccept(struct st_VioSSLAcceptorFd*, Vio*, long timeout);
+int sslaccept(struct st_VioSSLAcceptorFd*, Vio*, long timeout);
int sslconnect(struct st_VioSSLConnectorFd*, Vio*, long timeout);
struct st_VioSSLConnectorFd
@@ -245,7 +245,6 @@ struct st_vio
#ifdef HAVE_OPENSSL
SSL* ssl_;
- my_bool open_;
#endif /* HAVE_OPENSSL */
#ifdef HAVE_SMEM
HANDLE handle_file_map;
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index 7a7678b2dcf..a1665aefab7 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -274,6 +274,7 @@ btr_page_create(
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
page_create(page, mtr);
+ buf_block_align(page)->check_index_page_at_flush = TRUE;
btr_page_set_index_id(page, tree->id, mtr);
}
@@ -713,6 +714,7 @@ btr_create(
/* Create a new index page on the the allocated segment page */
page = page_create(frame, mtr);
+ buf_block_align(page)->check_index_page_at_flush = TRUE;
/* Set the index id of the page */
btr_page_set_index_id(page, index_id, mtr);
@@ -847,6 +849,7 @@ btr_page_reorganize_low(
segment headers, next page-field, etc.) is preserved intact */
page_create(page, mtr);
+ buf_block_align(page)->check_index_page_at_flush = TRUE;
/* Copy the records from the temporary space to the recreated page;
do not copy the lock bits yet */
@@ -919,6 +922,7 @@ btr_page_empty(
segment headers, next page-field, etc.) is preserved intact */
page_create(page, mtr);
+ buf_block_align(page)->check_index_page_at_flush = TRUE;
}
/*****************************************************************
@@ -2291,29 +2295,54 @@ btr_check_node_ptr(
/****************************************************************
Checks the size and number of fields in a record based on the definition of
the index. */
-static
+
ibool
btr_index_rec_validate(
/*====================*/
- /* out: TRUE if ok */
- rec_t* rec, /* in: index record */
- dict_index_t* index) /* in: index */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: index record */
+ dict_index_t* index, /* in: index */
+ ibool dump_on_error) /* in: TRUE if the function
+ should print hex dump of record
+ and page on error */
{
dtype_t* type;
byte* data;
ulint len;
ulint n;
ulint i;
+ page_t* page;
char err_buf[1000];
+
+ page = buf_frame_align(rec);
+ if (index->type & DICT_UNIVERSAL) {
+ /* The insert buffer index tree can contain records from any
+ other index: we cannot check the number of fields or
+ their length */
+
+ return(TRUE);
+ }
+
n = dict_index_get_n_fields(index);
if (rec_get_n_fields(rec) != n) {
- fprintf(stderr, "Record has %lu fields, should have %lu\n",
- rec_get_n_fields(rec), n);
+ fprintf(stderr,
+"InnoDB: Record in index %s in table %s, page %lu, at offset %lu\n"
+"InnoDB: has %lu fields, should have %lu\n",
+ index->name, index->table_name,
+ buf_frame_get_page_no(page), (ulint)(rec - page),
+ rec_get_n_fields(rec), n);
+
+ if (!dump_on_error) {
+
+ return(FALSE);
+ }
+
+ buf_page_print(page);
rec_sprintf(err_buf, 900, rec);
- fprintf(stderr, "InnoDB: record %s\n", err_buf);
+ fprintf(stderr, "InnoDB: corrupt record %s\n", err_buf);
return(FALSE);
}
@@ -2324,13 +2353,25 @@ btr_index_rec_validate(
type = dict_index_get_nth_type(index, i);
if (len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
- && len != dtype_get_fixed_size(type)) {
+ && len != dtype_get_fixed_size(type)) {
fprintf(stderr,
- "Record field %lu len is %lu, should be %lu\n",
+"InnoDB: Record in index %s in table %s, page %lu, at offset %lu\n"
+"InnoDB: field %lu len is %lu, should be %lu\n",
+ index->name, index->table_name,
+ buf_frame_get_page_no(page),
+ (ulint)(rec - page),
i, len, dtype_get_fixed_size(type));
+ if (!dump_on_error) {
+
+ return(FALSE);
+ }
+
+ buf_page_print(page);
+
rec_sprintf(err_buf, 900, rec);
- fprintf(stderr, "InnoDB: record %s\n", err_buf);
+ fprintf(stderr,
+ "InnoDB: corrupt record %s\n", err_buf);
return(FALSE);
}
@@ -2361,12 +2402,13 @@ btr_index_page_validate(
rec = (&cur)->rec;
if (page_cur_is_after_last(&cur)) {
+
break;
}
- if (!btr_index_rec_validate(rec, index)) {
+ if (!btr_index_rec_validate(rec, index, TRUE)) {
- ret = FALSE;
+ return(FALSE);
}
page_cur_move_to_next(&cur);
@@ -2423,25 +2465,26 @@ btr_validate_level(
index = UT_LIST_GET_FIRST(tree->tree_indexes);
- /* Now we are on the desired level */
+ /* Now we are on the desired level. Loop through the pages on that
+ level. */
loop:
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
/* Check ordering etc. of records */
if (!page_validate(page, index)) {
- fprintf(stderr, "Error in page %lu in index %s\n",
- buf_frame_get_page_no(page), index->name);
+ fprintf(stderr,
+"InnoDB: Error in page %lu in index %s table %s, index tree level %lu\n",
+ buf_frame_get_page_no(page), index->name,
+ index->table_name, level);
ret = FALSE;
- }
+ } else if (level == 0) {
+ /* We are on level 0. Check that the records have the right
+ number of fields, and field lengths are right. */
- if (level == 0) {
if (!btr_index_page_validate(page, index)) {
- fprintf(stderr,
- "Error in page %lu in index %s, level %lu\n",
- buf_frame_get_page_no(page), index->name,
- level);
+
ret = FALSE;
}
}
@@ -2464,14 +2507,17 @@ loop:
UT_LIST_GET_FIRST(tree->tree_indexes)) >= 0) {
fprintf(stderr,
- "InnoDB: Error on pages %lu and %lu in index %s\n",
+ "InnoDB: Error on pages %lu and %lu in index %s table %s\n",
buf_frame_get_page_no(page),
right_page_no,
- index->name);
+ index->name, index->table_name);
fprintf(stderr,
"InnoDB: records in wrong order on adjacent pages\n");
+ buf_page_print(page);
+ buf_page_print(right_page);
+
rec_sprintf(err_buf, 900,
page_rec_get_prev(page_get_supremum_rec(page)));
fprintf(stderr, "InnoDB: record %s\n", err_buf);
@@ -2494,6 +2540,7 @@ loop:
/* Check father node pointers */
node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr);
+ father_page = buf_frame_align(node_ptr);
if (btr_node_ptr_get_child_page_no(node_ptr) !=
buf_frame_get_page_no(page)
@@ -2501,13 +2548,16 @@ loop:
page_rec_get_prev(page_get_supremum_rec(page)),
&mtr)) {
fprintf(stderr,
- "InnoDB: Error on page %lu in index %s\n",
+ "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page),
- index->name);
+ index->name, index->table_name);
fprintf(stderr,
"InnoDB: node pointer to the page is wrong\n");
+ buf_page_print(father_page);
+ buf_page_print(page);
+
rec_sprintf(err_buf, 900, node_ptr);
fprintf(stderr, "InnoDB: node ptr %s\n", err_buf);
@@ -2528,8 +2578,6 @@ loop:
goto node_ptr_fails;
}
- father_page = buf_frame_align(node_ptr);
-
if (btr_page_get_level(page, &mtr) > 0) {
heap = mem_heap_create(256);
@@ -2543,9 +2591,12 @@ loop:
if (cmp_dtuple_rec(node_ptr_tuple, node_ptr) != 0) {
fprintf(stderr,
- "InnoDB: Error on page %lu in index %s\n",
+ "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page),
- index->name);
+ index->name, index->table_name);
+
+ buf_page_print(father_page);
+ buf_page_print(page);
fprintf(stderr,
"InnoDB: Error: node ptrs differ on levels > 0\n");
@@ -2595,9 +2646,13 @@ loop:
"InnoDB: node pointer to the right page is wrong\n");
fprintf(stderr,
- "InnoDB: Error on page %lu in index %s\n",
+ "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page),
- index->name);
+ index->name, index->table_name);
+
+ buf_page_print(father_page);
+ buf_page_print(page);
+ buf_page_print(right_page);
}
} else {
right_father_page = buf_frame_align(
@@ -2611,9 +2666,14 @@ loop:
"InnoDB: node pointer 2 to the right page is wrong\n");
fprintf(stderr,
- "InnoDB: Error on page %lu in index %s\n",
+ "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page),
- index->name);
+ index->name, index->table_name);
+
+ buf_page_print(father_page);
+ buf_page_print(right_father_page);
+ buf_page_print(page);
+ buf_page_print(right_page);
}
if (buf_frame_get_page_no(right_father_page)
@@ -2624,9 +2684,14 @@ loop:
"InnoDB: node pointer 3 to the right page is wrong\n");
fprintf(stderr,
- "InnoDB: Error on page %lu in index %s\n",
+ "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page),
- index->name);
+ index->name, index->table_name);
+
+ buf_page_print(father_page);
+ buf_page_print(right_father_page);
+ buf_page_print(page);
+ buf_page_print(right_page);
}
}
}
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 3d6b63def6c..24f0447d55d 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -121,16 +121,19 @@ btr_cur_latch_leaves(
{
ulint left_page_no;
ulint right_page_no;
-
+ page_t* get_page;
+
ut_ad(tree && page && mtr);
if (latch_mode == BTR_SEARCH_LEAF) {
- btr_page_get(space, page_no, RW_S_LATCH, mtr);
+ get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr);
+ buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_LEAF) {
- btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_TREE) {
@@ -138,15 +141,22 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
- btr_page_get(space, left_page_no, RW_X_LATCH, mtr);
+ get_page = btr_page_get(space, left_page_no,
+ RW_X_LATCH, mtr);
+ buf_block_align(get_page)->check_index_page_at_flush =
+ TRUE;
}
- btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ buf_block_align(get_page)->check_index_page_at_flush = TRUE;
right_page_no = btr_page_get_next(page, mtr);
if (right_page_no != FIL_NULL) {
- btr_page_get(space, right_page_no, RW_X_LATCH, mtr);
+ get_page = btr_page_get(space, right_page_no,
+ RW_X_LATCH, mtr);
+ buf_block_align(get_page)->check_index_page_at_flush =
+ TRUE;
}
} else if (latch_mode == BTR_SEARCH_PREV) {
@@ -157,9 +167,12 @@ btr_cur_latch_leaves(
if (left_page_no != FIL_NULL) {
cursor->left_page = btr_page_get(space, left_page_no,
RW_S_LATCH, mtr);
+ buf_block_align(
+ cursor->left_page)->check_index_page_at_flush = TRUE;
}
- btr_page_get(space, page_no, RW_S_LATCH, mtr);
+ get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr);
+ buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_PREV) {
@@ -169,9 +182,12 @@ btr_cur_latch_leaves(
if (left_page_no != FIL_NULL) {
cursor->left_page = btr_page_get(space, left_page_no,
RW_X_LATCH, mtr);
+ buf_block_align(
+ cursor->left_page)->check_index_page_at_flush = TRUE;
}
- btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else {
ut_error;
}
@@ -274,6 +290,7 @@ btr_cur_search_to_nth_level(
if (btr_search_latch.writer == RW_LOCK_NOT_LOCKED
&& latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ
&& !estimate
+ && mode != PAGE_CUR_LE_OR_EXTENDS
&& btr_search_guess_on_hash(index, info, tuple, mode,
latch_mode, cursor,
has_search_latch, mtr)) {
@@ -334,12 +351,18 @@ btr_cur_search_to_nth_level(
rw_latch = RW_NO_LATCH;
buf_mode = BUF_GET;
+ /* We use these modified search modes on non-leaf levels of the
+ B-tree. These let us end up in the right B-tree leaf. In that leaf
+ we use the original search mode. */
+
if (mode == PAGE_CUR_GE) {
page_mode = PAGE_CUR_L;
} else if (mode == PAGE_CUR_G) {
page_mode = PAGE_CUR_LE;
} else if (mode == PAGE_CUR_LE) {
page_mode = PAGE_CUR_LE;
+ } else if (mode == PAGE_CUR_LE_OR_EXTENDS) {
+ page_mode = PAGE_CUR_LE_OR_EXTENDS;
} else {
ut_ad(mode == PAGE_CUR_L);
page_mode = PAGE_CUR_L;
@@ -390,6 +413,8 @@ retry_page_get:
goto retry_page_get;
}
+
+ buf_block_align(page)->check_index_page_at_flush = TRUE;
#ifdef UNIV_SYNC_DEBUG
if (rw_latch != RW_NO_LATCH) {
@@ -543,6 +568,8 @@ btr_cur_open_at_index_side(
ut_ad(0 == ut_dulint_cmp(tree->id,
btr_page_get_index_id(page)));
+ buf_block_align(page)->check_index_page_at_flush = TRUE;
+
if (height == ULINT_UNDEFINED) {
/* We are in the root node */
diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c
index 8ca3d41f7f9..b2115dfdd6c 100644
--- a/innobase/btr/btr0pcur.c
+++ b/innobase/btr/btr0pcur.c
@@ -354,6 +354,7 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr);
+ buf_block_align(next_page)->check_index_page_at_flush = TRUE;
btr_leaf_page_release(page, cursor->latch_mode, mtr);
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index ee8e8b91f8d..c9a5ec5307f 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -331,6 +331,11 @@ buf_page_print(
index->table_name,
index->name);
}
+ } else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) {
+ fprintf(stderr, "InnoDB: Page may be an 'inode' page\n");
+ } else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) {
+ fprintf(stderr,
+ "InnoDB: Page may be an insert buffer free list page\n");
}
}
@@ -351,6 +356,8 @@ buf_block_init(
block->file_page_was_freed = FALSE;
+ block->check_index_page_at_flush = FALSE;
+
rw_lock_create(&(block->lock));
ut_ad(rw_lock_validate(&(block->lock)));
@@ -617,6 +624,29 @@ buf_page_peek_block(
}
/************************************************************************
+Resets the check_index_page_at_flush field of a page if found in the buffer
+pool. */
+
+void
+buf_reset_check_index_page_at_flush(
+/*================================*/
+ ulint space, /* in: space id */
+ ulint offset) /* in: page number */
+{
+ buf_block_t* block;
+
+ mutex_enter_fast(&(buf_pool->mutex));
+
+ block = buf_page_hash_get(space, offset);
+
+ if (block) {
+ block->check_index_page_at_flush = FALSE;
+ }
+
+ mutex_exit(&(buf_pool->mutex));
+}
+
+/************************************************************************
Returns the current state of is_hashed of a page. FALSE if the page is
not in the pool. NOTE that this operation does not fix the page in the
pool if it is found there. */
@@ -1185,6 +1215,8 @@ buf_page_init(
block->space = space;
block->offset = offset;
+ block->check_index_page_at_flush = FALSE;
+
block->lock_hash_val = lock_rec_hash(space, offset);
block->lock_mutex = NULL;
@@ -1325,11 +1357,6 @@ buf_page_create(
ut_ad(mtr);
free_block = buf_LRU_get_free_block();
-
- /* Delete possible entries for the page from the insert buffer:
- such can exist if the page belonged to an index which was dropped */
-
- ibuf_merge_or_delete_for_page(NULL, space, offset);
mutex_enter(&(buf_pool->mutex));
@@ -1378,6 +1405,11 @@ buf_page_create(
mutex_exit(&(buf_pool->mutex));
+ /* Delete possible entries for the page from the insert buffer:
+ such can exist if the page belonged to an index which was dropped */
+
+ ibuf_merge_or_delete_for_page(NULL, space, offset);
+
/* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin();
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index 4c6850af078..78bde60c9b2 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -15,6 +15,7 @@ Created 11/11/1995 Heikki Tuuri
#include "ut0byte.h"
#include "ut0lst.h"
+#include "page0page.h"
#include "fil0fil.h"
#include "buf0buf.h"
#include "buf0lru.h"
@@ -225,6 +226,24 @@ buf_flush_buffered_writes(void)
return;
}
+ for (i = 0; i < trx_doublewrite->first_free; i++) {
+ block = trx_doublewrite->buf_block_arr[i];
+
+ if (block->check_index_page_at_flush
+ && !page_simple_validate(block->frame)) {
+
+ buf_page_print(block->frame);
+
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Apparent corruption of an index page\n"
+ "InnoDB: to be written to data file. We intentionally crash server\n"
+ "InnoDB: to prevent corrupt data from ending up in data\n"
+ "InnoDB: files.\n");
+ ut_a(0);
+ }
+ }
+
if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
len = TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
} else {
diff --git a/innobase/configure.in b/innobase/configure.in
index 761859e5da3..59d213fef12 100644
--- a/innobase/configure.in
+++ b/innobase/configure.in
@@ -86,6 +86,8 @@ else
fi
case "$target_os" in
+ lin*)
+ CFLAGS="$CFLAGS -DUNIV_LINUX";;
hpux10*)
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
hp*)
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index 60beeacf435..b0f84e5663a 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -1041,7 +1041,7 @@ dict_create_or_check_foreign_constraint_tables(void)
que_t* graph;
ulint error;
trx_t* trx;
- char* str;
+ char* str;
mutex_enter(&(dict_sys->mutex));
@@ -1060,20 +1060,24 @@ dict_create_or_check_foreign_constraint_tables(void)
return(DB_SUCCESS);
}
+ mutex_exit(&(dict_sys->mutex));
+
trx = trx_allocate_for_mysql();
trx->op_info = (char *) "creating foreign key sys tables";
+ row_mysql_lock_data_dictionary(trx);
+
if (table1) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN table\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
}
if (table2) {
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN_COLS table\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
}
fprintf(stderr,
@@ -1122,8 +1126,8 @@ dict_create_or_check_foreign_constraint_tables(void)
fprintf(stderr,
"InnoDB: dropping incompletely created SYS_FOREIGN tables\n");
- row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx, TRUE);
- row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS",trx,TRUE);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN", trx);
+ row_drop_table_for_mysql((char *) "SYS_FOREIGN_COLS", trx);
error = DB_MUST_GET_MORE_FILE_SPACE;
}
@@ -1132,6 +1136,8 @@ dict_create_or_check_foreign_constraint_tables(void)
trx->op_info = (char *) "";
+ row_mysql_unlock_data_dictionary(trx);
+
trx_free_for_mysql(trx);
if (error == DB_SUCCESS) {
@@ -1139,8 +1145,6 @@ dict_create_or_check_foreign_constraint_tables(void)
"InnoDB: Foreign key constraint system tables created\n");
}
- mutex_exit(&(dict_sys->mutex));
-
return(error);
}
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 095c27f1c5f..18f27602cf0 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -29,7 +29,17 @@ Created 1/8/1996 Heikki Tuuri
dict_sys_t* dict_sys = NULL; /* the dictionary system */
-rw_lock_t dict_foreign_key_check_lock;
+rw_lock_t dict_operation_lock; /* table create, drop, etc. reserve
+ this in X-mode; implicit or backround
+ operations purge, rollback, foreign
+ key checks reserve this in S-mode; we
+ cannot trust that MySQL protects
+ implicit or background operations
+ a table drop since MySQL does not
+ know of them; therefore we need this;
+ NOTE: a transaction which reserves
+ this must keep book on the mode in
+ trx->dict_operation_lock_mode */
#define DICT_HEAP_SIZE 100 /* initial memory heap size when
creating a table or index object */
@@ -176,6 +186,58 @@ dict_foreign_free(
dict_foreign_t* foreign); /* in, own: foreign key struct */
/************************************************************************
+Checks if the database name in two table names is the same. */
+static
+ibool
+dict_tables_have_same_db(
+/*=====================*/
+ /* out: TRUE if same db name */
+ char* name1, /* in: table name in the form dbname '/' tablename */
+ char* name2) /* in: table name in the form dbname '/' tablename */
+{
+ ulint i;
+
+ for (i = 0; i < 100000; i++) {
+ if (name1[i] == '/' && name2[i] == '/') {
+
+ return(TRUE);
+ }
+
+ if (name1[i] != name2[i]) {
+
+ return(FALSE);
+ }
+ }
+
+ ut_a(0);
+
+ return(FALSE);
+}
+
+/************************************************************************
+Return the end of table name where we have removed dbname and '/'. */
+static
+char*
+dict_remove_db_name(
+/*================*/
+ /* out: table name */
+ char* name) /* in: table name in the form dbname '/' tablename */
+{
+ ulint i;
+
+ for (i = 0; i < 100000 ; i++) {
+ if (name[i] == '/') {
+
+ return(name + i + 1);
+ }
+ }
+
+ ut_a(0);
+
+ return(NULL);
+}
+
+/************************************************************************
Reserves the dictionary system mutex for MySQL. */
void
@@ -509,9 +571,8 @@ dict_init(void)
UT_LIST_INIT(dict_sys->table_LRU);
- rw_lock_create(&dict_foreign_key_check_lock);
- rw_lock_set_level(&dict_foreign_key_check_lock,
- SYNC_FOREIGN_KEY_CHECK);
+ rw_lock_create(&dict_operation_lock);
+ rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
}
/**************************************************************************
@@ -1851,14 +1912,14 @@ loop:
/*************************************************************************
Accepts a specified string. Comparisons are case-insensitive. */
-static
+
char*
dict_accept(
/*========*/
/* out: if string was accepted, the pointer
is moved after that, else ptr is returned */
char* ptr, /* in: scan from this */
- const char* string, /* in: accept only this string as the next
+ const char* string,/* in: accept only this string as the next
non-whitespace string */
ibool* success)/* out: TRUE if accepted */
{
@@ -1920,7 +1981,8 @@ dict_scan_col(
old_ptr = ptr;
- while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`') {
+ while (!isspace(*ptr) && *ptr != ',' && *ptr != ')' && *ptr != '`'
+ && *ptr != '\0') {
ptr++;
}
@@ -1994,7 +2056,7 @@ dict_scan_table_name(
old_ptr = ptr;
- while (!isspace(*ptr) && *ptr != '(' && *ptr != '`') {
+ while (!isspace(*ptr) && *ptr != '(' && *ptr != '`' && *ptr != '\0') {
if (*ptr == '.') {
dot_ptr = ptr;
}
@@ -2017,17 +2079,28 @@ dict_scan_table_name(
}
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name + i, old_ptr,
- ptr - old_ptr);
+ ptr - old_ptr);
#else
- ut_memcpy(second_table_name + i, old_ptr, ptr - old_ptr);
+ if (srv_lower_case_table_names) {
+ ut_cpy_in_lower_case(second_table_name + i, old_ptr,
+ ptr - old_ptr);
+ } else {
+ ut_memcpy(second_table_name + i, old_ptr,
+ ptr - old_ptr);
+ }
#endif
second_table_name[i + (ptr - old_ptr)] = '\0';
} else {
#ifdef __WIN__
ut_cpy_in_lower_case(second_table_name, old_ptr,
- ptr - old_ptr);
+ ptr - old_ptr);
#else
- ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
+ if (srv_lower_case_table_names) {
+ ut_cpy_in_lower_case(second_table_name, old_ptr,
+ ptr - old_ptr);
+ } else {
+ ut_memcpy(second_table_name, old_ptr, ptr - old_ptr);
+ }
#endif
second_table_name[dot_ptr - old_ptr] = '/';
second_table_name[ptr - old_ptr] = '\0';
@@ -2045,6 +2118,44 @@ dict_scan_table_name(
}
/*************************************************************************
+Skips one 'word', like an id. For the lexical definition of 'word', see the
+code below. */
+static
+char*
+dict_skip_word(
+/*===========*/
+ /* out: scanned to */
+ char* ptr, /* in: scanned to */
+ ibool* success)/* out: TRUE if success, FALSE if just spaces left in
+ string */
+{
+ *success = FALSE;
+
+ while (isspace(*ptr)) {
+ ptr++;
+ }
+
+ if (*ptr == '\0') {
+
+ return(ptr);
+ }
+
+ if (*ptr == '`') {
+ ptr++;
+ }
+
+ while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`'
+ && *ptr != '\0') {
+
+ ptr++;
+ }
+
+ *success = TRUE;
+
+ return(ptr);
+}
+
+/*************************************************************************
Returns the number of opening brackets '(' subtracted by the number
of closing brackets ')' between string and ptr. */
static
@@ -2113,7 +2224,6 @@ dict_create_foreign_constraints(
if (table == NULL) {
return(DB_ERROR);
}
-
loop:
ptr = dict_scan_to(ptr, (char *) "FOREIGN");
@@ -2142,7 +2252,19 @@ loop:
ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
- goto loop;
+ /* MySQL allows also an index id before the '('; we
+ skip it */
+ ptr = dict_skip_word(ptr, &success);
+
+ if (!success) {
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ ptr = dict_accept(ptr, (char *) "(", &success);
+
+ if (!success) {
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
}
i = 0;
@@ -2217,6 +2339,7 @@ col_loop1:
if (!success) {
dict_foreign_free(foreign);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2230,6 +2353,7 @@ col_loop2:
if (!success) {
dict_foreign_free(foreign);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2257,14 +2381,20 @@ col_loop2:
ptr = dict_accept(ptr, "DELETE", &success);
if (!success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ ptr = dict_accept(ptr, "RESTRICT", &success);
+ if (success) {
goto try_find_index;
}
ptr = dict_accept(ptr, "CASCADE", &success);
if (success) {
-
foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE;
goto try_find_index;
@@ -2273,32 +2403,47 @@ col_loop2:
ptr = dict_accept(ptr, "SET", &success);
if (!success) {
-
- goto try_find_index;
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, "NULL", &success);
- if (success) {
- for (j = 0; j < foreign->n_fields; j++) {
- if ((dict_index_get_nth_type(
+ if (!success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ for (j = 0; j < foreign->n_fields; j++) {
+ if ((dict_index_get_nth_type(
foreign->foreign_index, j)->prtype)
& DATA_NOT_NULL) {
- /* It is not sensible to define SET NULL
- if the column is not allowed to be NULL! */
+ /* It is not sensible to define SET NULL
+ if the column is not allowed to be NULL! */
- dict_foreign_free(foreign);
- return(DB_CANNOT_ADD_CONSTRAINT);
- }
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
+ }
- foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
+ foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
+
+try_find_index:
+ /* We check that there are no superfluous words like 'ON UPDATE ...'
+ which we do not support yet. */
- goto try_find_index;
+ ptr = dict_accept(ptr, (char *) "ON", &success);
+
+ if (success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
}
-try_find_index:
/* Try to find an index which contains the columns as the first fields
and in the right order, and the types are the same as in
foreign->foreign_index */
@@ -2345,6 +2490,7 @@ try_find_index:
referenced_table->referenced_list,
foreign);
}
+
goto loop;
}
@@ -2843,6 +2989,14 @@ dict_update_statistics_low(
ulint size;
ulint sum_of_index_sizes = 0;
+ /* If we have set a high innodb_force_recovery level, do not calculate
+ statistics, as a badly corrupted index can cause a crash in it. */
+
+ if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+ return;
+ }
+
/* Find out the sizes of the indexes and how many different values
for the key they approximately have */
@@ -3146,16 +3300,25 @@ dict_print_info_on_foreign_keys_in_create_format(
}
}
- buf2 += sprintf(buf2, ") REFERENCES `%s` (",
+ if (dict_tables_have_same_db(table->name,
+ foreign->referenced_table_name)) {
+ /* Do not print the database name of the referenced
+ table */
+ buf2 += sprintf(buf2, ") REFERENCES `%s` (",
+ dict_remove_db_name(
+ foreign->referenced_table_name));
+ } else {
+ buf2 += sprintf(buf2, ") REFERENCES `%s` (",
foreign->referenced_table_name);
- /* Change the '/' in the table name to '.' */
+ /* Change the '/' in the table name to '.' */
- for (i = ut_strlen(buf); i > 0; i--) {
- if (buf[i] == '/') {
+ for (i = ut_strlen(buf); i > 0; i--) {
+ if (buf[i] == '/') {
- buf[i] = '.';
+ buf[i] = '.';
- break;
+ break;
+ }
}
}
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index e9caa37fecc..d8d426d2036 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -335,7 +335,7 @@ dict_load_fields(
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
if (rec_get_deleted_flag(rec)) {
fprintf(stderr,
-"InnoDB: Error: data dictionary entry for table %s is corrupt!\n",
+"InnoDB: Error: data dictionary entry for table %s is corrupt!\n"
"InnoDB: An index field is delete marked.\n",
table->name);
}
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index 3e0f21395ef..98980f6c337 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -967,6 +967,7 @@ fil_extend_last_data_file(
fil_node_t* node;
fil_space_t* space;
fil_system_t* system = fil_system;
+ byte* buf2;
byte* buf;
ibool success;
ulint i;
@@ -981,19 +982,23 @@ fil_extend_last_data_file(
fil_node_prepare_for_io(node, system, space);
- buf = mem_alloc(1024 * 1024);
+ buf2 = mem_alloc(1024 * 1024 + UNIV_PAGE_SIZE);
+ buf = ut_align(buf2, UNIV_PAGE_SIZE);
memset(buf, '\0', 1024 * 1024);
for (i = 0; i < size_increase / ((1024 * 1024) / UNIV_PAGE_SIZE); i++) {
- success = os_file_write(node->name, node->handle, buf,
+ /* If we use native Windows aio, then also this write is
+ done using it */
+
+ success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
+ node->name, node->handle, buf,
(node->size << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFF,
node->size >> (32 - UNIV_PAGE_SIZE_SHIFT),
- 1024 * 1024);
+ 1024 * 1024, NULL, NULL);
if (!success) {
-
break;
}
@@ -1003,7 +1008,7 @@ fil_extend_last_data_file(
os_has_said_disk_full = FALSE;
}
- mem_free(buf);
+ mem_free(buf2);
fil_node_complete_io(node, system, OS_FILE_WRITE);
@@ -1528,7 +1533,6 @@ fil_page_set_type(
ulint type) /* in: type */
{
ut_ad(page);
- ut_ad((type == FIL_PAGE_INDEX) || (type == FIL_PAGE_UNDO_LOG));
mach_write_to_2(page + FIL_PAGE_TYPE, type);
}
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index 1abb043fdc2..ff586819d4a 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -769,6 +769,8 @@ fsp_init_file_page_low(
#endif
page = buf_frame_align(ptr);
+ buf_block_align(page)->check_index_page_at_flush = FALSE;
+
#ifdef UNIV_BASIC_LOG_DEBUG
/* printf("In log debug version: Erase the contents of the file page\n");
*/
@@ -1097,7 +1099,7 @@ fsp_fill_free_list(
/* Initialize the ibuf page in a separate
mini-transaction because it is low in the latching
- order, and we must be able to release the its latch
+ order, and we must be able to release its latch
before returning from the fsp routine */
mtr_start(&ibuf_mtr);
@@ -1264,7 +1266,12 @@ fsp_alloc_free_page(
free = xdes_find_bit(descr, XDES_FREE_BIT, TRUE,
hint % FSP_EXTENT_SIZE, mtr);
- ut_a(free != ULINT_UNDEFINED);
+ if (free == ULINT_UNDEFINED) {
+
+ ut_print_buf(((byte*)descr) - 500, 1000);
+
+ ut_a(0);
+ }
xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
@@ -1412,7 +1419,12 @@ fsp_free_extent(
descr = xdes_get_descriptor_with_space_hdr(header, space, page, mtr);
- ut_a(xdes_get_state(descr, mtr) != XDES_FREE);
+ if (xdes_get_state(descr, mtr) == XDES_FREE) {
+
+ ut_print_buf(((byte*)descr) - 500, 1000);
+
+ ut_a(0);
+ }
xdes_init(descr, mtr);
@@ -1523,6 +1535,10 @@ fsp_alloc_seg_inode_page(
page = buf_page_get(space, page_no, RW_X_LATCH, mtr);
+ buf_block_align(page)->check_index_page_at_flush = FALSE;
+
+ fil_page_set_type(page, FIL_PAGE_INODE);
+
buf_page_dbg_add_level(page, SYNC_FSP_PAGE);
for (i = 0; i < FSP_SEG_INODES_PER_PAGE; i++) {
@@ -2298,6 +2314,8 @@ fseg_alloc_free_page_low(
fseg_mark_page_used(seg_inode, space, ret_page, mtr);
}
+ buf_reset_check_index_page_at_flush(space, ret_page);
+
return(ret_page);
}
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index b7d691485cc..143b3bfa584 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -1295,6 +1295,8 @@ ibuf_add_free_page(
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
+ fil_page_set_type(page, FIL_PAGE_IBUF_FREE_LIST);
+
ibuf_data->seg_size++;
ibuf_data->free_list_len++;
@@ -1305,6 +1307,7 @@ ibuf_add_free_page(
ibuf_bitmap_page_set_bits(bitmap_page, page_no, IBUF_BITMAP_IBUF,
TRUE, &mtr);
+
mtr_commit(&mtr);
mutex_exit(&ibuf_mutex);
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index f66ad3639d4..3cd44ab5175 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -399,6 +399,19 @@ btr_print_tree(
dict_tree_t* tree, /* in: tree */
ulint width); /* in: print this many entries from start
and end */
+/****************************************************************
+Checks the size and number of fields in a record based on the definition of
+the index. */
+
+ibool
+btr_index_rec_validate(
+/*====================*/
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: index record */
+ dict_index_t* index, /* in: index */
+ ibool dump_on_error); /* in: TRUE if the function
+ should print hex dump of record
+ and page on error */
/******************************************************************
Checks the consistency of an index tree. */
diff --git a/innobase/include/btr0pcur.h b/innobase/include/btr0pcur.h
index 05b55e4491d..9d07dd0de18 100644
--- a/innobase/include/btr0pcur.h
+++ b/innobase/include/btr0pcur.h
@@ -298,6 +298,14 @@ btr_pcur_move_to_prev(
function may release the page latch */
mtr_t* mtr); /* in: mtr */
/*************************************************************
+Moves the persistent cursor to the last record on the same page. */
+UNIV_INLINE
+void
+btr_pcur_move_to_last_on_page(
+/*==========================*/
+ btr_pcur_t* cursor, /* in: persistent cursor */
+ mtr_t* mtr); /* in: mtr */
+/*************************************************************
Moves the persistent cursor to the next user record in the tree. If no user
records are left, the cursor ends up 'after last in tree'. */
UNIV_INLINE
diff --git a/innobase/include/btr0pcur.ic b/innobase/include/btr0pcur.ic
index a60140e4aa9..a1db2cc52dd 100644
--- a/innobase/include/btr0pcur.ic
+++ b/innobase/include/btr0pcur.ic
@@ -285,6 +285,24 @@ btr_pcur_move_to_prev_on_page(
}
/*************************************************************
+Moves the persistent cursor to the last record on the same page. */
+UNIV_INLINE
+void
+btr_pcur_move_to_last_on_page(
+/*==========================*/
+ btr_pcur_t* cursor, /* in: persistent cursor */
+ mtr_t* mtr) /* in: mtr */
+{
+ UT_NOT_USED(mtr);
+ ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
+
+ page_cur_set_after_last(buf_frame_align(btr_pcur_get_rec(cursor)),
+ btr_pcur_get_page_cur(cursor));
+
+ cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
+}
+
+/*************************************************************
Moves the persistent cursor to the next user record in the tree. If no user
records are left, the cursor ends up 'after last in tree'. */
UNIV_INLINE
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index 591c0ec54ab..f76c437bd1d 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -274,6 +274,15 @@ buf_page_peek_block(
ulint space, /* in: space id */
ulint offset);/* in: page number */
/************************************************************************
+Resets the check_index_page_at_flush field of a page if found in the buffer
+pool. */
+
+void
+buf_reset_check_index_page_at_flush(
+/*================================*/
+ ulint space, /* in: space id */
+ ulint offset);/* in: page number */
+/************************************************************************
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
This function should be called when we free a file page and want the
debug version to check that it is not accessed any more unless
@@ -648,6 +657,14 @@ struct buf_block_struct{
then it can wait for this rw-lock */
buf_block_t* hash; /* node used in chaining to the page
hash table */
+ ibool check_index_page_at_flush;
+ /* TRUE if we know that this is
+ an index page, and want the database
+ to check its consistency before flush;
+ note that there may be pages in the
+ buffer pool which are index pages,
+ but this flag is not set because
+ we do not keep track of all pages */
/* 2. Page flushing fields */
UT_LIST_NODE_T(buf_block_t) flush_list;
diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h
index ddfbd5b7862..86b79b65bf2 100644
--- a/innobase/include/db0err.h
+++ b/innobase/include/db0err.h
@@ -41,7 +41,8 @@ Created 5/24/1996 Heikki Tuuri
which is referenced */
#define DB_CANNOT_ADD_CONSTRAINT 38 /* adding a foreign key constraint
to a table failed */
-
+#define DB_CORRUPTION 39 /* data structure corruption noticed */
+
/* The following are partial failure codes */
#define DB_FAIL 1000
#define DB_OVERFLOW 1001
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index dd92c5aa467..b5e6e04a1de 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -26,6 +26,18 @@ Created 1/8/1996 Heikki Tuuri
#include "ut0byte.h"
#include "trx0types.h"
+/*************************************************************************
+Accepts a specified string. Comparisons are case-insensitive. */
+
+char*
+dict_accept(
+/*========*/
+ /* out: if string was accepted, the pointer
+ is moved after that, else ptr is returned */
+ char* ptr, /* in: scan from this */
+ const char* string,/* in: accept only this string as the next
+ non-whitespace string */
+ ibool* success);/* out: TRUE if accepted */
/************************************************************************
Decrements the count of open MySQL handles to a table. */
@@ -798,7 +810,7 @@ dict_mutex_exit_for_mysql(void);
extern dict_sys_t* dict_sys; /* the dictionary system */
-extern rw_lock_t dict_foreign_key_check_lock;
+extern rw_lock_t dict_operation_lock;
/* Dictionary system struct */
struct dict_sys_struct{
diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h
index 63e20221c16..23ef0304b2d 100644
--- a/innobase/include/fil0fil.h
+++ b/innobase/include/fil0fil.h
@@ -73,6 +73,8 @@ extern fil_addr_t fil_addr_null;
/* File page types */
#define FIL_PAGE_INDEX 17855
#define FIL_PAGE_UNDO_LOG 2
+#define FIL_PAGE_INODE 3
+#define FIL_PAGE_IBUF_FREE_LIST 4
/* Space types */
#define FIL_TABLESPACE 501
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 288356d3270..d3b3d55d015 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -292,16 +292,12 @@ lock_sec_rec_modify_check_and_lock(
dict_index_t* index, /* in: secondary index */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
-Checks if locks of other transactions prevent an immediate read, or passing
-over by a read cursor, of a clustered index record. If they do, first tests
-if the query thread should anyway be suspended for some reason; if not, then
-puts the transaction and the query thread to the lock wait state and inserts a
-waiting request for a record lock to the lock queue. Sets the requested mode
-lock on the record. */
+Like the counterpart for a clustered index below, but now we read a
+secondary index record. */
ulint
-lock_clust_rec_read_check_and_lock(
-/*===============================*/
+lock_sec_rec_read_check_and_lock(
+/*=============================*/
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
@@ -309,18 +305,24 @@ lock_clust_rec_read_check_and_lock(
rec_t* rec, /* in: user record or page supremum record
which should be read or passed over by a read
cursor */
- dict_index_t* index, /* in: clustered index */
+ dict_index_t* index, /* in: secondary index */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
+ ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
+ LOCK_REC_NOT_GAP */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
-Like the counterpart for a clustered index above, but now we read a
-secondary index record. */
+Checks if locks of other transactions prevent an immediate read, or passing
+over by a read cursor, of a clustered index record. If they do, first tests
+if the query thread should anyway be suspended for some reason; if not, then
+puts the transaction and the query thread to the lock wait state and inserts a
+waiting request for a record lock to the lock queue. Sets the requested mode
+lock on the record. */
ulint
-lock_sec_rec_read_check_and_lock(
-/*=============================*/
+lock_clust_rec_read_check_and_lock(
+/*===============================*/
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
@@ -328,10 +330,12 @@ lock_sec_rec_read_check_and_lock(
rec_t* rec, /* in: user record or page supremum record
which should be read or passed over by a read
cursor */
- dict_index_t* index, /* in: secondary index */
+ dict_index_t* index, /* in: clustered index */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
+ ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
+ LOCK_REC_NOT_GAP */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
Checks that a record is seen in a consistent read. */
@@ -509,6 +513,7 @@ lock_validate(void);
extern lock_sys_t* lock_sys;
/* Lock modes and types */
+/* Basic modes */
#define LOCK_NONE 0 /* this flag is used elsewhere to note
consistent read */
#define LOCK_IS 2 /* intention shared */
@@ -519,15 +524,20 @@ extern lock_sys_t* lock_sys;
in an exclusive mode */
#define LOCK_MODE_MASK 0xF /* mask used to extract mode from the
type_mode field in a lock */
+/* Lock types */
#define LOCK_TABLE 16 /* these type values should be so high that */
#define LOCK_REC 32 /* they can be ORed to the lock mode */
#define LOCK_TYPE_MASK 0xF0 /* mask used to extract lock type from the
type_mode field in a lock */
+/* Waiting lock flag */
#define LOCK_WAIT 256 /* this wait bit should be so high that
it can be ORed to the lock mode and type;
when this bit is set, it means that the
lock has not yet been granted, it is just
waiting for its turn in the wait queue */
+/* Precise modes */
+#define LOCK_ORDINARY 0 /* this flag denotes an ordinary next-key lock
+ in contrast to LOCK_GAP or LOCK_REC_NOT_GAP */
#define LOCK_GAP 512 /* this gap bit should be so high that
it can be ORed to the other flags;
when this bit is set, it means that the
@@ -537,7 +547,15 @@ extern lock_sys_t* lock_sys;
the bit is set; locks of this type are created
when records are removed from the index chain
of records */
-#define LOCK_INSERT_INTENTION 1024 /* this bit is set when we place a waiting
+#define LOCK_REC_NOT_GAP 1024 /* this bit means that the lock is only on
+ the index record and does NOT block inserts
+ to the gap before the index record; this is
+ used in the case when we retrieve a record
+ with a unique key, and is also used in
+ locking plain SELECTs (not part of UPDATE
+ or DELETE) when the user has set the READ
+ COMMITTED isolation level */
+#define LOCK_INSERT_INTENTION 2048 /* this bit is set when we place a waiting
gap type record lock request in order to let
an insert of an index record to wait until
there are no conflicting locks by other
diff --git a/innobase/include/log0recv.h b/innobase/include/log0recv.h
index baa2ba50c7d..7418e4abf1b 100644
--- a/innobase/include/log0recv.h
+++ b/innobase/include/log0recv.h
@@ -334,6 +334,7 @@ extern ibool recv_no_ibuf_operations;
extern ibool recv_needed_recovery;
extern ibool recv_is_making_a_backup;
+extern ulint recv_max_parsed_page_no;
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
times! */
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index d65c7fd47e3..a7624a90d5e 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -111,6 +111,7 @@ log. */
#define OS_WIN31 1
#define OS_WIN95 2
#define OS_WINNT 3
+#define OS_WIN2000 4
extern ulint os_n_file_reads;
extern ulint os_n_file_writes;
@@ -122,7 +123,7 @@ Gets the operating system version. Currently works only on Windows. */
ulint
os_get_os_version(void);
/*===================*/
- /* out: OS_WIN95, OS_WIN31, OS_WINNT (2000 == NT) */
+ /* out: OS_WIN95, OS_WIN31, OS_WINNT, or OS_WIN2000 */
/********************************************************************
Creates the seek mutexes used in positioned reads and writes. */
diff --git a/innobase/include/os0proc.h b/innobase/include/os0proc.h
index 9da1f33e070..79750e5c1f7 100644
--- a/innobase/include/os0proc.h
+++ b/innobase/include/os0proc.h
@@ -16,6 +16,15 @@ typedef void* os_process_t;
typedef unsigned long int os_process_id_t;
/********************************************************************
+Converts the current process id to a number. It is not guaranteed that the
+number is unique. In Linux returns the 'process number' of the current
+thread. That number is the same as one sees in 'top', for example. In Linux
+the thread id is not the same as one sees in 'top'. */
+
+ulint
+os_proc_get_number(void);
+/*====================*/
+/********************************************************************
Allocates non-cacheable memory. */
void*
diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h
index 8355afa46e9..efc8651e06d 100644
--- a/innobase/include/os0thread.h
+++ b/innobase/include/os0thread.h
@@ -16,11 +16,8 @@ Created 9/8/1995 Heikki Tuuri
this is also the size of the wait slot array for MySQL threads which
can wait inside InnoDB */
#ifdef __WIN__
-/* Windows 95/98/ME seemed to have difficulties creating the all
-the event semaphores for the wait array slots. If the computer had
-<= 64 MB memory, InnoDB startup could take minutes or even crash.
-That is why we set this to only 1000 in Windows. */
-
+/* Create less event semaphores because Win 98/ME had difficult creating
+40000 event semaphores */
#define OS_THREAD_MAX_N 1000
#else
#define OS_THREAD_MAX_N 10000
diff --git a/innobase/include/page0cur.h b/innobase/include/page0cur.h
index 144e0e02b21..c3f0decdb4b 100644
--- a/innobase/include/page0cur.h
+++ b/innobase/include/page0cur.h
@@ -26,7 +26,12 @@ Created 10/4/1994 Heikki Tuuri
#define PAGE_CUR_GE 2
#define PAGE_CUR_L 3
#define PAGE_CUR_LE 4
-#define PAGE_CUR_DBG 5
+#define PAGE_CUR_LE_OR_EXTENDS 5 /* This is a search mode used in
+ "column LIKE 'abc%' ORDER BY column DESC";
+ we have to find strings which are <= 'abc' or
+ which extend it */
+#define PAGE_CUR_DBG 6
+
extern ulint page_cur_short_succ;
diff --git a/innobase/include/page0page.h b/innobase/include/page0page.h
index 2f77127466f..b5e33af5bc0 100644
--- a/innobase/include/page0page.h
+++ b/innobase/include/page0page.h
@@ -666,6 +666,16 @@ page_rec_validate(
/* out: TRUE if ok */
rec_t* rec); /* in: record on the page */
/*******************************************************************
+This function checks the consistency of an index page when we do not
+know the index. This is also resilient so that this should never crash
+even if the page is total garbage. */
+
+ibool
+page_simple_validate(
+/*=================*/
+ /* out: TRUE if ok */
+ page_t* page); /* in: index page */
+/*******************************************************************
This function checks the consistency of an index page. */
ibool
diff --git a/innobase/include/que0que.h b/innobase/include/que0que.h
index cdaeeae1fde..a3ed18e2b14 100644
--- a/innobase/include/que0que.h
+++ b/innobase/include/que0que.h
@@ -117,6 +117,7 @@ que_thr_stop(
/**************************************************************************
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
the n_active_thrs counters of the query graph and transaction. */
+
void
que_thr_move_to_run_state_for_mysql(
/*================================*/
@@ -125,14 +126,17 @@ que_thr_move_to_run_state_for_mysql(
/**************************************************************************
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
select, when there is no error or lock wait. */
+
void
que_thr_stop_for_mysql_no_error(
/*============================*/
que_thr_t* thr, /* in: query thread */
trx_t* trx); /* in: transaction */
/**************************************************************************
-A patch for MySQL used to 'stop' a dummy query thread used in MySQL
-select. */
+A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
+query thread is stopped and made inactive, except in the case where
+it was put to the lock wait state in lock0lock.c, but the lock has already
+been granted or the transaction chosen as a victim in deadlock resolution. */
void
que_thr_stop_for_mysql(
diff --git a/innobase/include/read0read.h b/innobase/include/read0read.h
index cebb2d6701c..db6bf888095 100644
--- a/innobase/include/read0read.h
+++ b/innobase/include/read0read.h
@@ -45,6 +45,14 @@ read_view_close(
/*============*/
read_view_t* view); /* in: read view */
/*************************************************************************
+Closes a consistent read view for MySQL. This function is called at an SQL
+statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */
+
+void
+read_view_close_for_mysql(
+/*======================*/
+ trx_t* trx); /* in: trx which has a read view */
+/*************************************************************************
Checks if a read view sees the specified transaction. */
UNIV_INLINE
ibool
diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h
index 12e3a8b39d6..b28f39925c1 100644
--- a/innobase/include/rem0rec.h
+++ b/innobase/include/rem0rec.h
@@ -148,12 +148,22 @@ data field in the record. */
byte*
rec_get_nth_field(
/*==============*/
- /* out: pointer to the field, NULL if SQL null */
+ /* out: pointer to the field */
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
ulint* len); /* out: length of the field; UNIV_SQL_NULL
if SQL null */
/****************************************************************
+Return field length or UNIV_SQL_NULL. */
+UNIV_INLINE
+ulint
+rec_get_nth_field_len(
+/*==================*/
+ /* out: length of the field; UNIV_SQL_NULL if SQL
+ null */
+ rec_t* rec, /* in: record */
+ ulint n); /* in: index of the field */
+/****************************************************************
Gets the physical size of a field. Also an SQL null may have a field of
size > 0, if the data type is of a fixed size. */
UNIV_INLINE
diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic
index aaa3c58a003..9dfd4faeec8 100644
--- a/innobase/include/rem0rec.ic
+++ b/innobase/include/rem0rec.ic
@@ -65,6 +65,24 @@ a field stored to another page: */
#define REC_2BYTE_EXTERN_MASK 0x4000
+/****************************************************************
+Return field length or UNIV_SQL_NULL. */
+UNIV_INLINE
+ulint
+rec_get_nth_field_len(
+/*==================*/
+ /* out: length of the field; UNIV_SQL_NULL if SQL
+ null */
+ rec_t* rec, /* in: record */
+ ulint n) /* in: index of the field */
+{
+ ulint len;
+
+ rec_get_nth_field(rec, n, &len);
+
+ return(len);
+}
+
/***************************************************************
Sets the value of the ith field SQL null bit. */
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 8152c534f48..44b470fe7ea 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -230,18 +230,35 @@ row_update_cascade_for_mysql(
or set null operation */
dict_table_t* table); /* in: table where we do the operation */
/*************************************************************************
-Locks the data dictionary exclusively for performing a table create
-operation. */
+Locks the data dictionary exclusively for performing a table create or other
+data dictionary modification operation. */
void
-row_mysql_lock_data_dictionary(void);
-/*================================*/
+row_mysql_lock_data_dictionary(
+/*===========================*/
+ trx_t* trx); /* in: transaction */
/*************************************************************************
-Unlocks the data dictionary exclusively lock. */
+Unlocks the data dictionary exclusive lock. */
void
-row_mysql_unlock_data_dictionary(void);
-/*==================================*/
+row_mysql_unlock_data_dictionary(
+/*=============================*/
+ trx_t* trx); /* in: transaction */
+/*************************************************************************
+Locks the data dictionary in shared mode from modifications, for performing
+foreign key check, rollback, or other operation invisible to MySQL. */
+
+void
+row_mysql_freeze_data_dictionary(
+/*=============================*/
+ trx_t* trx); /* in: transaction */
+/*************************************************************************
+Unlocks the data dictionary shared lock. */
+
+void
+row_mysql_unfreeze_data_dictionary(
+/*===============================*/
+ trx_t* trx); /* in: transaction */
/*************************************************************************
Does a table creation operation for MySQL. If the name of the created
table ends to characters INNODB_MONITOR, then this also starts
@@ -310,11 +327,9 @@ output by the master thread. */
int
row_drop_table_for_mysql(
/*=====================*/
- /* out: error code or DB_SUCCESS */
- char* name, /* in: table name */
- trx_t* trx, /* in: transaction handle */
- ibool has_dict_mutex);/* in: TRUE if the caller already owns the
- dictionary system mutex */
+ /* out: error code or DB_SUCCESS */
+ char* name, /* in: table name */
+ trx_t* trx); /* in: transaction handle */
/*************************************************************************
Drops a database for MySQL. */
@@ -393,6 +408,10 @@ struct row_prebuilt_struct {
an SQL statement: we may have to set
an intention lock on the table,
create a consistent read view etc. */
+ ibool mysql_has_locked; /* this is set TRUE when MySQL
+ calls external_lock on this handle
+ with a lock flag, and set FALSE when
+ with the F_UNLOCK flag */
ibool clust_index_was_generated;
/* if the user did not define a
primary key in MySQL, then Innobase
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 9de5e9ccfc9..ad6f71f7a3a 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -28,6 +28,9 @@ extern os_event_t srv_lock_timeout_thread_event;
at a time */
#define SRV_AUTO_EXTEND_INCREMENT (8 * ((1024 * 1024) / UNIV_PAGE_SIZE))
+/* This is set to TRUE if the MySQL user has set it in MySQL */
+extern ibool srv_lower_case_table_names;
+
/* Server parameters which are read from the initfile */
extern char* srv_data_home;
@@ -57,8 +60,6 @@ extern ulint srv_flush_log_at_trx_commit;
extern byte srv_latin1_ordering[256];/* The sort order table of the latin1
character set */
-extern ibool srv_use_native_aio;
-
extern ulint srv_pool_size;
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
@@ -70,8 +71,9 @@ extern dulint srv_archive_recovery_limit_lsn;
extern ulint srv_lock_wait_timeout;
-extern char* srv_unix_file_flush_method_str;
+extern char* srv_file_flush_method_str;
extern ulint srv_unix_file_flush_method;
+extern ulint srv_win_file_flush_method;
extern ulint srv_force_recovery;
extern ulint srv_thread_concurrency;
@@ -154,13 +156,19 @@ typedef struct srv_sys_struct srv_sys_t;
/* The server system */
extern srv_sys_t* srv_sys;
-/* Alternatives for the field flush option in Unix; see the InnoDB manual about
+/* Alternatives for the file flush option in Unix; see the InnoDB manual about
what these mean */
-#define SRV_UNIX_FDATASYNC 1
+#define SRV_UNIX_FDATASYNC 1 /* This is the default; it is currently mapped
+ to a call of fsync() because fdatasync()
+ seemed to corrupt files in Linux and Solaris */
#define SRV_UNIX_O_DSYNC 2
#define SRV_UNIX_LITTLESYNC 3
#define SRV_UNIX_NOSYNC 4
+/* Alternatives for file i/o in Windows */
+#define SRV_WIN_IO_NORMAL 1
+#define SRV_WIN_IO_UNBUFFERED 2 /* This is the default */
+
/* Alternatives for srv_force_recovery. Non-zero values are intended
to help the user get a damaged database up so that he can dump intact
tables and rows with SELECT INTO OUTFILE. The database must not otherwise
@@ -311,15 +319,17 @@ srv_conc_exit_innodb(
trx_t* trx); /* in: transaction object associated with the
thread */
/*******************************************************************
-Puts a MySQL OS thread to wait for a lock to be released. */
+Puts a MySQL OS thread to wait for a lock to be released. If an error
+occurs during the wait trx->error_state associated with thr is
+!= DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
+are possible errors. DB_DEADLOCK is returned if selective deadlock
+resolution chose this transaction as a victim. */
-ibool
+void
srv_suspend_mysql_thread(
/*=====================*/
- /* out: TRUE if the lock wait timeout was
- exceeded */
- que_thr_t* thr); /* in: query thread associated with
- the MySQL OS thread */
+ que_thr_t* thr); /* in: query thread associated with the MySQL
+ OS thread */
/************************************************************************
Releases a MySQL OS thread waiting for a lock to be released, if the
thread is already suspended. */
@@ -407,3 +417,4 @@ struct srv_sys_struct{
extern ulint srv_n_threads_active[];
#endif
+
diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h
index 646d2c1bb06..24cdecb7341 100644
--- a/innobase/include/srv0start.h
+++ b/innobase/include/srv0start.h
@@ -79,6 +79,8 @@ innobase_shutdown_for_mysql(void);
/*=============================*/
/* out: DB_SUCCESS or error code */
+extern ulint srv_sizeof_trx_t_in_ha_innodb_cc;
+
extern ibool srv_startup_is_before_trx_rollback_phase;
extern ibool srv_is_being_shut_down;
diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h
index 7ad38f5bc7f..5aa3dcdffc3 100644
--- a/innobase/include/sync0rw.h
+++ b/innobase/include/sync0rw.h
@@ -335,7 +335,8 @@ ibool
rw_lock_own(
/*========*/
rw_lock_t* lock, /* in: rw-lock */
- ulint lock_type); /* in: lock type */
+ ulint lock_type); /* in: lock type: RW_LOCK_SHARED,
+ RW_LOCK_EX */
/**********************************************************************
Checks if somebody has locked the rw-lock in the specified mode. */
diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h
index 5bfa0bc2d48..320f8faf12d 100644
--- a/innobase/include/sync0sync.h
+++ b/innobase/include/sync0sync.h
@@ -371,10 +371,12 @@ or row lock! */
#define SYNC_NO_ORDER_CHECK 3000 /* this can be used to suppress
latching order checking */
#define SYNC_LEVEL_NONE 2000 /* default: level not defined */
-#define SYNC_FOREIGN_KEY_CHECK 1001
+#define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve
+ this in X-mode, implicit or backround
+ operations purge, rollback, foreign
+ key checks reserve this in S-mode */
#define SYNC_DICT 1000
#define SYNC_DICT_AUTOINC_MUTEX 999
-#define SYNC_PURGE_IS_RUNNING 997
#define SYNC_DICT_HEADER 995
#define SYNC_IBUF_HEADER 914
#define SYNC_IBUF_PESS_INSERT_MUTEX 912
diff --git a/innobase/include/trx0purge.h b/innobase/include/trx0purge.h
index 087be2f060e..049c79aec9b 100644
--- a/innobase/include/trx0purge.h
+++ b/innobase/include/trx0purge.h
@@ -111,9 +111,6 @@ struct trx_purge_struct{
of the trx system and it never ends */
que_t* query; /* The query graph which will do the
parallelized purge operation */
- rw_lock_t purge_is_running;/* Purge operation set an x-latch here
- while it is accessing a table: this
- prevents dropping of the table */
rw_lock_t latch; /* The latch protecting the purge view.
A purge operation must acquire an
x-latch here for the instant at which
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 9b29c481b6d..34f820f03e7 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -327,6 +327,7 @@ struct trx_struct{
time_t start_time; /* time the trx object was created
or the state last time became
TRX_ACTIVE */
+ ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
ibool check_foreigns; /* normally TRUE, but if the user
wants to suppress foreign key checks,
(in table imports, for example) we
@@ -350,6 +351,9 @@ struct trx_struct{
/*------------------------------*/
void* mysql_thd; /* MySQL thread handle corresponding
to this trx, or NULL */
+ char** mysql_query_str;/* pointer to the field in mysqld_thd
+ which contains the pointer to the
+ current SQL query string */
char* mysql_log_file_name;
/* if MySQL binlog is used, this field
contains a pointer to the latest file
@@ -371,6 +375,9 @@ struct trx_struct{
replication has processed */
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
with this transaction object */
+ ulint mysql_process_no;/* since in Linux, 'top' reports
+ process id's and not thread id's, we
+ store the process number too */
/*------------------------------*/
ulint n_mysql_tables_in_use; /* number of Innobase tables
used in the processing of the current
@@ -379,9 +386,10 @@ struct trx_struct{
/* how many tables the current SQL
statement uses, except those
in consistent read */
- ibool has_dict_foreign_key_check_lock;
- /* TRUE if the trx currently holds
- an s-lock on dict_foreign_... */
+ ibool dict_operation_lock_mode;
+ /* 0, RW_S_LATCH, or RW_X_LATCH:
+ the latch mode trx currently holds
+ on dict_operation_lock */
ibool has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
@@ -420,36 +428,11 @@ struct trx_struct{
mysql_trx_list; /* list of transactions created for
MySQL */
/*------------------------------*/
- mutex_t undo_mutex; /* mutex protecting the fields in this
- section (down to undo_no_arr), EXCEPT
- last_sql_stat_start, which can be
- accessed only when we know that there
- cannot be any activity in the undo
- logs! */
- dulint undo_no; /* next undo log record number to
- assign */
- trx_savept_t last_sql_stat_start;
- /* undo_no when the last sql statement
- was started: in case of an error, trx
- is rolled back down to this undo
- number; see note at undo_mutex! */
- trx_rseg_t* rseg; /* rollback segment assigned to the
- transaction, or NULL if not assigned
- yet */
- trx_undo_t* insert_undo; /* pointer to the insert undo log, or
- NULL if no inserts performed yet */
- trx_undo_t* update_undo; /* pointer to the update undo log, or
- NULL if no update performed yet */
- dulint roll_limit; /* least undo number to undo during
- a rollback */
- ulint pages_undone; /* number of undo log pages undone
- since the last undo log truncation */
- trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
- records which are currently processed
- by a rollback operation */
- /*------------------------------*/
ulint error_state; /* 0 if no error, otherwise error
- number */
+ number; NOTE That ONLY the thread
+ doing the transaction is allowed to
+ set this field: this is NOT protected
+ by the kernel mutex */
void* error_info; /* if the error number indicates a
duplicate key error, a pointer to
the problematic index is stored here */
@@ -486,6 +469,12 @@ struct trx_struct{
TRX_QUE_LOCK_WAIT, this points to
the lock request, otherwise this is
NULL */
+ ibool was_chosen_as_deadlock_victim;
+ /* when the transaction decides to wait
+ for a lock, this it sets this to FALSE;
+ if another transaction chooses this
+ transaction as a victim in deadlock
+ resolution, it sets this to TRUE */
time_t wait_started; /* lock wait started at this time */
UT_LIST_BASE_NODE_T(que_thr_t)
wait_thrs; /* query threads belonging to this
@@ -501,6 +490,34 @@ struct trx_struct{
/*------------------------------*/
mem_heap_t* read_view_heap; /* memory heap for the read view */
read_view_t* read_view; /* consistent read view or NULL */
+ /*------------------------------*/
+ mutex_t undo_mutex; /* mutex protecting the fields in this
+ section (down to undo_no_arr), EXCEPT
+ last_sql_stat_start, which can be
+ accessed only when we know that there
+ cannot be any activity in the undo
+ logs! */
+ dulint undo_no; /* next undo log record number to
+ assign */
+ trx_savept_t last_sql_stat_start;
+ /* undo_no when the last sql statement
+ was started: in case of an error, trx
+ is rolled back down to this undo
+ number; see note at undo_mutex! */
+ trx_rseg_t* rseg; /* rollback segment assigned to the
+ transaction, or NULL if not assigned
+ yet */
+ trx_undo_t* insert_undo; /* pointer to the insert undo log, or
+ NULL if no inserts performed yet */
+ trx_undo_t* update_undo; /* pointer to the update undo log, or
+ NULL if no update performed yet */
+ dulint roll_limit; /* least undo number to undo during
+ a rollback */
+ ulint pages_undone; /* number of undo log pages undone
+ since the last undo log truncation */
+ trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
+ records which are currently processed
+ by a rollback operation */
};
#define TRX_MAX_N_THREADS 32 /* maximum number of concurrent
@@ -523,6 +540,41 @@ struct trx_struct{
#define TRX_QUE_ROLLING_BACK 3 /* transaction is rolling back */
#define TRX_QUE_COMMITTING 4 /* transaction is committing */
+/* Transaction isolation levels */
+#define TRX_ISO_READ_UNCOMMITTED 1 /* dirty read: non-locking
+ SELECTs are performed so that
+ we do not look at a possible
+ earlier version of a record;
+ thus they are not 'consistent'
+ reads under this isolation
+ level; otherwise like level
+ 2 */
+
+#define TRX_ISO_READ_COMMITTED 2 /* somewhat Oracle-like
+ isolation, except that in
+ range UPDATE and DELETE we
+ must block phantom rows
+ with next-key locks;
+ SELECT ... FOR UPDATE and ...
+ LOCK IN SHARE MODE only lock
+ the index records, NOT the
+ gaps before them, and thus
+ allow free inserting;
+ each consistent read reads its
+ own snapshot */
+
+#define TRX_ISO_REPEATABLE_READ 3 /* this is the default;
+ all consistent reads in the
+ same trx read the same
+ snapshot;
+ full next-key locking used
+ in locking reads to block
+ insertions into gaps */
+
+#define TRX_ISO_SERIALIZABLE 4 /* all plain SELECTs are
+ converted to LOCK IN SHARE
+ MODE reads */
+
/* Types of a trx signal */
#define TRX_SIG_NO_SIGNAL 100
#define TRX_SIG_TOTAL_ROLLBACK 1
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 866fe556af9..7b08d6b89b8 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -70,6 +70,11 @@ A waiting record lock can also be of the gap type. A waiting lock request
can be granted when there is no conflicting mode lock request by another
transaction ahead of it in the explicit lock queue.
+In version 4.0.5 we added yet another explicit lock type: LOCK_REC_NOT_GAP.
+It only locks the record it is placed on, not the gap before the record.
+This lock type is necessary to emulate an Oracle-like READ COMMITTED isolation
+level.
+
-------------------------------------------------------------------------
RULE 1: If there is an implicit x-lock on a record, and there are non-gap
-------
@@ -294,7 +299,9 @@ struct lock_struct{
UT_LIST_NODE_T(lock_t)
trx_locks; /* list of the locks of the
transaction */
- ulint type_mode; /* lock type, mode, gap flag, and
+ ulint type_mode; /* lock type, mode, LOCK_GAP or
+ LOCK_REC_NOT_GAP,
+ LOCK_INSERT_INTENTION,
wait flag, ORed */
hash_node_t hash; /* hash chain node for a record lock */
dict_index_t* index; /* index for a record lock */
@@ -309,6 +316,10 @@ Monitor will then fetch it and print */
ibool lock_deadlock_found = FALSE;
char* lock_latest_err_buf; /* We allocate 5000 bytes for this */
+/* Flags for recursive deadlock search */
+#define LOCK_VICTIM_IS_START 1
+#define LOCK_VICTIM_IS_OTHER 2
+
/************************************************************************
Checks if a lock request results in a deadlock. */
static
@@ -700,23 +711,23 @@ lock_rec_get_gap(
}
/*************************************************************************
-Sets the gap flag of a record lock. */
+Gets the LOCK_REC_NOT_GAP flag of a record lock. */
UNIV_INLINE
-void
-lock_rec_set_gap(
-/*=============*/
- lock_t* lock, /* in: record lock */
- ibool val) /* in: value to set: TRUE or FALSE */
+ibool
+lock_rec_get_rec_not_gap(
+/*=====================*/
+ /* out: TRUE if LOCK_REC_NOT_GAP flag set */
+ lock_t* lock) /* in: record lock */
{
ut_ad(lock);
- ut_ad((val == TRUE) || (val == FALSE));
ut_ad(lock_get_type(lock) == LOCK_REC);
- if (val) {
- lock->type_mode = lock->type_mode | LOCK_GAP;
- } else {
- lock->type_mode = lock->type_mode & ~LOCK_GAP;
+ if (lock->type_mode & LOCK_REC_NOT_GAP) {
+
+ return(TRUE);
}
+
+ return(FALSE);
}
/*************************************************************************
@@ -740,26 +751,6 @@ lock_rec_get_insert_intention(
}
/*************************************************************************
-Sets the waiting insert flag of a record lock. */
-UNIV_INLINE
-void
-lock_rec_set_insert_intention(
-/*==========================*/
- lock_t* lock, /* in: record lock */
- ibool val) /* in: value to set: TRUE or FALSE */
-{
- ut_ad(lock);
- ut_ad((val == TRUE) || (val == FALSE));
- ut_ad(lock_get_type(lock) == LOCK_REC);
-
- if (val) {
- lock->type_mode = lock->type_mode | LOCK_INSERT_INTENTION;
- } else {
- lock->type_mode = lock->type_mode & ~LOCK_INSERT_INTENTION;
- }
-}
-
-/*************************************************************************
Calculates if lock mode 1 is stronger or equal to lock mode 2. */
UNIV_INLINE
ibool
@@ -848,48 +839,53 @@ lock_rec_has_to_wait(
/* out: TRUE if new lock has to wait for lock2 to be
removed */
trx_t* trx, /* in: trx of new lock */
- ulint mode, /* in: LOCK_S or LOCK_X */
- ulint gap, /* in: LOCK_GAP or 0 */
- ulint insert_intention,
- /* in: LOCK_INSERT_INTENTION or 0 */
+ ulint type_mode,/* in: precise mode of the new lock to set:
+ LOCK_S or LOCK_X, possibly ORed to
+ LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION */
lock_t* lock2) /* in: another record lock; NOTE that it is assumed
that this has a lock bit set on the same record as
- in lock1 */
+ in the new lock we are setting */
{
ut_ad(trx && lock2);
ut_ad(lock_get_type(lock2) == LOCK_REC);
- ut_ad(mode == LOCK_S || mode == LOCK_X);
- ut_ad(gap == LOCK_GAP || gap == 0);
- ut_ad(insert_intention == LOCK_INSERT_INTENTION
- || insert_intention == 0);
- if (trx != lock2->trx && !lock_mode_compatible(mode,
+ if (trx != lock2->trx
+ && !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
lock_get_mode(lock2))) {
- /* We have somewhat complex rules when gap type
- record locks cause waits */
+ /* We have somewhat complex rules when gap type record locks
+ cause waits */
- if (!gap && lock_rec_get_insert_intention(lock2)) {
+ if ((type_mode & LOCK_REC_NOT_GAP)
+ && lock_rec_get_gap(lock2)) {
+ /* Lock on just the record does not need to wait for
+ a gap type lock */
+
+ return(FALSE);
+ }
+
+ if ((type_mode & LOCK_GAP)
+ && lock_rec_get_rec_not_gap(lock2)) {
+
+ /* Lock on gap does not need to wait for
+ a LOCK_REC_NOT_GAP type lock */
- /* Request of a full next-key record does not
- need to wait for an insert intention lock to be
- removed. This is ok since our rules allow conflicting
- locks on gaps. This eliminates a spurious deadlock
- caused by a next-key lock waiting for an insert
- intention lock; when the insert intention lock was
- granted, the insert deadlocked on the waiting
- next-key lock. */
-
return(FALSE);
}
- if (insert_intention && lock_rec_get_insert_intention(lock2)) {
+ if (lock_rec_get_insert_intention(lock2)) {
- /* An insert intention is not disturbed by another
- insert intention; this removes a spurious deadlock
- caused by inserts which had to wait for a next-key
- lock to be removed */
+ /* No lock request needs to wait for an insert
+ intention lock to be removed. This is ok since our
+ rules allow conflicting locks on gaps. This eliminates
+ a spurious deadlock caused by a next-key lock waiting
+ for an insert intention lock; when the insert
+ intention lock was granted, the insert deadlocked on
+ the waiting next-key lock.
+ Also, insert intention locks do not disturb each
+ other. */
+
return(FALSE);
}
@@ -921,10 +917,7 @@ lock_has_to_wait(
ut_ad(lock_get_type(lock2) == LOCK_REC);
return(lock_rec_has_to_wait(lock1->trx,
- lock_get_mode(lock1),
- lock_rec_get_gap(lock1),
- lock_rec_get_insert_intention(lock1),
- lock2));
+ lock1->type_mode, lock2));
}
return(TRUE);
@@ -1386,32 +1379,41 @@ lock_table_has(
/*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/
/*************************************************************************
-Checks if a transaction has a GRANTED explicit lock on rec, where the gap
-flag or the insert intention flag is not set, stronger or equal to mode.
-Note that locks on the supremum of a page are a special case here, since
-they are always gap type locks, even if the gap flag is not set in them. */
+Checks if a transaction has a GRANTED explicit lock on rec stronger or equal
+to precise_mode. */
UNIV_INLINE
lock_t*
lock_rec_has_expl(
/*==============*/
/* out: lock or NULL */
- ulint mode, /* in: lock mode */
+ ulint precise_mode,/* in: LOCK_S or LOCK_X possibly ORed to
+ LOCK_GAP or LOCK_REC_NOT_GAP,
+ for a supremum record we regard this always a gap
+ type request */
rec_t* rec, /* in: record */
trx_t* trx) /* in: transaction */
{
lock_t* lock;
-
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad((mode == LOCK_X) || (mode == LOCK_S));
+ ut_ad(mutex_own(&kernel_mutex));
+ ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S
+ || (precise_mode & LOCK_MODE_MASK) == LOCK_X);
+ ut_ad(!(precise_mode & LOCK_INSERT_INTENTION));
+
lock = lock_rec_get_first(rec);
while (lock) {
if (lock->trx == trx
- && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)
+ && lock_mode_stronger_or_eq(lock_get_mode(lock),
+ precise_mode & LOCK_MODE_MASK)
&& !lock_get_wait(lock)
- && !lock_rec_get_insert_intention(lock)
- && !lock_rec_get_gap(lock)) {
+ && (!lock_rec_get_rec_not_gap(lock)
+ || (precise_mode & LOCK_REC_NOT_GAP)
+ || page_rec_is_supremum(rec))
+ && (!lock_rec_get_gap(lock)
+ || (precise_mode & LOCK_GAP)
+ || page_rec_is_supremum(rec))
+ && (!lock_rec_get_insert_intention(lock))) {
return(lock);
}
@@ -1429,7 +1431,7 @@ lock_t*
lock_rec_other_has_expl_req(
/*========================*/
/* out: lock or NULL */
- ulint mode, /* in: lock mode */
+ ulint mode, /* in: LOCK_S or LOCK_X */
ulint gap, /* in: LOCK_GAP if also gap locks are taken
into account, or 0 if not */
ulint wait, /* in: LOCK_WAIT if also waiting locks are
@@ -1471,27 +1473,21 @@ lock_t*
lock_rec_other_has_conflicting(
/*===========================*/
/* out: lock or NULL */
- ulint mode, /* in: lock mode of the lock we are going to reserve */
- ulint gap, /* in: LOCK_GAP if we are going to reserve a gap type
- lock, else 0 */
- ulint insert_intention,
- /* in: LOCK_INSERT_INTENTION if we are going to
- reserve an insert intention lock */
+ ulint mode, /* in: LOCK_S or LOCK_X,
+ possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP,
+ LOCK_INSERT_INTENTION */
rec_t* rec, /* in: record to look at */
trx_t* trx) /* in: our transaction */
{
lock_t* lock;
ut_ad(mutex_own(&kernel_mutex));
- ut_ad(mode == LOCK_X || mode == LOCK_S);
- ut_ad(gap == 0 || gap == LOCK_GAP);
- ut_ad(insert_intention == LOCK_INSERT_INTENTION
- || insert_intention == 0);
+
lock = lock_rec_get_first(rec);
while (lock) {
- if (lock_rec_has_to_wait(trx, mode, gap, insert_intention,
- lock)) {
+ if (lock_rec_has_to_wait(trx, mode, lock)) {
+
return(lock);
}
@@ -1607,14 +1603,14 @@ lock_rec_create(
page_no = buf_frame_get_page_no(page);
heap_no = rec_get_heap_no(rec);
- /* If rec is the supremum record, then we reset the gap bit, as
- all locks on the supremum are automatically of the gap type, and
- we try to avoid unnecessary memory consumption of a new record lock
- struct for a gap type lock */
+ /* If rec is the supremum record, then we reset the gap and
+ LOCK_REC_NOT_GAP bits, as all locks on the supremum are
+ automatically of the gap type */
if (rec == page_get_supremum_rec(page)) {
+ ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
- type_mode = type_mode & ~LOCK_GAP;
+ type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
}
/* Make lock bitmap bigger by a safety margin */
@@ -1666,10 +1662,14 @@ ulint
lock_rec_enqueue_waiting(
/*=====================*/
/* out: DB_LOCK_WAIT, DB_DEADLOCK, or
- DB_QUE_THR_SUSPENDED */
+ DB_QUE_THR_SUSPENDED, or DB_SUCCESS;
+ DB_SUCCESS means that there was a deadlock,
+ but another transaction was chosen as a
+ victim, and we got the lock immediately:
+ no need to wait then */
ulint type_mode,/* in: lock mode this transaction is
- requesting: LOCK_S or LOCK_X, ORed with
- LOCK_GAP if a gap lock is requested, ORed
+ requesting: LOCK_S or LOCK_X, possibly ORed
+ with LOCK_GAP or LOCK_REC_NOT_GAP, ORed
with LOCK_INSERT_INTENTION if this waiting
lock request is set when performing an
insert of an index record */
@@ -1718,7 +1718,16 @@ index->table_name);
return(DB_DEADLOCK);
}
+ /* If there was a deadlock but we chose another transaction as a
+ victim, it is possible that we already have the lock now granted! */
+
+ if (trx->wait_lock == NULL) {
+
+ return(DB_SUCCESS);
+ }
+
trx->que_state = TRX_QUE_LOCK_WAIT;
+ trx->was_chosen_as_deadlock_victim = FALSE;
trx->wait_started = time(NULL);
ut_a(que_thr_stop(thr));
@@ -1744,8 +1753,8 @@ lock_rec_add_to_queue(
/*==================*/
/* out: lock where the bit was set, NULL if out
of memory */
- ulint type_mode,/* in: lock mode, wait, and gap flags; type
- is ignored and replaced by LOCK_REC */
+ ulint type_mode,/* in: lock mode, wait, gap etc. flags;
+ type is ignored and replaced by LOCK_REC */
rec_t* rec, /* in: record on page */
dict_index_t* index, /* in: index of record */
trx_t* trx) /* in: transaction */
@@ -1759,12 +1768,11 @@ lock_rec_add_to_queue(
ut_ad(mutex_own(&kernel_mutex));
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_S)
- || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,
- rec, trx));
+ || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, rec, trx));
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_X)
- || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
- rec, trx));
+ || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, rec, trx));
+
type_mode = type_mode | LOCK_REC;
page = buf_frame_align(rec);
@@ -1775,12 +1783,15 @@ lock_rec_add_to_queue(
struct for a gap type lock */
if (rec == page_get_supremum_rec(page)) {
+ ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
- type_mode = type_mode & ~LOCK_GAP;
+ /* There should never be LOCK_REC_NOT_GAP on a supremum
+ record, but let us play safe */
+
+ type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
}
- /* Look for a waiting lock request on the same record, or for a
- similar record lock on the same page */
+ /* Look for a waiting lock request on the same record or on a gap */
heap_no = rec_get_heap_no(rec);
lock = lock_rec_get_first_on_page(rec);
@@ -1795,6 +1806,9 @@ lock_rec_add_to_queue(
lock = lock_rec_get_next_on_page(lock);
}
+ /* Look for a similar record lock on the same page: if one is found
+ and there are no waiting lock requests, we can just set the bit */
+
similar_lock = lock_rec_find_similar_on_page(type_mode, rec, trx);
if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) {
@@ -1822,7 +1836,8 @@ lock_rec_lock_fast(
ibool impl, /* in: if TRUE, no lock is set if no wait
is necessary: we assume that the caller will
set an implicit lock */
- ulint mode, /* in: lock mode */
+ ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
+ ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index of record */
que_thr_t* thr) /* in: query thread */
@@ -1831,8 +1846,16 @@ lock_rec_lock_fast(
ulint heap_no;
ut_ad(mutex_own(&kernel_mutex));
- ut_ad((mode == LOCK_X) || (mode == LOCK_S));
-
+ ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
+ || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
+ ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
+ || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
+ ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
+ || (LOCK_MODE_MASK & mode) == LOCK_X);
+ ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
+ || mode - (LOCK_MODE_MASK & mode) == 0
+ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
+
heap_no = rec_get_heap_no(rec);
lock = lock_rec_get_first_on_page(rec);
@@ -1877,7 +1900,8 @@ lock_rec_lock_slow(
ibool impl, /* in: if TRUE, no lock is set if no wait is
necessary: we assume that the caller will set
an implicit lock */
- ulint mode, /* in: lock mode */
+ ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
+ ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index of record */
que_thr_t* thr) /* in: query thread */
@@ -1886,20 +1910,24 @@ lock_rec_lock_slow(
ulint err;
ut_ad(mutex_own(&kernel_mutex));
- ut_ad((mode == LOCK_X) || (mode == LOCK_S));
-
+ ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
+ || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
+ ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
+ || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
+ ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
+ || (LOCK_MODE_MASK & mode) == LOCK_X);
+ ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
+ || mode - (LOCK_MODE_MASK & mode) == 0
+ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
+
trx = thr_get_trx(thr);
-
- ut_ad((mode != LOCK_S) || lock_table_has(trx, index->table,
- LOCK_IS));
- ut_ad((mode != LOCK_X) || lock_table_has(trx, index->table,
- LOCK_IX));
+
if (lock_rec_has_expl(mode, rec, trx)) {
/* The trx already has a strong enough lock on rec: do
nothing */
err = DB_SUCCESS;
- } else if (lock_rec_other_has_conflicting(mode, 0, 0, rec, trx)) {
+ } else if (lock_rec_other_has_conflicting(mode, rec, trx)) {
/* If another transaction has a non-gap conflicting request in
the queue, as this transaction does not have a lock strong
@@ -1935,7 +1963,8 @@ lock_rec_lock(
ibool impl, /* in: if TRUE, no lock is set if no wait is
necessary: we assume that the caller will set
an implicit lock */
- ulint mode, /* in: lock mode */
+ ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
+ ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index of record */
que_thr_t* thr) /* in: query thread */
@@ -1943,11 +1972,16 @@ lock_rec_lock(
ulint err;
ut_ad(mutex_own(&kernel_mutex));
- ut_ad((mode != LOCK_S) || lock_table_has(thr_get_trx(thr),
- index->table, LOCK_IS));
- ut_ad((mode != LOCK_X) || lock_table_has(thr_get_trx(thr),
- index->table, LOCK_IX));
-
+ ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
+ || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
+ ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
+ || lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
+ ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
+ || (LOCK_MODE_MASK & mode) == LOCK_X);
+ ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
+ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
+ || mode - (LOCK_MODE_MASK & mode) == 0);
+
if (lock_rec_lock_fast(impl, mode, rec, index, thr)) {
/* We try a simplified and faster subroutine for the most
@@ -2011,26 +2045,33 @@ lock_grant(
ut_ad(mutex_own(&kernel_mutex));
lock_reset_lock_and_trx_wait(lock);
-
- if (lock_get_mode(lock) == LOCK_AUTO_INC) {
- if (lock->trx->auto_inc_lock != NULL) {
- fprintf(stderr,
- "InnoDB: Error: trx already had an AUTO-INC lock!\n");
- }
+ if (lock_get_mode(lock) == LOCK_AUTO_INC) {
- /* Store pointer to lock to trx so that we know to
- release it at the end of the SQL statement */
+ if (lock->trx->auto_inc_lock != NULL) {
+ fprintf(stderr,
+ "InnoDB: Error: trx already had an AUTO-INC lock!\n");
+ }
- lock->trx->auto_inc_lock = lock;
- }
+ /* Store pointer to lock to trx so that we know to
+ release it at the end of the SQL statement */
+
+ lock->trx->auto_inc_lock = lock;
+ }
if (lock_print_waits) {
printf("Lock wait for trx %lu ends\n",
ut_dulint_get_low(lock->trx->id));
}
+
+ /* If we are resolving a deadlock by choosing another transaction
+ as a victim, then our original transaction may not be in the
+ TRX_QUE_LOCK_WAIT state, and there is no need to end the lock wait
+ for it */
- trx_end_lock_wait(lock->trx);
+ if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) {
+ trx_end_lock_wait(lock->trx);
+ }
}
/*****************************************************************
@@ -2080,7 +2121,7 @@ lock_rec_dequeue_from_page(
ut_ad(lock_get_type(in_lock) == LOCK_REC);
trx = in_lock->trx;
-
+
space = in_lock->un_member.rec_lock.space;
page_no = in_lock->un_member.rec_lock.page_no;
@@ -2199,9 +2240,10 @@ lock_rec_reset_and_release_wait(
}
/*****************************************************************
-Makes a record to inherit the locks of another record as gap type locks, but
-does not reset the lock bits of the other record. Also waiting lock requests
-on rec are inherited as GRANTED gap locks. */
+Makes a record to inherit the locks (except LOCK_INSERT_INTENTION type)
+of another record as gap type locks, but does not reset the lock bits of
+the other record. Also waiting lock requests on rec are inherited as
+GRANTED gap locks. */
void
lock_rec_inherit_to_gap(
@@ -2217,9 +2259,45 @@ lock_rec_inherit_to_gap(
lock = lock_rec_get_first(rec);
while (lock != NULL) {
- lock_rec_add_to_queue(((lock->type_mode | LOCK_GAP)
- & ~LOCK_WAIT),
+ if (!lock_rec_get_insert_intention(lock)) {
+
+ lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
+ | LOCK_GAP,
heir, lock->index, lock->trx);
+ }
+
+ lock = lock_rec_get_next(rec, lock);
+ }
+}
+
+/*****************************************************************
+Makes a record to inherit the gap locks (except LOCK_INSERT_INTENTION type)
+of another record as gap type locks, but does not reset the lock bits of the
+other record. Also waiting lock requests are inherited as GRANTED gap locks. */
+
+void
+lock_rec_inherit_to_gap_if_gap_lock(
+/*================================*/
+ rec_t* heir, /* in: record which inherits */
+ rec_t* rec) /* in: record from which inherited; does NOT reset
+ the locks on this record */
+{
+ lock_t* lock;
+
+ ut_ad(mutex_own(&kernel_mutex));
+
+ lock = lock_rec_get_first(rec);
+
+ while (lock != NULL) {
+ if (!lock_rec_get_insert_intention(lock)
+ && (page_rec_is_supremum(rec)
+ || !lock_rec_get_rec_not_gap(lock))) {
+
+ lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
+ | LOCK_GAP,
+ heir, lock->index, lock->trx);
+ }
+
lock = lock_rec_get_next(rec, lock);
}
}
@@ -2778,9 +2856,10 @@ lock_update_insert(
{
lock_mutex_enter_kernel();
- /* Inherit the locks for rec, in gap mode, from the next record */
+ /* Inherit the gap-locking locks for rec, in gap mode, from the next
+ record */
- lock_rec_inherit_to_gap(rec, page_rec_get_next(rec));
+ lock_rec_inherit_to_gap_if_gap_lock(rec, page_rec_get_next(rec));
lock_mutex_exit_kernel();
}
@@ -2859,20 +2938,23 @@ static
ibool
lock_deadlock_occurs(
/*=================*/
- /* out: TRUE if a deadlock was detected */
+ /* out: TRUE if a deadlock was detected and we
+ chose trx as a victim; FALSE if no deadlock, or
+ there was a deadlock, but we chose other
+ transaction(s) as victim(s) */
lock_t* lock, /* in: lock the transaction is requesting */
trx_t* trx) /* in: transaction */
{
dict_table_t* table;
dict_index_t* index;
trx_t* mark_trx;
- ibool ret;
+ ulint ret;
ulint cost = 0;
char* err_buf;
ut_ad(trx && lock);
ut_ad(mutex_own(&kernel_mutex));
-
+retry:
/* We check that adding this trx to the waits-for graph
does not produce a cycle. First mark all active transactions
with 0: */
@@ -2886,7 +2968,14 @@ lock_deadlock_occurs(
ret = lock_deadlock_recursive(trx, trx, lock, &cost);
- if (ret) {
+ if (ret == LOCK_VICTIM_IS_OTHER) {
+ /* We chose some other trx as a victim: retry if there still
+ is a deadlock */
+
+ goto retry;
+ }
+
+ if (ret == LOCK_VICTIM_IS_START) {
if (lock_get_type(lock) == LOCK_TABLE) {
table = lock->un_member.tab_lock.table;
index = NULL;
@@ -2898,19 +2987,6 @@ lock_deadlock_occurs(
lock_deadlock_found = TRUE;
err_buf = lock_latest_err_buf + strlen(lock_latest_err_buf);
-
- err_buf += sprintf(err_buf,
- "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
-
- ut_a(err_buf <= lock_latest_err_buf + 4000);
-
- if (lock_get_type(lock) == LOCK_REC) {
- lock_rec_print(err_buf, lock);
- err_buf += strlen(err_buf);
- } else {
- lock_table_print(err_buf, lock);
- err_buf += strlen(err_buf);
- }
ut_a(err_buf <= lock_latest_err_buf + 4000);
@@ -2923,30 +2999,39 @@ lock_deadlock_occurs(
sess_raise_error_low(trx, DB_DEADLOCK, lock->type_mode, table,
index, NULL, NULL, NULL);
*/
+
+ return(TRUE);
}
- return(ret);
+ return(FALSE);
}
/************************************************************************
Looks recursively for a deadlock. */
static
-ibool
+ulint
lock_deadlock_recursive(
/*====================*/
- /* out: TRUE if a deadlock was detected
- or the calculation took too long */
+ /* out: 0 if no deadlock found,
+ LOCK_VICTIM_IS_START if there was a deadlock
+ and we chose 'start' as the victim,
+ LOCK_VICTIM_IS_OTHER if a deadlock
+ was found and we chose some other trx as a
+ victim: we must do the search again in this
+ last case because there may be another
+ deadlock! */
trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
ulint* cost) /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
- we return TRUE */
+ we return LOCK_VICTIM_IS_START */
{
lock_t* lock;
ulint bit_no;
trx_t* lock_trx;
char* err_buf;
+ ulint ret;
ut_a(trx && start && wait_lock);
ut_ad(mutex_own(&kernel_mutex));
@@ -2955,14 +3040,14 @@ lock_deadlock_recursive(
/* We have already exhaustively searched the subtree starting
from this trx */
- return(FALSE);
+ return(0);
}
*cost = *cost + 1;
if (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK) {
- return(TRUE);
+ return(LOCK_VICTIM_IS_START);
}
lock = wait_lock;
@@ -2998,6 +3083,9 @@ lock_deadlock_recursive(
lock_trx = lock->trx;
if (lock_trx == start) {
+ /* We came back to the recursion starting
+ point: a deadlock detected */
+
err_buf = lock_latest_err_buf;
ut_sprintf_timestamp(err_buf);
@@ -3045,11 +3133,60 @@ lock_deadlock_recursive(
ut_a(err_buf <= lock_latest_err_buf + 4000);
+ err_buf += sprintf(err_buf,
+ "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
+
+ ut_a(err_buf <= lock_latest_err_buf + 4000);
+
+ if (lock_get_type(start->wait_lock)
+ == LOCK_REC) {
+ lock_rec_print(err_buf,
+ start->wait_lock);
+ err_buf += strlen(err_buf);
+ } else {
+ lock_table_print(err_buf,
+ start->wait_lock);
+ err_buf += strlen(err_buf);
+ }
+
if (lock_print_waits) {
printf("Deadlock detected\n");
}
- return(TRUE);
+ if (ut_dulint_cmp(wait_lock->trx->undo_no,
+ start->undo_no) >= 0) {
+ /* Our recursion starting point
+ transaction is 'smaller', let us
+ choose 'start' as the victim and roll
+ back it */
+
+ return(LOCK_VICTIM_IS_START);
+ }
+
+ lock_deadlock_found = TRUE;
+
+ ut_a(err_buf <= lock_latest_err_buf + 4000);
+
+ /* Let us choose the transaction of wait_lock
+ as a victim to try to avoid deadlocking our
+ recursion starting point transaction */
+
+ err_buf += sprintf(err_buf,
+ "*** WE ROLL BACK TRANSACTION (1)\n");
+
+ wait_lock->trx->was_chosen_as_deadlock_victim
+ = TRUE;
+
+ lock_cancel_waiting_and_release(wait_lock);
+
+ /* Since trx and wait_lock are no longer
+ in the waits-for graph, we can return FALSE;
+ note that our selective algorithm can choose
+ several transactions as victims, but still
+ we may end up rolling back also the recursion
+ starting point transaction! */
+
+ return(LOCK_VICTIM_IS_OTHER);
}
if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
@@ -3058,10 +3195,11 @@ lock_deadlock_recursive(
incompatible mode, and is itself waiting for
a lock */
- if (lock_deadlock_recursive(start, lock_trx,
- lock_trx->wait_lock, cost)) {
+ ret = lock_deadlock_recursive(start, lock_trx,
+ lock_trx->wait_lock, cost);
+ if (ret != 0) {
- return(TRUE);
+ return(ret);
}
}
}
@@ -3153,12 +3291,16 @@ lock_table_remove_low(
/*************************************************************************
Enqueues a waiting request for a table lock which cannot be granted
immediately. Checks for deadlocks. */
-
+static
ulint
lock_table_enqueue_waiting(
/*=======================*/
/* out: DB_LOCK_WAIT, DB_DEADLOCK, or
- DB_QUE_THR_SUSPENDED */
+ DB_QUE_THR_SUSPENDED, or DB_SUCCESS;
+ DB_SUCCESS means that there was a deadlock,
+ but another transaction was chosen as a
+ victim, and we got the lock immediately:
+ no need to wait then */
ulint mode, /* in: lock mode this transaction is
requesting */
dict_table_t* table, /* in: table */
@@ -3205,7 +3347,15 @@ table->name);
return(DB_DEADLOCK);
}
+ if (trx->wait_lock == NULL) {
+ /* Deadlock resolution chose another transaction as a victim,
+ and we accidentally got our lock granted! */
+
+ return(DB_SUCCESS);
+ }
+
trx->que_state = TRX_QUE_LOCK_WAIT;
+ trx->was_chosen_as_deadlock_victim = FALSE;
trx->wait_started = time(NULL);
ut_a(que_thr_stop(thr));
@@ -3292,7 +3442,7 @@ lock_table(
if (lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode)) {
/* Another trx has a request on the table in an incompatible
- mode: this trx must wait */
+ mode: this trx may have to wait */
err = lock_table_enqueue_waiting(mode, table, thr);
@@ -3659,7 +3809,11 @@ lock_rec_print(
}
if (lock_rec_get_gap(lock)) {
- buf += sprintf(buf, " gap type lock");
+ buf += sprintf(buf, " locks gap before rec");
+ }
+
+ if (lock_rec_get_rec_not_gap(lock)) {
+ buf += sprintf(buf, " locks rec but not gap");
}
if (lock_rec_get_insert_intention(lock)) {
@@ -3776,8 +3930,8 @@ lock_print_info(
mtr_t mtr;
if (buf_end - buf < 600) {
- sprintf(buf, "... output truncated!\n");
-
+ sprintf(buf, "... output truncated!\n");
+
return;
}
@@ -3802,8 +3956,8 @@ lock_print_info(
if ((ulint)(buf_end - buf)
< 100 + strlen(lock_latest_err_buf)) {
- lock_mutex_exit_kernel();
- sprintf(buf, "... output truncated!\n");
+ lock_mutex_exit_kernel();
+ sprintf(buf, "... output truncated!\n");
return;
}
@@ -3826,8 +3980,8 @@ lock_print_info(
while (trx) {
if (buf_end - buf < 900) {
- lock_mutex_exit_kernel();
- sprintf(buf, "... output truncated!\n");
+ lock_mutex_exit_kernel();
+ sprintf(buf, "... output truncated!\n");
return;
}
@@ -3879,8 +4033,8 @@ loop:
buf += strlen(buf);
if (buf_end - buf < 500) {
- lock_mutex_exit_kernel();
- sprintf(buf, "... output truncated!\n");
+ lock_mutex_exit_kernel();
+ sprintf(buf, "... output truncated!\n");
return;
}
@@ -3936,7 +4090,7 @@ loop:
}
if (buf_end - buf < 500) {
- lock_mutex_exit_kernel();
+ lock_mutex_exit_kernel();
sprintf(buf, "... output truncated!\n");
return;
@@ -4080,7 +4234,8 @@ lock_rec_queue_validate(
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
LOCK_WAIT, rec, impl_trx)) {
- ut_a(lock_rec_has_expl(LOCK_X, rec, impl_trx));
+ ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
+ impl_trx));
}
}
@@ -4095,7 +4250,8 @@ lock_rec_queue_validate(
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
LOCK_WAIT, rec, impl_trx)) {
- ut_a(lock_rec_has_expl(LOCK_X, rec, impl_trx));
+ ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
+ impl_trx));
}
}
@@ -4359,8 +4515,8 @@ lock_rec_insert_check_and_lock(
*inherit = TRUE;
- /* If another transaction has an explicit lock request, gap or not,
- waiting or granted, on the successor, the insert has to wait.
+ /* If another transaction has an explicit lock request which locks
+ the gap, waiting or granted, on the successor, the insert has to wait.
An exception is the case where the lock by the another transaction
is a gap type lock which it placed to wait for its turn to insert. We
@@ -4369,8 +4525,10 @@ lock_rec_insert_check_and_lock(
had to wait for their insert. Both had waiting gap type lock requests
on the successor, which produced an unnecessary deadlock. */
- if (lock_rec_other_has_conflicting(LOCK_X, LOCK_GAP,
- LOCK_INSERT_INTENTION, next_rec, trx)) {
+ if (lock_rec_other_has_conflicting(LOCK_X | LOCK_GAP
+ | LOCK_INSERT_INTENTION, next_rec, trx)) {
+
+ /* Note that we may get DB_SUCCESS also here! */
err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP
| LOCK_INSERT_INTENTION,
next_rec, index, thr);
@@ -4418,9 +4576,11 @@ lock_rec_convert_impl_to_expl(
/* If the transaction has no explicit x-lock set on the
record, set one for it */
- if (!lock_rec_has_expl(LOCK_X, rec, impl_trx)) {
+ if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
+ impl_trx)) {
- lock_rec_add_to_queue(LOCK_REC | LOCK_X, rec, index,
+ lock_rec_add_to_queue(LOCK_REC | LOCK_X
+ | LOCK_REC_NOT_GAP, rec, index,
impl_trx);
}
}
@@ -4466,7 +4626,7 @@ lock_clust_rec_modify_check_and_lock(
lock_rec_convert_impl_to_expl(rec, index);
- err = lock_rec_lock(TRUE, LOCK_X, rec, index, thr);
+ err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
lock_mutex_exit_kernel();
@@ -4511,7 +4671,7 @@ lock_sec_rec_modify_check_and_lock(
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
- err = lock_rec_lock(TRUE, LOCK_X, rec, index, thr);
+ err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
lock_mutex_exit_kernel();
@@ -4545,6 +4705,8 @@ lock_sec_rec_read_check_and_lock(
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
+ ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
+ LOCK_REC_NOT_GAP */
que_thr_t* thr) /* in: query thread */
{
ulint err;
@@ -4576,7 +4738,7 @@ lock_sec_rec_read_check_and_lock(
lock_rec_convert_impl_to_expl(rec, index);
}
- err = lock_rec_lock(FALSE, mode, rec, index, thr);
+ err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
lock_mutex_exit_kernel();
@@ -4607,13 +4769,16 @@ lock_clust_rec_read_check_and_lock(
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
+ ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
+ LOCK_REC_NOT_GAP */
que_thr_t* thr) /* in: query thread */
{
ulint err;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
-
+ ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
+ || gap_mode == LOCK_REC_NOT_GAP);
if (flags & BTR_NO_LOCKING_FLAG) {
return(DB_SUCCESS);
@@ -4631,7 +4796,7 @@ lock_clust_rec_read_check_and_lock(
lock_rec_convert_impl_to_expl(rec, index);
}
- err = lock_rec_lock(FALSE, mode, rec, index, thr);
+ err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
lock_mutex_exit_kernel();
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index c798a08e2de..f9b785ccbd5 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -1654,8 +1654,8 @@ log_reset_first_header_and_checkpoint(
lsn = ut_dulint_add(start, LOG_BLOCK_HDR_SIZE);
/* Write the label of ibbackup --restore */
- sprintf(hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "ibbackup ");
- ut_sprintf_timestamp(hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
+ sprintf((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "ibbackup ");
+ ut_sprintf_timestamp((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
+ strlen("ibbackup "));
buf = hdr_buf + LOG_CHECKPOINT_1;
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 1223f9b6041..dfe67c444b4 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -69,6 +69,8 @@ ulint recv_previous_parsed_rec_type = 999999;
ulint recv_previous_parsed_rec_offset = 0;
ulint recv_previous_parsed_rec_is_multi = 0;
+ulint recv_max_parsed_page_no = 0;
+
/************************************************************
Creates the recovery system. */
@@ -141,7 +143,13 @@ recv_sys_empty_hash(void)
/*=====================*/
{
ut_ad(mutex_own(&(recv_sys->mutex)));
- ut_a(recv_sys->n_addrs == 0);
+ if (recv_sys->n_addrs != 0) {
+ fprintf(stderr,
+"InnoDB: Error: %lu pages with log records were left unprocessed!\n"
+"InnoDB: Maximum page number with log records on it %lu\n",
+ recv_sys->n_addrs, recv_max_parsed_page_no);
+ ut_a(0);
+ }
hash_table_free(recv_sys->addr_hash);
mem_heap_empty(recv_sys->heap);
@@ -1361,6 +1369,14 @@ recv_apply_log_recs_for_backup(
n_pages_total += file_sizes[i];
}
+ if (recv_max_parsed_page_no >= n_pages_total) {
+ printf(
+"InnoDB: Error: tablespace size %lu pages, but a log record on page %lu!\n"
+"InnoDB: Are you sure you have specified all the ibdata files right in\n"
+"InnoDB: the my.cnf file you gave as the argument to ibbackup --restore?\n",
+ n_pages_total, recv_max_parsed_page_no);
+ }
+
printf(
"InnoDB: Starting an apply batch of log records to the database...\n"
"InnoDB: Progress in percents: ");
@@ -1381,7 +1397,7 @@ recv_apply_log_recs_for_backup(
&success);
if (!success) {
printf(
-"InnoDB: Error: cannot open %lu'th data file %s\n", nth_file);
+"InnoDB: Error: cannot open %lu'th data file\n", nth_file);
exit(1);
}
@@ -1397,7 +1413,7 @@ recv_apply_log_recs_for_backup(
UNIV_PAGE_SIZE);
if (!success) {
printf(
-"InnoDB: Error: cannot read page no %lu from %lu'th data file %s\n",
+"InnoDB: Error: cannot read page no %lu from %lu'th data file\n",
nth_page_in_file, nth_file);
exit(1);
@@ -1425,7 +1441,7 @@ recv_apply_log_recs_for_backup(
UNIV_PAGE_SIZE);
if (!success) {
printf(
-"InnoDB: Error: cannot write page no %lu to %lu'th data file %s\n",
+"InnoDB: Error: cannot write page no %lu to %lu'th data file\n",
nth_page_in_file, nth_file);
exit(1);
@@ -1701,6 +1717,10 @@ recv_parse_log_rec(
return(0);
}
+ if (*page_no > recv_max_parsed_page_no) {
+ recv_max_parsed_page_no = *page_no;
+ }
+
return(new_ptr - ptr);
}
@@ -1779,7 +1799,7 @@ recv_report_corrupt_log(
"InnoDB: Recv offset %lu, prev %lu\n",
recv_previous_parsed_rec_type,
recv_previous_parsed_rec_is_multi,
- ptr - recv_sys->buf,
+ (ulint)(ptr - recv_sys->buf),
recv_previous_parsed_rec_offset);
if ((ulint)(ptr - recv_sys->buf + 100)
diff --git a/innobase/mem/mem0dbg.c b/innobase/mem/mem0dbg.c
index 23585e494b8..22d0bab0da2 100644
--- a/innobase/mem/mem0dbg.c
+++ b/innobase/mem/mem0dbg.c
@@ -347,9 +347,19 @@ mem_hash_remove(
NULL, NULL);
if (error) {
printf("Inconsistency in memory heap or buffer n:o %lu created\n",
- node->nth_heap);
+ node->nth_heap);
printf("in %s line %lu and tried to free in %s line %lu.\n",
node->file_name, node->line, file_name, line);
+
+ printf(
+ "Hex dump of 400 bytes around memory heap first block start:\n");
+
+ ut_print_buf((byte*)(node->heap) - 200, 400);
+
+ printf("\nDump of the mem heap:\n");
+
+ mem_heap_validate_or_print(node->heap, NULL, TRUE, &error, &size,
+ NULL, NULL);
ut_error;
}
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 098d5b25e89..9eae358c7fb 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -148,7 +148,7 @@ Gets the operating system version. Currently works only on Windows. */
ulint
os_get_os_version(void)
/*===================*/
- /* out: OS_WIN95, OS_WIN31, OS_WINNT (2000 == NT) */
+ /* out: OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
{
#ifdef __WIN__
OSVERSIONINFO os_info;
@@ -162,7 +162,11 @@ os_get_os_version(void)
} else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
return(OS_WIN95);
} else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- return(OS_WINNT);
+ if (os_info.dwMajorVersion <= 4) {
+ return(OS_WINNT);
+ } else {
+ return(OS_WIN2000);
+ }
} else {
ut_error;
return(0);
@@ -268,9 +272,7 @@ os_file_get_last_error(void)
}
/********************************************************************
-Does error handling when a file operation fails. If we have run out
-of disk space, then the user can clean the disk. If we do not find
-a specified file, then the user can copy it to disk. */
+Does error handling when a file operation fails. */
static
ibool
os_file_handle_error(
@@ -503,7 +505,11 @@ try_again:
value 2 denotes that we do not flush the log at every
commit, but only once per second */
} else {
- attributes = attributes | FILE_FLAG_NO_BUFFERING;
+ if (srv_win_file_flush_method ==
+ SRV_WIN_IO_UNBUFFERED) {
+ attributes = attributes
+ | FILE_FLAG_NO_BUFFERING;
+ }
}
#endif
} else if (purpose == OS_FILE_NORMAL) {
@@ -514,7 +520,11 @@ try_again:
value 2 denotes that we do not flush the log at every
commit, but only once per second */
} else {
- attributes = attributes | FILE_FLAG_NO_BUFFERING;
+ if (srv_win_file_flush_method ==
+ SRV_WIN_IO_UNBUFFERED) {
+ attributes = attributes
+ | FILE_FLAG_NO_BUFFERING;
+ }
}
#endif
} else {
@@ -1752,6 +1762,7 @@ os_aio(
os_aio_array_t* array;
os_aio_slot_t* slot;
#ifdef WIN_ASYNC_IO
+ ibool retval;
BOOL ret = TRUE;
DWORD len = n;
void* dummy_mess1;
@@ -1824,6 +1835,8 @@ try_again:
if (os_aio_use_native_aio) {
#ifdef WIN_ASYNC_IO
os_n_file_reads++;
+ os_bytes_read_since_printout += len;
+
ret = ReadFile(file, buf, (DWORD)n, &len,
&(slot->control));
#elif defined(POSIX_ASYNC_IO)
@@ -1870,10 +1883,12 @@ try_again:
where we also use async i/o: in Windows we must
use the same wait mechanism as for async i/o */
- return(os_aio_windows_handle(ULINT_UNDEFINED,
+ retval = os_aio_windows_handle(ULINT_UNDEFINED,
slot->pos,
&dummy_mess1, &dummy_mess2,
- &dummy_type));
+ &dummy_type);
+
+ return(retval);
}
return(TRUE);
@@ -1897,8 +1912,6 @@ try_again:
goto try_again;
}
- ut_error;
-
return(FALSE);
}
@@ -1958,14 +1971,14 @@ os_aio_windows_handle(
n = array->n_slots / array->n_segments;
if (array == os_aio_sync_array) {
- srv_io_thread_op_info[orig_seg] = "wait windows aio for 1 page";
+ srv_io_thread_op_info[orig_seg] = "wait Windows aio for 1 page";
ut_ad(pos < array->n_slots);
os_event_wait(array->events[pos]);
i = pos;
} else {
srv_io_thread_op_info[orig_seg] =
- "wait windows aio for n pages";
+ "wait Windows aio";
i = os_event_wait_multiple(n, (array->events) + segment * n);
}
@@ -1991,10 +2004,8 @@ os_aio_windows_handle(
ut_a(TRUE == os_file_flush(slot->file));
}
} else {
- os_file_get_last_error();
-
- ut_error;
-
+ os_file_handle_error(slot->file, slot->name);
+
ret_val = FALSE;
}
diff --git a/innobase/os/os0proc.c b/innobase/os/os0proc.c
index 43a2db4d306..1ee448a4a44 100644
--- a/innobase/os/os0proc.c
+++ b/innobase/os/os0proc.c
@@ -19,6 +19,23 @@ Created 9/30/1995 Heikki Tuuri
#include "ut0mem.h"
/********************************************************************
+Converts the current process id to a number. It is not guaranteed that the
+number is unique. In Linux returns the 'process number' of the current
+thread. That number is the same as one sees in 'top', for example. In Linux
+the thread id is not the same as one sees in 'top'. */
+
+ulint
+os_proc_get_number(void)
+/*====================*/
+{
+#ifdef __WIN__
+ return((ulint)GetCurrentProcessId());
+#else
+ return((ulint)getpid());
+#endif
+}
+
+/********************************************************************
Allocates non-cacheable memory. */
void*
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index 14677ede20f..bac1f23a1af 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -66,8 +66,12 @@ os_event_create(
event = ut_malloc(sizeof(struct os_event_struct));
os_fast_mutex_init(&(event->os_mutex));
- pthread_cond_init(&(event->cond_var), NULL);
+#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
+ pthread_cond_init(&(event->cond_var), pthread_condattr_default);
+#else
+ pthread_cond_init(&(event->cond_var), NULL);
+#endif
event->is_set = FALSE;
return(event);
@@ -441,8 +445,12 @@ os_fast_mutex_init(
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else
+#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
+ pthread_mutex_init(fast_mutex, pthread_mutexattr_default);
+#else
pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
#endif
+#endif
}
/**************************************************************
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index 48aea4b8abb..30404c4e66b 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -126,8 +126,10 @@ os_thread_create(
os_thread_t pthread;
pthread_attr_t attr;
+#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
pthread_attr_init(&attr);
-
+#endif
+
#ifdef UNIV_AIX
/* We must make sure a thread stack is at least 32 kB, otherwise
InnoDB might crash; we do not know if the default stack size on
@@ -142,16 +144,21 @@ os_thread_create(
exit(1);
}
#endif
- ret = pthread_create(&pthread, &attr, start_f, arg);
+#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
+ ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
+#else
+ ret = pthread_create(&pthread, &attr, start_f, arg);
+#endif
if (ret) {
fprintf(stderr,
"InnoDB: Error: pthread_create returned %d\n", ret);
exit(1);
}
+#if !(defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10))
pthread_attr_destroy(&attr);
-
+#endif
if (srv_set_thread_priorities) {
my_pthread_setprio(pthread, srv_query_thread_priority);
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 2909573b14b..bb49e9080ce 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -169,7 +169,7 @@ page_cur_search_with_match(
ut_ad(dtuple_check_typed(tuple));
ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE)
|| (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)
- || (mode == PAGE_CUR_DBG));
+ || (mode == PAGE_CUR_LE_OR_EXTENDS) || (mode == PAGE_CUR_DBG));
#ifdef PAGE_CUR_ADAPT
if ((page_header_get_field(page, PAGE_LEVEL) == 0)
@@ -232,9 +232,26 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
- up = mid;
- up_matched_fields = cur_matched_fields;
- up_matched_bytes = cur_matched_bytes;
+
+ if (mode == PAGE_CUR_LE_OR_EXTENDS
+ && dfield_get_len(dtuple_get_nth_field(tuple,
+ cur_matched_fields))
+ == cur_matched_bytes
+ && rec_get_nth_field_len(mid_rec,
+ cur_matched_fields)
+ != UNIV_SQL_NULL) {
+
+ /* This means current dfield is not SQL
+ NULL, and the current rec field extends it */
+
+ low = mid;
+ low_matched_fields = cur_matched_fields;
+ low_matched_bytes = cur_matched_bytes;
+ } else {
+ up = mid;
+ up_matched_fields = cur_matched_fields;
+ up_matched_bytes = cur_matched_bytes;
+ }
} else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) {
low = mid;
@@ -252,8 +269,8 @@ page_cur_search_with_match(
slot = page_dir_get_nth_slot(page, up);
up_rec = page_dir_slot_get_rec(slot);
- /* Perform linear search until the upper and lower records
- come to distance 1 of each other. */
+ /* Perform linear search until the upper and lower records come to
+ distance 1 of each other. */
while (page_rec_get_next(low_rec) != up_rec) {
@@ -272,10 +289,25 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
- up_rec = mid_rec;
- up_matched_fields = cur_matched_fields;
- up_matched_bytes = cur_matched_bytes;
-
+ if (mode == PAGE_CUR_LE_OR_EXTENDS
+ && dfield_get_len(dtuple_get_nth_field(tuple,
+ cur_matched_fields))
+ == cur_matched_bytes
+ && rec_get_nth_field_len(mid_rec,
+ cur_matched_fields)
+ != UNIV_SQL_NULL) {
+
+ /* This means current dfield is not SQL
+ NULL, and the current rec field extends it */
+
+ low = mid;
+ low_matched_fields = cur_matched_fields;
+ low_matched_bytes = cur_matched_bytes;
+ } else {
+ up_rec = mid_rec;
+ up_matched_fields = cur_matched_fields;
+ up_matched_bytes = cur_matched_bytes;
+ }
} else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) {
low_rec = mid_rec;
low_matched_fields = cur_matched_fields;
diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c
index ed74736c8da..7d240bdd5b0 100644
--- a/innobase/page/page0page.c
+++ b/innobase/page/page0page.c
@@ -1299,12 +1299,16 @@ page_rec_validate(
heap_no = rec_get_heap_no(rec);
if (!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED)) {
- fprintf(stderr, "Dir slot n owned too big %lu\n", n_owned);
+ fprintf(stderr,
+ "InnoDB: Dir slot of rec %lu, n owned too big %lu\n",
+ (ulint)(rec - page), n_owned);
return(FALSE);
}
if (!(heap_no < page_header_get_field(page, PAGE_N_HEAP))) {
- fprintf(stderr, "Heap no too big %lu %lu\n", heap_no,
+ fprintf(stderr,
+ "InnoDB: Heap no of rec %lu too big %lu %lu\n",
+ (ulint)(rec - page), heap_no,
page_header_get_field(page, PAGE_N_HEAP));
return(FALSE);
}
@@ -1313,6 +1317,194 @@ page_rec_validate(
}
/*******************************************************************
+This function checks the consistency of an index page when we do not
+know the index. This is also resilient so that this should never crash
+even if the page is total garbage. */
+
+ibool
+page_simple_validate(
+/*=================*/
+ /* out: TRUE if ok */
+ page_t* page) /* in: index page */
+{
+ page_cur_t cur;
+ page_dir_slot_t* slot;
+ ulint slot_no;
+ ulint n_slots;
+ rec_t* rec;
+ byte* rec_heap_top;
+ ulint count;
+ ulint own_count;
+ ibool ret = FALSE;
+
+ /* Check first that the record heap and the directory do not
+ overlap. */
+
+ n_slots = page_dir_get_n_slots(page);
+
+ if (n_slots > UNIV_PAGE_SIZE / 4) {
+ fprintf(stderr,
+ "InnoDB: Nonsensical number %lu of page dir slots\n", n_slots);
+
+ goto func_exit;
+ }
+
+ rec_heap_top = page_header_get_ptr(page, PAGE_HEAP_TOP);
+
+ if (rec_heap_top > page_dir_get_nth_slot(page, n_slots - 1)) {
+
+ fprintf(stderr,
+ "InnoDB: Record heap and dir overlap on a page, heap top %lu, dir %lu\n",
+ (ulint)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page),
+ (ulint)(page_dir_get_nth_slot(page, n_slots - 1) - page));
+
+ goto func_exit;
+ }
+
+ /* Validate the record list in a loop checking also that it is
+ consistent with the page record directory. */
+
+ count = 0;
+ own_count = 1;
+ slot_no = 0;
+ slot = page_dir_get_nth_slot(page, slot_no);
+
+ page_cur_set_before_first(page, &cur);
+
+ for (;;) {
+ rec = (&cur)->rec;
+
+ if (rec > rec_heap_top) {
+ fprintf(stderr,
+ "InnoDB: Record %lu is above rec heap top %lu\n",
+ (ulint)(rec - page), (ulint)(rec_heap_top - page));
+
+ goto func_exit;
+ }
+
+ if (rec_get_n_owned(rec) != 0) {
+ /* This is a record pointed to by a dir slot */
+ if (rec_get_n_owned(rec) != own_count) {
+
+ fprintf(stderr,
+ "InnoDB: Wrong owned count %lu, %lu, rec %lu\n",
+ rec_get_n_owned(rec), own_count,
+ (ulint)(rec - page));
+
+ goto func_exit;
+ }
+
+ if (page_dir_slot_get_rec(slot) != rec) {
+ fprintf(stderr,
+ "InnoDB: Dir slot does not point to right rec %lu\n",
+ (ulint)(rec - page));
+
+ goto func_exit;
+ }
+
+ own_count = 0;
+
+ if (!page_cur_is_after_last(&cur)) {
+ slot_no++;
+ slot = page_dir_get_nth_slot(page, slot_no);
+ }
+ }
+
+ if (page_cur_is_after_last(&cur)) {
+
+ break;
+ }
+
+ if (rec_get_next_offs(rec) < FIL_PAGE_DATA
+ || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
+ fprintf(stderr,
+ "InnoDB: Next record offset nonsensical %lu for rec %lu\n",
+ rec_get_next_offs(rec),
+ (ulint)(rec - page));
+
+ goto func_exit;
+ }
+
+ count++;
+
+ if (count > UNIV_PAGE_SIZE) {
+ fprintf(stderr,
+ "InnoDB: Page record list appears to be circular %lu\n",
+ count);
+ goto func_exit;
+ }
+
+ page_cur_move_to_next(&cur);
+ own_count++;
+ }
+
+ if (rec_get_n_owned(rec) == 0) {
+ fprintf(stderr, "InnoDB: n owned is zero in a supremum rec\n");
+
+ goto func_exit;
+ }
+
+ if (slot_no != n_slots - 1) {
+ fprintf(stderr, "InnoDB: n slots wrong %lu, %lu\n",
+ slot_no, n_slots - 1);
+ goto func_exit;
+ }
+
+ if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) {
+ fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n",
+ page_header_get_field(page, PAGE_N_RECS) + 2, count + 1);
+
+ goto func_exit;
+ }
+
+ /* Check then the free list */
+ rec = page_header_get_ptr(page, PAGE_FREE);
+
+ while (rec != NULL) {
+ if (rec < page + FIL_PAGE_DATA
+ || rec >= page + UNIV_PAGE_SIZE) {
+ fprintf(stderr,
+ "InnoDB: Free list record has a nonsensical offset %lu\n",
+ (ulint)(rec - page));
+
+ goto func_exit;
+ }
+
+ if (rec > rec_heap_top) {
+ fprintf(stderr,
+ "InnoDB: Free list record %lu is above rec heap top %lu\n",
+ (ulint)(rec - page), (ulint)(rec_heap_top - page));
+
+ goto func_exit;
+ }
+
+ count++;
+
+ if (count > UNIV_PAGE_SIZE) {
+ fprintf(stderr,
+ "InnoDB: Page free list appears to be circular %lu\n",
+ count);
+ goto func_exit;
+ }
+
+ rec = page_rec_get_next(rec);
+ }
+
+ if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
+
+ fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n",
+ page_header_get_field(page, PAGE_N_HEAP), count + 1);
+
+ goto func_exit;
+ }
+
+ ret = TRUE;
+
+func_exit:
+ return(ret);
+}
+
+/*******************************************************************
This function checks the consistency of an index page. */
ibool
@@ -1339,6 +1531,17 @@ page_validate(
ulint i;
char err_buf[1000];
+ if (!page_simple_validate(page)) {
+ fprintf(stderr,
+"InnoDB: Apparent corruption in page %lu in index %s in table %s\n",
+ buf_frame_get_page_no(page), index->name,
+ index->table_name);
+
+ buf_page_print(page);
+
+ return(FALSE);
+ }
+
heap = mem_heap_create(UNIV_PAGE_SIZE);
/* The following buffer is used to check that the
@@ -1357,7 +1560,7 @@ page_validate(
if (!(page_header_get_ptr(page, PAGE_HEAP_TOP) <=
page_dir_get_nth_slot(page, n_slots - 1))) {
fprintf(stderr,
- "Record heap and dir overlap on a page in index %s, %lu, %lu\n",
+"InnoDB: Record heap and dir overlap on a page in index %s, %lu, %lu\n",
index->name, (ulint)page_header_get_ptr(page, PAGE_HEAP_TOP),
(ulint)page_dir_get_nth_slot(page, n_slots - 1));
@@ -1385,10 +1588,14 @@ page_validate(
if ((count >= 2) && (!page_cur_is_after_last(&cur))) {
if (!(1 == cmp_rec_rec(rec, old_rec, index))) {
fprintf(stderr,
- "Records in wrong order in index %s\n",
- index->name);
+"InnoDB: Records in wrong order on page %lu index %s table %s\n",
+ buf_frame_get_page_no(page),
+ index->name,
+ index->table_name);
+
rec_sprintf(err_buf, 900, old_rec);
- fprintf(stderr, "InnoDB: record %s\n", err_buf);
+ fprintf(stderr,
+ "InnoDB: previous record %s\n", err_buf);
rec_sprintf(err_buf, 900, rec);
fprintf(stderr, "InnoDB: record %s\n", err_buf);
@@ -1410,7 +1617,7 @@ page_validate(
/* No other record may overlap this */
fprintf(stderr,
- "Record overlaps another in index %s \n",
+ "InnoDB: Record overlaps another in index %s \n",
index->name);
goto func_exit;
@@ -1423,7 +1630,7 @@ page_validate(
/* This is a record pointed to by a dir slot */
if (rec_get_n_owned(rec) != own_count) {
fprintf(stderr,
- "Wrong owned count %lu, %lu, in index %s\n",
+ "InnoDB: Wrong owned count %lu, %lu, in index %s\n",
rec_get_n_owned(rec), own_count,
index->name);
@@ -1432,7 +1639,7 @@ page_validate(
if (page_dir_slot_get_rec(slot) != rec) {
fprintf(stderr,
- "Dir slot does not point to right rec in %s\n",
+ "InnoDB: Dir slot does not point to right rec in %s\n",
index->name);
goto func_exit;
@@ -1454,7 +1661,7 @@ page_validate(
if (rec_get_next_offs(rec) < FIL_PAGE_DATA
|| rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
fprintf(stderr,
- "Next record offset wrong %lu in index %s\n",
+ "InnoDB: Next record offset wrong %lu in index %s\n",
rec_get_next_offs(rec), index->name);
goto func_exit;
@@ -1467,19 +1674,20 @@ page_validate(
}
if (rec_get_n_owned(rec) == 0) {
- fprintf(stderr, "n owned is zero in index %s\n", index->name);
+ fprintf(stderr,
+ "InnoDB: n owned is zero in index %s\n", index->name);
goto func_exit;
}
if (slot_no != n_slots - 1) {
- fprintf(stderr, "n slots wrong %lu %lu in index %s\n",
+ fprintf(stderr, "InnoDB: n slots wrong %lu %lu in index %s\n",
slot_no, n_slots - 1, index->name);
goto func_exit;
}
if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) {
- fprintf(stderr, "n recs wrong %lu %lu in index %s\n",
+ fprintf(stderr, "InnoDB: n recs wrong %lu %lu in index %s\n",
page_header_get_field(page, PAGE_N_RECS) + 2, count + 1,
index->name);
@@ -1487,7 +1695,8 @@ page_validate(
}
if (data_size != page_get_data_size(page)) {
- fprintf(stderr, "Summed data size %lu, returned by func %lu\n",
+ fprintf(stderr,
+ "InnoDB: Summed data size %lu, returned by func %lu\n",
data_size, page_get_data_size(page));
goto func_exit;
}
@@ -1508,7 +1717,7 @@ page_validate(
if (buf[offs + i] != 0) {
fprintf(stderr,
- "Record overlaps another in free list, index %s \n",
+ "InnoDB: Record overlaps another in free list, index %s \n",
index->name);
goto func_exit;
@@ -1522,9 +1731,11 @@ page_validate(
if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
- fprintf(stderr, "N heap is wrong %lu %lu in index %s\n",
- page_header_get_field(page, PAGE_N_HEAP), count + 1,
- index->name);
+ fprintf(stderr,
+ "InnoDB: N heap is wrong %lu %lu in index %s\n",
+ page_header_get_field(page, PAGE_N_HEAP), count + 1,
+ index->name);
+ goto func_exit;
}
ret = TRUE;
@@ -1532,6 +1743,15 @@ page_validate(
func_exit:
mem_heap_free(heap);
+ if (ret == FALSE) {
+ fprintf(stderr,
+"InnoDB: Apparent corruption in page %lu in index %s in table %s\n",
+ buf_frame_get_page_no(page), index->name,
+ index->table_name);
+
+ buf_page_print(page);
+ }
+
return(ret);
}
diff --git a/innobase/pars/lexyy.c b/innobase/pars/lexyy.c
index 782fca35f66..71507ccd868 100644
--- a/innobase/pars/lexyy.c
+++ b/innobase/pars/lexyy.c
@@ -4,8 +4,6 @@
* $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
*/
-#include "univ.i"
-
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
@@ -609,11 +607,8 @@ How to make the InnoDB parser and lexer C files:
6. Remove the #include of unistd.h from about line 2500 of lexyy.c
-7. Move #include <math.h> in pars0grm.c after #include "univ.i" to remove
- a large file compilation error on AIX.
-
-8. Move #include "univ.i" in lexyy.c to the file start to remove a large
- file compilation error on AIX.
+7. Add '#include "univ.i"' before #include <stdio.h> in lexyy.c
+ (Needed for AIX)
These instructions seem to work at least with bison-1.28 and flex-2.5.4 on
Linux.
@@ -621,6 +616,7 @@ Linux.
#line 36 "pars0lex.l"
#define YYSTYPE que_node_t*
+#include "univ.i"
#include "pars0pars.h"
#include "pars0grm.h"
#include "pars0sym.h"
diff --git a/innobase/pars/pars0grm.c b/innobase/pars/pars0grm.c
index ce575063610..05b75398084 100644
--- a/innobase/pars/pars0grm.c
+++ b/innobase/pars/pars0grm.c
@@ -102,8 +102,6 @@ que_node_t */
#include "que0que.h"
#include "row0sel.h"
-#include <math.h>
-
#define YYSTYPE que_node_t*
/* #define __STDC__ */
diff --git a/innobase/que/que0que.c b/innobase/que/que0que.c
index 7fa444f6741..a96c8840a03 100644
--- a/innobase/que/que0que.c
+++ b/innobase/que/que0que.c
@@ -1046,14 +1046,16 @@ que_thr_stop(
}
/**************************************************************************
-A patch for MySQL used to 'stop' a dummy query thread used in MySQL. */
+A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
+query thread is stopped and made inactive, except in the case where
+it was put to the lock wait state in lock0lock.c, but the lock has already
+been granted or the transaction chosen as a victim in deadlock resolution. */
void
que_thr_stop_for_mysql(
/*===================*/
que_thr_t* thr) /* in: query thread */
{
- ibool stopped = FALSE;
trx_t* trx;
trx = thr_get_trx(thr);
@@ -1067,13 +1069,10 @@ que_thr_stop_for_mysql(
/* Error handling built for the MySQL interface */
thr->state = QUE_THR_COMPLETED;
-
- stopped = TRUE;
- }
-
- if (!stopped) {
- /* It must have been a lock wait but the
- lock was already released */
+ } else {
+ /* It must have been a lock wait but the lock was
+ already released, or this transaction was chosen
+ as a victim in selective deadlock resolution */
mutex_exit(&kernel_mutex);
@@ -1081,6 +1080,10 @@ que_thr_stop_for_mysql(
}
}
+ ut_ad(thr->is_active == TRUE);
+ ut_ad(trx->n_active_thrs == 1);
+ ut_ad(thr->graph->n_active_thrs == 1);
+
thr->is_active = FALSE;
(thr->graph)->n_active_thrs--;
@@ -1132,6 +1135,9 @@ que_thr_stop_for_mysql_no_error(
trx_t* trx) /* in: transaction */
{
ut_ad(thr->state == QUE_THR_RUNNING);
+ ut_ad(thr->is_active == TRUE);
+ ut_ad(trx->n_active_thrs == 1);
+ ut_ad(thr->graph->n_active_thrs == 1);
if (thr->magic_n != QUE_THR_MAGIC_N) {
fprintf(stderr,
diff --git a/innobase/read/read0read.c b/innobase/read/read0read.c
index a5048c0c909..5c1d2d5418e 100644
--- a/innobase/read/read0read.c
+++ b/innobase/read/read0read.c
@@ -201,6 +201,28 @@ read_view_close(
}
/*************************************************************************
+Closes a consistent read view for MySQL. This function is called at an SQL
+statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */
+
+void
+read_view_close_for_mysql(
+/*======================*/
+ trx_t* trx) /* in: trx which has a read view */
+{
+ ut_a(trx->read_view);
+
+ mutex_enter(&kernel_mutex);
+
+ read_view_close(trx->read_view);
+
+ mem_heap_empty(trx->read_view_heap);
+
+ trx->read_view = NULL;
+
+ mutex_exit(&kernel_mutex);
+}
+
+/*************************************************************************
Prints a read view to stderr. */
void
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index c50516dfc8b..e9740d7ea78 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -353,7 +353,7 @@ cmp_data_data_slow(
data2++;
}
- return(0);
+ return(0); /* Not reached */
}
/*****************************************************************
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 941c9d5759d..d0a5cfec604 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -321,59 +321,6 @@ row_ins_clust_index_entry_by_modify(
return(err);
}
-/*******************************************************************
-Checks if a unique key violation to rec would occur at the index entry
-insert. */
-static
-ibool
-row_ins_dupl_error_with_rec(
-/*========================*/
- /* out: TRUE if error */
- rec_t* rec, /* in: user record; NOTE that we assume
- that the caller already has a record lock on
- the record! */
- dtuple_t* entry, /* in: entry to insert */
- dict_index_t* index) /* in: index */
-{
- ulint matched_fields;
- ulint matched_bytes;
- ulint n_unique;
- ulint i;
-
- n_unique = dict_index_get_n_unique(index);
-
- matched_fields = 0;
- matched_bytes = 0;
-
- cmp_dtuple_rec_with_match(entry, rec, &matched_fields, &matched_bytes);
-
- if (matched_fields < n_unique) {
-
- return(FALSE);
- }
-
- /* In a unique secondary index we allow equal key values if they
- contain SQL NULLs */
-
- if (!(index->type & DICT_CLUSTERED)) {
-
- for (i = 0; i < n_unique; i++) {
- if (UNIV_SQL_NULL == dfield_get_len(
- dtuple_get_nth_field(entry, i))) {
-
- return(FALSE);
- }
- }
- }
-
- if (!rec_get_deleted_flag(rec)) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
/*************************************************************************
Either deletes or sets the referencing columns SQL NULL in a child row.
Used in ON DELETE ... clause for foreign keys when a parent row is
@@ -533,8 +480,12 @@ row_ins_foreign_delete_or_set_null(
err = lock_table(0, table, LOCK_IX, thr);
if (err == DB_SUCCESS) {
+ /* Here it suffices to use a LOCK_REC_NOT_GAP type lock;
+ we already have a normal shared lock on the appropriate
+ gap if the search criterion was not unique */
+
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
- clust_index, LOCK_X, thr);
+ clust_index, LOCK_X, LOCK_REC_NOT_GAP, thr);
}
if (err != DB_SUCCESS) {
@@ -630,12 +581,14 @@ nonstandard_exit_func:
/*************************************************************************
Sets a shared lock on a record. Used in locking possible duplicate key
-records. */
+records and also in checking foreign key constraints. */
static
ulint
row_ins_set_shared_rec_lock(
/*========================*/
/* out: DB_SUCCESS or error code */
+ ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
+ LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
que_thr_t* thr) /* in: query thread */
@@ -644,10 +597,10 @@ row_ins_set_shared_rec_lock(
if (index->type & DICT_CLUSTERED) {
err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_S,
- thr);
+ type, thr);
} else {
err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_S,
- thr);
+ type, thr);
}
return(err);
@@ -656,7 +609,7 @@ row_ins_set_shared_rec_lock(
/*******************************************************************
Checks if foreign key constraint fails for an index entry. Sets shared locks
which lock either the success or the failure of the constraint. NOTE that
-the caller must have a shared latch on dict_foreign_key_check_lock. */
+the caller must have a shared latch on dict_operation_lock. */
ulint
row_ins_check_foreign_constraint(
@@ -679,7 +632,7 @@ row_ins_check_foreign_constraint(
dict_table_t* check_table;
dict_index_t* check_index;
ulint n_fields_cmp;
- ibool timeout_expired;
+ ibool unique_search;
rec_t* rec;
btr_pcur_t pcur;
ibool moved;
@@ -689,7 +642,9 @@ row_ins_check_foreign_constraint(
mtr_t mtr;
run_again:
- ut_ad(rw_lock_own(&dict_foreign_key_check_lock, RW_LOCK_SHARED));
+ ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED));
+
+ err = DB_SUCCESS;
if (thr_get_trx(thr)->check_foreigns == FALSE) {
/* The user has suppressed foreign key checks currently for
@@ -748,6 +703,14 @@ run_again:
dtuple_set_n_fields_cmp(entry, foreign->n_fields);
+ if (dict_index_get_n_unique(check_index) <= foreign->n_fields) {
+ /* We can just set a LOCK_REC_NOT_GAP type lock */
+
+ unique_search = TRUE;
+ } else {
+ unique_search = FALSE;
+ }
+
btr_pcur_open(check_index, entry, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
@@ -761,25 +724,45 @@ run_again:
goto next_rec;
}
- /* Try to place a lock on the index record */
-
- err = row_ins_set_shared_rec_lock(rec, check_index, thr);
-
- if (err != DB_SUCCESS) {
-
- break;
- }
-
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec,
+ check_index, thr);
+ if (err != DB_SUCCESS) {
+
+ break;
+ }
+
goto next_rec;
}
cmp = cmp_dtuple_rec(entry, rec);
if (cmp == 0) {
- if (!rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec)) {
+ err = row_ins_set_shared_rec_lock(LOCK_ORDINARY,
+ rec, check_index, thr);
+ if (err != DB_SUCCESS) {
+
+ break;
+ }
+ } else {
/* Found a matching record */
+
+ if (unique_search) {
+ err = row_ins_set_shared_rec_lock(
+ LOCK_REC_NOT_GAP,
+ rec, check_index, thr);
+ } else {
+ err = row_ins_set_shared_rec_lock(
+ LOCK_ORDINARY,
+ rec, check_index, thr);
+ }
+
+ if (err != DB_SUCCESS) {
+
+ break;
+ }
/* printf(
"FOREIGN: Found matching record from %s %s\n",
@@ -807,6 +790,13 @@ run_again:
}
if (cmp < 0) {
+ err = row_ins_set_shared_rec_lock(LOCK_GAP,
+ rec, check_index, thr);
+ if (err != DB_SUCCESS) {
+
+ break;
+ }
+
if (check_ref) {
err = DB_NO_REFERENCED_ROW;
} else {
@@ -844,14 +834,14 @@ do_possible_lock_wait:
que_thr_stop_for_mysql(thr);
- timeout_expired = srv_suspend_mysql_thread(thr);
+ srv_suspend_mysql_thread(thr);
- if (!timeout_expired) {
+ if (thr_get_trx(thr)->error_state == DB_SUCCESS) {
goto run_again;
}
- err = DB_LOCK_WAIT_TIMEOUT;
+ err = thr_get_trx(thr)->error_state;
}
return(err);
@@ -890,21 +880,16 @@ row_ins_check_foreign_constraints(
trx);
}
- if (!trx->has_dict_foreign_key_check_lock) {
+ if (0 == trx->dict_operation_lock_mode) {
got_s_lock = TRUE;
- rw_lock_s_lock(&dict_foreign_key_check_lock);
-
- trx->has_dict_foreign_key_check_lock = TRUE;
+ row_mysql_freeze_data_dictionary(trx);
}
err = row_ins_check_foreign_constraint(TRUE, foreign,
table, index, entry, thr);
if (got_s_lock) {
-
- rw_lock_s_unlock(&dict_foreign_key_check_lock);
-
- trx->has_dict_foreign_key_check_lock = FALSE;
+ row_mysql_unfreeze_data_dictionary(trx);
}
if (err != DB_SUCCESS) {
@@ -919,6 +904,59 @@ row_ins_check_foreign_constraints(
}
/*******************************************************************
+Checks if a unique key violation to rec would occur at the index entry
+insert. */
+static
+ibool
+row_ins_dupl_error_with_rec(
+/*========================*/
+ /* out: TRUE if error */
+ rec_t* rec, /* in: user record; NOTE that we assume
+ that the caller already has a record lock on
+ the record! */
+ dtuple_t* entry, /* in: entry to insert */
+ dict_index_t* index) /* in: index */
+{
+ ulint matched_fields;
+ ulint matched_bytes;
+ ulint n_unique;
+ ulint i;
+
+ n_unique = dict_index_get_n_unique(index);
+
+ matched_fields = 0;
+ matched_bytes = 0;
+
+ cmp_dtuple_rec_with_match(entry, rec, &matched_fields, &matched_bytes);
+
+ if (matched_fields < n_unique) {
+
+ return(FALSE);
+ }
+
+ /* In a unique secondary index we allow equal key values if they
+ contain SQL NULLs */
+
+ if (!(index->type & DICT_CLUSTERED)) {
+
+ for (i = 0; i < n_unique; i++) {
+ if (UNIV_SQL_NULL == dfield_get_len(
+ dtuple_get_nth_field(entry, i))) {
+
+ return(FALSE);
+ }
+ }
+ }
+
+ if (!rec_get_deleted_flag(rec)) {
+
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+/*******************************************************************
Scans a unique non-clustered index at a given index entry to determine
whether a uniqueness violation has occurred for the key value of the entry.
Set shared locks on possible duplicate records. */
@@ -976,9 +1014,10 @@ row_ins_scan_sec_index_for_duplicate(
goto next_rec;
}
- /* Try to place a lock on the index record */
+ /* Try to place a lock on the index record */
- err = row_ins_set_shared_rec_lock(rec, index, thr);
+ err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec, index,
+ thr);
if (err != DB_SUCCESS) {
@@ -1082,8 +1121,8 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
- err = row_ins_set_shared_rec_lock(rec, cursor->index,
- thr);
+ err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP,
+ rec, cursor->index, thr);
if (err != DB_SUCCESS) {
return(err);
@@ -1105,8 +1144,8 @@ row_ins_duplicate_error_in_clust(
if (rec != page_get_supremum_rec(page)) {
- err = row_ins_set_shared_rec_lock(rec, cursor->index,
- thr);
+ err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP,
+ rec, cursor->index, thr);
if (err != DB_SUCCESS) {
return(err);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index cea8f1316fe..9ce86b5d487 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -27,6 +27,7 @@ Created 9/17/2000 Heikki Tuuri
#include "lock0lock.h"
#include "rem0cmp.h"
#include "log0log.h"
+#include "btr0sea.h"
/* A dummy variable used to fool the compiler */
ibool row_mysql_identically_false = FALSE;
@@ -197,13 +198,13 @@ row_mysql_handle_errors(
/* out: TRUE if it was a lock wait and
we should continue running the query thread */
ulint* new_err,/* out: possible new error encountered in
- rollback, or the old error which was
- during the function entry */
+ lock wait, or if no new error, the value
+ of trx->error_state at the entry of this
+ function */
trx_t* trx, /* in: transaction */
que_thr_t* thr, /* in: query thread */
trx_savept_t* savept) /* in: savepoint or NULL */
{
- ibool timeout_expired;
ulint err;
handle_new_error:
@@ -240,11 +241,9 @@ handle_new_error:
/* MySQL will roll back the latest SQL statement */
} else if (err == DB_LOCK_WAIT) {
- timeout_expired = srv_suspend_mysql_thread(thr);
-
- if (timeout_expired) {
- trx->error_state = DB_LOCK_WAIT_TIMEOUT;
+ srv_suspend_mysql_thread(thr);
+ if (trx->error_state != DB_SUCCESS) {
que_thr_stop_for_mysql(thr);
goto handle_new_error;
@@ -321,6 +320,8 @@ row_create_prebuilt(
prebuilt->sql_stat_start = TRUE;
+ prebuilt->mysql_has_locked = FALSE;
+
prebuilt->index = NULL;
prebuilt->n_template = 0;
prebuilt->mysql_template = NULL;
@@ -1000,8 +1001,8 @@ row_update_cascade_for_mysql(
or set null operation */
dict_table_t* table) /* in: table where we do the operation */
{
- ulint err;
- trx_t* trx;
+ ulint err;
+ trx_t* trx;
trx = thr_get_trx(thr);
run_again:
@@ -1012,11 +1013,28 @@ run_again:
err = trx->error_state;
+ /* Note that the cascade node is a subnode of another InnoDB
+ query graph node. We do a normal lock wait in this node, but
+ all errors are handled by the parent node. */
+
if (err == DB_LOCK_WAIT) {
- que_thr_stop_for_mysql(thr);
+ /* Handle lock wait here */
- row_mysql_handle_errors(&err, trx, thr, NULL);
+ que_thr_stop_for_mysql(thr);
+
+ srv_suspend_mysql_thread(thr);
+
+ /* Note that a lock wait may also end in a lock wait timeout,
+ or this transaction is picked as a victim in selective
+ deadlock resolution */
+
+ if (trx->error_state != DB_SUCCESS) {
+ return(trx->error_state);
+ }
+
+ /* Retry operation after a normal lock wait */
+
goto run_again;
}
@@ -1136,32 +1154,73 @@ row_mysql_recover_tmp_table(
}
/*************************************************************************
-Locks the data dictionary exclusively for performing a table create
-operation. */
+Locks the data dictionary in shared mode from modifications, for performing
+foreign key check, rollback, or other operation invisible to MySQL. */
+
+void
+row_mysql_freeze_data_dictionary(
+/*=============================*/
+ trx_t* trx) /* in: transaction */
+{
+ ut_a(trx->dict_operation_lock_mode == 0);
+
+ rw_lock_s_lock(&dict_operation_lock);
+
+ trx->dict_operation_lock_mode = RW_S_LATCH;
+}
+
+/*************************************************************************
+Unlocks the data dictionary shared lock. */
+
+void
+row_mysql_unfreeze_data_dictionary(
+/*===============================*/
+ trx_t* trx) /* in: transaction */
+{
+ ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
+
+ rw_lock_s_unlock(&dict_operation_lock);
+
+ trx->dict_operation_lock_mode = 0;
+}
+
+/*************************************************************************
+Locks the data dictionary exclusively for performing a table create or other
+data dictionary modification operation. */
void
-row_mysql_lock_data_dictionary(void)
-/*================================*/
+row_mysql_lock_data_dictionary(
+/*===========================*/
+ trx_t* trx) /* in: transaction */
{
+ ut_a(trx->dict_operation_lock_mode == 0);
+
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks or lock waits can occur then in these operations */
- rw_lock_x_lock(&(dict_foreign_key_check_lock));
+ rw_lock_x_lock(&dict_operation_lock);
+ trx->dict_operation_lock_mode = RW_X_LATCH;
+
mutex_enter(&(dict_sys->mutex));
}
/*************************************************************************
-Unlocks the data dictionary exclusively lock. */
+Unlocks the data dictionary exclusive lock. */
void
-row_mysql_unlock_data_dictionary(void)
-/*==================================*/
+row_mysql_unlock_data_dictionary(
+/*=============================*/
+ trx_t* trx) /* in: transaction */
{
+ ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
+
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&(dict_foreign_key_check_lock));
+ rw_lock_x_unlock(&dict_operation_lock);
+
+ trx->dict_operation_lock_mode = 0;
}
/*************************************************************************
@@ -1184,6 +1243,8 @@ row_create_table_for_mysql(
ulint err;
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+ ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
+ ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(mutex_own(&(dict_sys->mutex)));
if (srv_created_new_raw) {
@@ -1332,7 +1393,7 @@ row_create_table_for_mysql(
fprintf(stderr,
"InnoDB: Warning: cannot create table %s because tablespace full\n",
table->name);
- row_drop_table_for_mysql(table->name, trx, TRUE);
+ row_drop_table_for_mysql(table->name, trx);
} else {
ut_a(err == DB_DUPLICATE_KEY);
@@ -1383,7 +1444,8 @@ row_create_index_for_mysql(
ulint namelen;
ulint keywordlen;
ulint err;
-
+
+ ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -1425,7 +1487,7 @@ row_create_index_for_mysql(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
- row_drop_table_for_mysql(index->table_name, trx, TRUE);
+ row_drop_table_for_mysql(index->table_name, trx);
trx->error_state = DB_SUCCESS;
}
@@ -1464,6 +1526,7 @@ row_table_add_foreign_constraints(
ulint err;
ut_ad(mutex_own(&(dict_sys->mutex)));
+ ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
ut_a(sql_string);
trx->op_info = (char *) "adding foreign keys";
@@ -1498,7 +1561,7 @@ row_table_add_foreign_constraints(
trx_general_rollback_for_mysql(trx, FALSE, NULL);
- row_drop_table_for_mysql(name, trx, TRUE);
+ row_drop_table_for_mysql(name, trx);
trx->error_state = DB_SUCCESS;
}
@@ -1529,7 +1592,7 @@ row_drop_table_for_mysql_in_background(
name); */
/* Drop the table in InnoDB */
- error = row_drop_table_for_mysql(name, trx, FALSE);
+ error = row_drop_table_for_mysql(name, trx);
if (error != DB_SUCCESS) {
fprintf(stderr,
@@ -1688,9 +1751,7 @@ row_drop_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
char* name, /* in: table name */
- trx_t* trx, /* in: transaction handle */
- ibool has_dict_mutex) /* in: TRUE if the caller already owns the
- dictionary system mutex */
+ trx_t* trx) /* in: transaction handle */
{
dict_table_t* table;
que_thr_t* thr;
@@ -1702,6 +1763,7 @@ row_drop_table_for_mysql(
ulint namelen;
ulint keywordlen;
ulint rounds = 0;
+ ibool locked_dictionary = FALSE;
char buf[10000];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -1845,13 +1907,18 @@ row_drop_table_for_mysql(
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
- if (!has_dict_mutex) {
- /* Prevent foreign key checks while we are dropping the table */
- rw_lock_x_lock(&(dict_foreign_key_check_lock));
+ if (trx->dict_operation_lock_mode != RW_X_LATCH) {
+ /* Prevent foreign key checks etc. while we are dropping the
+ table */
+
+ row_mysql_lock_data_dictionary(trx);
- mutex_enter(&(dict_sys->mutex));
+ locked_dictionary = TRUE;
}
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+ ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
+
graph = pars_sql(buf);
ut_a(graph);
@@ -1861,9 +1928,6 @@ row_drop_table_for_mysql(
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
- /* Prevent purge from running while we are dropping the table */
- rw_lock_s_lock(&(purge_sys->purge_is_running));
-
table = dict_table_get_low(name);
if (!table) {
@@ -1944,12 +2008,10 @@ row_drop_table_for_mysql(
}
}
-funct_exit:
- rw_lock_s_unlock(&(purge_sys->purge_is_running));
+funct_exit:
- if (!has_dict_mutex) {
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&(dict_foreign_key_check_lock));
+ if (locked_dictionary) {
+ row_mysql_unlock_data_dictionary(trx);
}
que_graph_free(graph);
@@ -1985,8 +2047,7 @@ row_drop_database_for_mysql(
trx_start_if_not_started(trx);
loop:
- rw_lock_x_lock(&(dict_foreign_key_check_lock));
- mutex_enter(&(dict_sys->mutex));
+ row_mysql_lock_data_dictionary(trx);
while ((table_name = dict_get_first_table_name_in_db(name))) {
ut_a(memcmp(table_name, name, strlen(name)) == 0);
@@ -1999,8 +2060,7 @@ loop:
the table */
if (table->n_mysql_handles_opened > 0) {
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&(dict_foreign_key_check_lock));
+ row_mysql_unlock_data_dictionary(trx);
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -2015,7 +2075,7 @@ loop:
goto loop;
}
- err = row_drop_table_for_mysql(table_name, trx, TRUE);
+ err = row_drop_table_for_mysql(table_name, trx);
mem_free(table_name);
@@ -2027,8 +2087,7 @@ loop:
}
}
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&(dict_foreign_key_check_lock));
+ row_mysql_unlock_data_dictionary(trx);
trx_commit_for_mysql(trx);
@@ -2165,8 +2224,7 @@ row_rename_table_for_mysql(
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
- rw_lock_x_lock(&(dict_foreign_key_check_lock));
- mutex_enter(&(dict_sys->mutex));
+ row_mysql_lock_data_dictionary(trx);
table = dict_table_get_low(old_name);
@@ -2248,8 +2306,7 @@ row_rename_table_for_mysql(
}
}
funct_exit:
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&(dict_foreign_key_check_lock));
+ row_mysql_unlock_data_dictionary(trx);
que_graph_free(graph);
@@ -2394,18 +2451,28 @@ row_check_table_for_mysql(
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
handle */
{
- dict_table_t* table = prebuilt->table;
+ dict_table_t* table = prebuilt->table;
dict_index_t* index;
ulint n_rows;
ulint n_rows_in_table = ULINT_UNDEFINED;
- ulint ret = DB_SUCCESS;
-
+ ulint ret = DB_SUCCESS;
+ ulint old_isolation_level;
+
prebuilt->trx->op_info = (char *) "checking table";
+ old_isolation_level = prebuilt->trx->isolation_level;
+
+ /* We must run the index record counts at an isolation level
+ >= READ COMMITTED, because a dirty read can see a wrong number
+ of records in some index; to play safe, we use always
+ REPEATABLE READ here */
+
+ prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
+
index = dict_table_get_first_index(table);
while (index != NULL) {
- /* fprintf(stderr, "Validating index %s\n", index->name); */
+ /* fprintf(stderr, "Validating index %s\n", index->name); */
if (!btr_validate_tree(index->tree)) {
ret = DB_ERROR;
@@ -2433,6 +2500,9 @@ row_check_table_for_mysql(
index = dict_table_get_next_index(index);
}
+ /* Restore the original isolation level */
+ prebuilt->trx->isolation_level = old_isolation_level;
+
/* We validate also the whole adaptive hash index for all tables
at every CHECK TABLE */
diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c
index 60e057b816e..b64003f22d4 100644
--- a/innobase/row/row0purge.c
+++ b/innobase/row/row0purge.c
@@ -24,6 +24,7 @@ Created 3/14/1997 Heikki Tuuri
#include "row0row.h"
#include "row0upd.h"
#include "row0vers.h"
+#include "row0mysql.h"
#include "log0log.h"
/************************************************************************
@@ -453,7 +454,9 @@ static
ibool
row_purge_parse_undo_rec(
/*=====================*/
- /* out: TRUE if purge operation required */
+ /* out: TRUE if purge operation required:
+ NOTE that then the CALLER must unfreeze
+ data dictionary! */
purge_node_t* node, /* in: row undo node */
ibool* updated_extern,
/* out: TRUE if an externally stored field
@@ -462,6 +465,7 @@ row_purge_parse_undo_rec(
{
dict_index_t* clust_index;
byte* ptr;
+ trx_t* trx;
dulint undo_no;
dulint table_id;
dulint trx_id;
@@ -471,6 +475,8 @@ row_purge_parse_undo_rec(
ulint cmpl_info;
ut_ad(node && thr);
+
+ trx = thr_get_trx(thr);
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
updated_extern, &undo_no, &table_id);
@@ -493,18 +499,21 @@ row_purge_parse_undo_rec(
return(FALSE);
}
- mutex_enter(&(dict_sys->mutex));
+ /* Prevent DROP TABLE etc. from running when we are doing the purge
+ for this row */
- node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr));
+ row_mysql_freeze_data_dictionary(trx);
- rw_lock_x_lock(&(purge_sys->purge_is_running));
+ mutex_enter(&(dict_sys->mutex));
- mutex_exit(&(dict_sys->mutex));
+ node->table = dict_table_get_on_id_low(table_id, thr_get_trx(thr));
+ mutex_exit(&(dict_sys->mutex));
+
if (node->table == NULL) {
/* The table has been dropped: no need to do purge */
- rw_lock_x_unlock(&(purge_sys->purge_is_running));
+ row_mysql_unfreeze_data_dictionary(trx);
return(FALSE);
}
@@ -514,7 +523,7 @@ row_purge_parse_undo_rec(
if (clust_index == NULL) {
/* The table was corrupt in the data dictionary */
- rw_lock_x_unlock(&(purge_sys->purge_is_running));
+ row_mysql_unfreeze_data_dictionary(trx);
return(FALSE);
}
@@ -552,9 +561,12 @@ row_purge(
dulint roll_ptr;
ibool purge_needed;
ibool updated_extern;
+ trx_t* trx;
ut_ad(node && thr);
+ trx = thr_get_trx(thr);
+
node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
&(node->reservation),
node->heap);
@@ -573,6 +585,8 @@ row_purge(
} else {
purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
thr);
+ /* If purge_needed == TRUE, we must also remember to unfreeze
+ data dictionary! */
}
if (purge_needed) {
@@ -594,7 +608,7 @@ row_purge(
btr_pcur_close(&(node->pcur));
}
- rw_lock_x_unlock(&(purge_sys->purge_is_running));
+ row_mysql_unfreeze_data_dictionary(trx);
}
/* Do some cleanup */
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 4af04251996..ce6ed091a48 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -606,7 +606,7 @@ row_sel_get_clust_rec(
/* Try to place a lock on the index record */
err = lock_clust_rec_read_check_and_lock(0, clust_rec, index,
- node->row_lock_mode, thr);
+ node->row_lock_mode, LOCK_ORDINARY, thr);
if (err != DB_SUCCESS) {
return(err);
@@ -621,7 +621,7 @@ row_sel_get_clust_rec(
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view, plan,
- clust_rec, &old_vers, mtr);
+ clust_rec, &old_vers, mtr);
if (err != DB_SUCCESS) {
return(err);
@@ -678,16 +678,17 @@ sel_set_rec_lock(
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
ulint mode, /* in: lock mode */
+ ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */
que_thr_t* thr) /* in: query thread */
{
ulint err;
if (index->type & DICT_CLUSTERED) {
err = lock_clust_rec_read_check_and_lock(0, rec, index, mode,
- thr);
+ type, thr);
} else {
err = lock_sec_rec_read_check_and_lock(0, rec, index, mode,
- thr);
+ type, thr);
}
return(err);
@@ -1154,7 +1155,7 @@ rec_loop:
if (!consistent_read) {
err = sel_set_rec_lock(page_rec_get_next(rec), index,
- node->row_lock_mode, thr);
+ node->row_lock_mode, LOCK_ORDINARY, thr);
if (err != DB_SUCCESS) {
/* Note that in this case we will store in pcur
the PREDECESSOR of the record we are waiting
@@ -1180,8 +1181,8 @@ rec_loop:
if (!consistent_read) {
/* Try to place a lock on the index record */
- err = sel_set_rec_lock(rec, index, node->row_lock_mode, thr);
-
+ err = sel_set_rec_lock(rec, index, node->row_lock_mode,
+ LOCK_ORDINARY, thr);
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
@@ -2200,6 +2201,7 @@ row_sel_get_clust_rec_for_mysql(
rec_t* old_vers;
ulint err;
trx_t* trx;
+ char err_buf[1000];
*out_rec = NULL;
@@ -2213,14 +2215,41 @@ row_sel_get_clust_rec_for_mysql(
clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur);
- ut_ad(page_rec_is_user_rec(clust_rec));
+ if (!page_rec_is_user_rec(clust_rec)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: error clustered record for sec rec not found\n"
+ "InnoDB: index %s table %s\n", sec_index->name,
+ sec_index->table->name);
+
+ rec_sprintf(err_buf, 900, rec);
+ fprintf(stderr, "InnoDB: sec index record %s\n", err_buf);
+
+ rec_sprintf(err_buf, 900, clust_rec);
+ fprintf(stderr, "InnoDB: clust index record %s\n", err_buf);
+
+ trx = thr_get_trx(thr);
+ trx_print(err_buf, trx);
+
+ fprintf(stderr,
+ "%s\nInnoDB: Make a detailed bug report and send it\n",
+ err_buf);
+ fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
+
+ clust_rec = NULL;
+
+ goto func_exit;
+ }
if (prebuilt->select_lock_type != LOCK_NONE) {
- /* Try to place a lock on the index record */
+ /* Try to place a lock on the index record; we are searching
+ the clust rec with a unique condition, hence
+ we set a LOCK_REC_NOT_GAP type lock */
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
clust_index,
- prebuilt->select_lock_type, thr);
+ prebuilt->select_lock_type,
+ LOCK_REC_NOT_GAP, thr);
if (err != DB_SUCCESS) {
return(err);
@@ -2232,8 +2261,12 @@ row_sel_get_clust_rec_for_mysql(
trx = thr_get_trx(thr);
old_vers = NULL;
-
- if (!lock_clust_rec_cons_read_sees(clust_rec, clust_index,
+
+ /* If the isolation level allows reading of uncommitted data,
+ then we never look for an earlier version */
+
+ if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
+ && !lock_clust_rec_cons_read_sees(clust_rec, clust_index,
trx->read_view)) {
err = row_sel_build_prev_vers_for_mysql(
@@ -2275,6 +2308,7 @@ row_sel_get_clust_rec_for_mysql(
}
}
+func_exit:
*out_rec = clust_rec;
if (prebuilt->select_lock_type == LOCK_X) {
@@ -2407,7 +2441,7 @@ row_sel_push_cache_row_for_mysql(
/*************************************************************************
Tries to do a shortcut to fetch a clustered index record with a unique key,
using the hash index if possible (not always). We assume that the search
-mode is PAGE_CUR_GE, it is a consistent read, trx has already a read view,
+mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx,
btr search latch has been locked in S-mode. */
static
ulint
@@ -2426,7 +2460,7 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(!prebuilt->templ_contains_blob);
-
+
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur,
#ifndef UNIV_SEARCH_DEBUG
@@ -2516,17 +2550,23 @@ row_search_for_mysql(
ibool was_lock_wait;
ulint ret;
ulint shortcut;
+ ibool unique_search = FALSE;
ibool unique_search_from_clust_index = FALSE;
ibool mtr_has_extra_clust_latch = FALSE;
ibool moves_up = FALSE;
+ ibool set_also_gap_locks = TRUE;
+ /* if the query is a plain
+ locking SELECT, and the isolation
+ level is <= TRX_ISO_READ_COMMITTED,
+ then this is set to FALSE */
+ ibool success;
ulint cnt = 0;
+ ulint next_offs;
mtr_t mtr;
ut_ad(index && pcur && search_tuple);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
-
- ut_ad(sync_thread_levels_empty_gen(FALSE));
-
+
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"
@@ -2543,6 +2583,9 @@ row_search_for_mysql(
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
*/
+ /*-------------------------------------------------------------*/
+ /* PHASE 1: Try to pop the row from the prefetch cache */
+
if (direction == 0) {
trx->op_info = (char *) "starting index read";
@@ -2608,18 +2651,35 @@ row_search_for_mysql(
mtr_start(&mtr);
- /* Since we must release the search system latch when we retrieve an
- externally stored field, we cannot use the adaptive hash index in a
- search in the case the row may be long and there may be externally
- stored fields */
+ /* In a search where at most one record in the index may match, we
+ can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete
+ marked matching record.
+
+ Note that in a unique secondary index there may be different delete
+ marked versions of a record where only the primary key values differ:
+ thus in a secondary index we must use next-key locks when locking
+ delete marked records. */
if (match_mode == ROW_SEL_EXACT
- && index->type & DICT_UNIQUE
- && index->type & DICT_CLUSTERED
- && !prebuilt->templ_contains_blob
- && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)
- && dtuple_get_n_fields(search_tuple)
+ && index->type & DICT_UNIQUE
+ && dtuple_get_n_fields(search_tuple)
== dict_index_get_n_unique(index)) {
+ unique_search = TRUE;
+ }
+
+ /*-------------------------------------------------------------*/
+ /* PHASE 2: Try fast adaptive hash index search if possible */
+
+ /* Next test if this is the special case where we can use the fast
+ adaptive hash index to try the search. Since we must release the
+ search system latch when we retrieve an externally stored field, we
+ cannot use the adaptive hash index in a search in the case the row
+ may be long and there may be externally stored fields */
+
+ if (unique_search
+ && index->type & DICT_CLUSTERED
+ && !prebuilt->templ_contains_blob
+ && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
if (direction == ROW_SEL_NEXT) {
/* MySQL sometimes seems to do fetch next even
@@ -2642,8 +2702,9 @@ row_search_for_mysql(
unique_search_from_clust_index = TRUE;
- if (trx->mysql_n_tables_locked == 0
- && !prebuilt->sql_stat_start) {
+ if (prebuilt->select_lock_type == LOCK_NONE
+ && trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
+ && trx->read_view) {
/* This is a SELECT query done as a consistent read,
and the read view has already been allocated:
@@ -2722,13 +2783,34 @@ row_search_for_mysql(
mtr_start(&mtr);
}
}
-no_shortcut:
+
+no_shortcut:
+ /*-------------------------------------------------------------*/
+ /* PHASE 3: Open or restore index cursor position */
+
if (trx->has_search_latch) {
rw_lock_s_unlock(&btr_search_latch);
trx->has_search_latch = FALSE;
}
trx_start_if_not_started(trx);
+
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ && prebuilt->select_lock_type != LOCK_NONE
+ && trx->mysql_query_str) {
+
+ /* Scan the MySQL query string; check if SELECT is the first
+ word there */
+
+ dict_accept(*trx->mysql_query_str, "SELECT", &success);
+
+ if (success) {
+ /* It is a plain locking SELECT and the isolation
+ level is low: do not lock gaps */
+
+ set_also_gap_locks = FALSE;
+ }
+ }
/* Note that if the search mode was GE or G, then the cursor
naturally moves upward (in fetch next) in alphabetical order,
@@ -2793,8 +2875,10 @@ no_shortcut:
prebuilt->sql_stat_start = FALSE;
}
- /*-------------------------------------------------------------*/
rec_loop:
+ /*-------------------------------------------------------------*/
+ /* PHASE 4: Look for matching records in a loop */
+
cons_read_requires_clust_rec = FALSE;
rec = btr_pcur_get_rec(pcur);
@@ -2812,37 +2896,88 @@ rec_loop:
goto next_rec;
}
-
- if (prebuilt->select_lock_type != LOCK_NONE) {
- /* Try to place a lock on the index record */
- err = sel_set_rec_lock(rec, index, prebuilt->select_lock_type,
- thr);
- if (err != DB_SUCCESS) {
+ if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
- goto lock_wait_or_error;
- }
- }
+ if (prebuilt->select_lock_type != LOCK_NONE
+ && set_also_gap_locks) {
- if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
+ /* Try to place a lock on the index record */
+
+ err = sel_set_rec_lock(rec, index,
+ prebuilt->select_lock_type,
+ LOCK_ORDINARY, thr);
+ if (err != DB_SUCCESS) {
+ goto lock_wait_or_error;
+ }
+ }
/* A page supremum record cannot be in the result set: skip
- it now when we have placed a possible lock on it */
+ it now that we have placed a possible lock on it */
goto next_rec;
}
- ut_ad(page_rec_is_user_rec(rec));
+ /*-------------------------------------------------------------*/
+ /* Do sanity checks in case our cursor has bumped into page
+ corruption */
+
+ next_offs = rec_get_next_offs(rec);
+
+ if (next_offs >= UNIV_PAGE_SIZE || next_offs < PAGE_SUPREMUM) {
+
+ if (srv_force_recovery == 0 || moves_up == FALSE) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
+"InnoDB: index %s, table %s. Run CHECK TABLE to table. You may need to\n"
+"InnoDB: restore from a backup, or dump + drop + reimport the table.\n",
+ (ulint)(rec - buf_frame_align(rec)), next_offs,
+ buf_frame_get_page_no(rec), index->name,
+ index->table_name);
+
+ err = DB_CORRUPTION;
- if (unique_search_from_clust_index && btr_pcur_get_up_match(pcur)
- == dtuple_get_n_fields(search_tuple)) {
- /* The record matches enough */
+ goto lock_wait_or_error;
+ } else {
+ /* The user may be dumping a corrupt table. Jump
+ over the corruption to recover as much as possible. */
- ut_ad(mode == PAGE_CUR_GE);
-#ifdef UNIV_SEARCH_DEBUG
- ut_a(0 == cmp_dtuple_rec(search_tuple, rec));
-#endif
- } else if (match_mode == ROW_SEL_EXACT) {
+ fprintf(stderr,
+"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
+"InnoDB: index %s, table %s. We try to skip the rest of the page.\n",
+ (ulint)(rec - buf_frame_align(rec)), next_offs,
+ buf_frame_get_page_no(rec), index->name,
+ index->table_name);
+
+ btr_pcur_move_to_last_on_page(pcur, &mtr);
+
+ goto next_rec;
+ }
+ }
+
+ if (srv_force_recovery > 0) {
+ if (!rec_validate(rec) || !btr_index_rec_validate(rec, index,
+ FALSE)) {
+ fprintf(stderr,
+"InnoDB: Index record corruption: rec offs %lu next offs %lu, page no %lu,\n"
+"InnoDB: index %s, table %s. We try to skip the record.\n",
+ (ulint)(rec - buf_frame_align(rec)), next_offs,
+ buf_frame_get_page_no(rec), index->name,
+ index->table_name);
+
+ goto next_rec;
+ }
+ }
+
+ /*-------------------------------------------------------------*/
+
+ /* Note that we cannot trust the up_match value in the cursor at this
+ place because we can arrive here after moving the cursor! Thus
+ we have to recompare rec and search_tuple to determine if they
+ match enough. */
+
+ if (match_mode == ROW_SEL_EXACT) {
/* Test if the index record matches completely to search_tuple
in prebuilt: if not, then we return with DB_RECORD_NOT_FOUND */
@@ -2850,6 +2985,19 @@ rec_loop:
if (0 != cmp_dtuple_rec(search_tuple, rec)) {
+ if (prebuilt->select_lock_type != LOCK_NONE
+ && set_also_gap_locks) {
+ /* Try to place a lock on the index record */
+
+ err = sel_set_rec_lock(rec, index,
+ prebuilt->select_lock_type,
+ LOCK_GAP, thr);
+ if (err != DB_SUCCESS) {
+
+ goto lock_wait_or_error;
+ }
+ }
+
btr_pcur_store_position(pcur, &mtr);
ret = DB_RECORD_NOT_FOUND;
@@ -2862,6 +3010,19 @@ rec_loop:
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec)) {
+ if (prebuilt->select_lock_type != LOCK_NONE
+ && set_also_gap_locks) {
+ /* Try to place a lock on the index record */
+
+ err = sel_set_rec_lock(rec, index,
+ prebuilt->select_lock_type,
+ LOCK_GAP, thr);
+ if (err != DB_SUCCESS) {
+
+ goto lock_wait_or_error;
+ }
+ }
+
btr_pcur_store_position(pcur, &mtr);
ret = DB_RECORD_NOT_FOUND;
@@ -2874,16 +3035,39 @@ rec_loop:
/* We are ready to look at a possible new index entry in the result
set: the cursor is now placed on a user record */
- /* Get the right version of the row in a consistent read */
-
- if (prebuilt->select_lock_type == LOCK_NONE) {
+ if (prebuilt->select_lock_type != LOCK_NONE) {
+ /* Try to place a lock on the index record; note that delete
+ marked records are a special case in a unique search. If there
+ is a non-delete marked record, then it is enough to lock its
+ existence with LOCK_REC_NOT_GAP. */
+
+ if (!set_also_gap_locks
+ || (unique_search && !rec_get_deleted_flag(rec))) {
+ err = sel_set_rec_lock(rec, index,
+ prebuilt->select_lock_type,
+ LOCK_REC_NOT_GAP, thr);
+ } else {
+ err = sel_set_rec_lock(rec, index,
+ prebuilt->select_lock_type,
+ LOCK_ORDINARY, thr);
+ }
+
+ if (err != DB_SUCCESS) {
+ goto lock_wait_or_error;
+ }
+ } else {
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
cons_read_requires_clust_rec = FALSE;
- if (index == clust_index) {
+ if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) {
+
+ /* Do nothing: we let a non-locking SELECT read the
+ latest version of the record */
+
+ } else if (index == clust_index) {
if (!lock_clust_rec_cons_read_sees(rec, index,
trx->read_view)) {
@@ -3020,8 +3204,11 @@ got_row:
ret = DB_SUCCESS;
goto normal_return;
- /*-------------------------------------------------------------*/
+
next_rec:
+ /*-------------------------------------------------------------*/
+ /* PHASE 5: Move the cursor to the next index record */
+
if (mtr_has_extra_clust_latch) {
/* We must commit mtr if we are moving to the next
non-clustered index record, because we could break the
@@ -3064,8 +3251,10 @@ next_rec:
cnt++;
goto rec_loop;
- /*-------------------------------------------------------------*/
+
lock_wait_or_error:
+ /*-------------------------------------------------------------*/
+
btr_pcur_store_position(pcur, &mtr);
mtr_commit(&mtr);
@@ -3096,6 +3285,7 @@ lock_wait_or_error:
return(err);
normal_return:
+ /*-------------------------------------------------------------*/
que_thr_stop_for_mysql_no_error(thr, trx);
mtr_commit(&mtr);
@@ -3156,10 +3346,12 @@ row_search_check_if_query_cache_permitted(
ret = TRUE;
- /* Assign a read view for the transaction if it does not yet
- have one */
+ /* If the isolation level is high, assign a read view for the
+ transaction if it does not yet have one */
+
+ if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ
+ && !trx->read_view) {
- if (!trx->read_view) {
trx->read_view = read_view_open_now(trx,
trx->read_view_heap);
}
diff --git a/innobase/row/row0uins.c b/innobase/row/row0uins.c
index 9990f893432..fff67dcd627 100644
--- a/innobase/row/row0uins.c
+++ b/innobase/row/row0uins.c
@@ -254,7 +254,8 @@ row_undo_ins_parse_undo_rec(
node->table = dict_table_get_on_id(table_id, node->trx);
if (node->table == NULL) {
- return;
+
+ return;
}
clust_index = dict_table_get_first_index(node->table);
@@ -281,7 +282,7 @@ row_undo_ins(
ut_ad(node && thr);
ut_ad(node->state == UNDO_NODE_INSERT);
-
+
row_undo_ins_parse_undo_rec(node, thr);
if (node->table == NULL) {
@@ -292,6 +293,7 @@ row_undo_ins(
if (!found) {
trx_undo_rec_release(node->trx, node->undo_no);
+
return(DB_SUCCESS);
}
diff --git a/innobase/row/row0undo.c b/innobase/row/row0undo.c
index 5119254f405..01b0b1ab41e 100644
--- a/innobase/row/row0undo.c
+++ b/innobase/row/row0undo.c
@@ -24,6 +24,7 @@ Created 1/8/1997 Heikki Tuuri
#include "row0row.h"
#include "row0uins.h"
#include "row0umod.h"
+#include "row0mysql.h"
#include "srv0srv.h"
/* How to undo row operations?
@@ -204,6 +205,7 @@ row_undo(
ulint err;
trx_t* trx;
dulint roll_ptr;
+ ibool froze_data_dict = FALSE;
ut_ad(node && thr);
@@ -211,7 +213,6 @@ row_undo(
if (node->state == UNDO_NODE_FETCH_NEXT) {
- /* The call below also starts &mtr */
node->undo_rec = trx_roll_pop_top_rec_of_trx(trx,
trx->roll_limit,
&roll_ptr,
@@ -254,6 +255,18 @@ row_undo(
}
}
+ /* Prevent DROP TABLE etc. while we are rolling back this row.
+ If we are doing a TABLE CREATE or some other dictionary operation,
+ then we already have dict_operation_lock locked in x-mode. Do not
+ try to lock again in s-mode, because that would cause a hang. */
+
+ if (trx->dict_operation_lock_mode == 0) {
+
+ row_mysql_freeze_data_dictionary(trx);
+
+ froze_data_dict = TRUE;
+ }
+
if (node->state == UNDO_NODE_INSERT) {
err = row_undo_ins(node, thr);
@@ -264,6 +277,11 @@ row_undo(
err = row_undo_mod(node, thr);
}
+ if (froze_data_dict) {
+
+ row_mysql_unfreeze_data_dictionary(trx);
+ }
+
/* Do some cleanup */
btr_pcur_close(&(node->pcur));
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 25c82f39da9..1231c94da63 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -79,7 +79,7 @@ ibool
row_upd_index_is_referenced(
/*========================*/
/* out: TRUE if referenced; NOTE that since
- we do not hold dict_foreign_key_check_lock
+ we do not hold dict_operation_lock
when leaving the function, it may be that
the referencing table has been dropped when
we leave this function: this function is only
@@ -89,14 +89,16 @@ row_upd_index_is_referenced(
{
dict_table_t* table = index->table;
dict_foreign_t* foreign;
+ ibool froze_data_dict = FALSE;
if (!UT_LIST_GET_FIRST(table->referenced_list)) {
return(FALSE);
}
- if (!trx->has_dict_foreign_key_check_lock) {
- rw_lock_s_lock(&dict_foreign_key_check_lock);
+ if (trx->dict_operation_lock_mode == 0) {
+ row_mysql_freeze_data_dictionary(trx);
+ froze_data_dict = TRUE;
}
foreign = UT_LIST_GET_FIRST(table->referenced_list);
@@ -104,8 +106,8 @@ row_upd_index_is_referenced(
while (foreign) {
if (foreign->referenced_index == index) {
- if (!trx->has_dict_foreign_key_check_lock) {
- rw_lock_s_unlock(&dict_foreign_key_check_lock);
+ if (froze_data_dict) {
+ row_mysql_unfreeze_data_dictionary(trx);
}
return(TRUE);
@@ -114,8 +116,8 @@ row_upd_index_is_referenced(
foreign = UT_LIST_GET_NEXT(referenced_list, foreign);
}
- if (!trx->has_dict_foreign_key_check_lock) {
- rw_lock_s_unlock(&dict_foreign_key_check_lock);
+ if (froze_data_dict) {
+ row_mysql_unfreeze_data_dictionary(trx);
}
return(FALSE);
@@ -162,12 +164,10 @@ row_upd_check_references_constraints(
mtr_start(mtr);
- if (!trx->has_dict_foreign_key_check_lock) {
+ if (trx->dict_operation_lock_mode == 0) {
got_s_lock = TRUE;
- rw_lock_s_lock(&dict_foreign_key_check_lock);
-
- trx->has_dict_foreign_key_check_lock = TRUE;
+ row_mysql_freeze_data_dictionary(trx);
}
foreign = UT_LIST_GET_FIRST(table->referenced_list);
@@ -189,7 +189,7 @@ row_upd_check_references_constraints(
}
/* NOTE that if the thread ends up waiting for a lock
- we will release dict_foreign_key_check_lock
+ we will release dict_operation_lock
temporarily! But the counter on the table
protects 'foreign' from being dropped while the check
is running. */
@@ -211,10 +211,7 @@ row_upd_check_references_constraints(
if (err != DB_SUCCESS) {
if (got_s_lock) {
- rw_lock_s_unlock(
- &dict_foreign_key_check_lock);
- trx->has_dict_foreign_key_check_lock
- = FALSE;
+ row_mysql_unfreeze_data_dictionary(trx);
}
mem_heap_free(heap);
@@ -227,8 +224,7 @@ row_upd_check_references_constraints(
}
if (got_s_lock) {
- rw_lock_s_unlock(&dict_foreign_key_check_lock);
- trx->has_dict_foreign_key_check_lock = FALSE;
+ row_mysql_unfreeze_data_dictionary(trx);
}
mem_heap_free(heap);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index d754f603efc..f9eba721cbc 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -51,6 +51,10 @@ Created 10/8/1995 Heikki Tuuri
#include "srv0start.h"
#include "row0mysql.h"
+/* This is set to TRUE if the MySQL user has set it in MySQL; currently
+affects only FOREIGN KEY definition parsing */
+ibool srv_lower_case_table_names = FALSE;
+
/* Buffer which can be used in printing fatal error messages */
char srv_fatal_errbuf[5000];
@@ -135,8 +139,6 @@ byte srv_latin1_ordering[256] /* The sort order table of the latin1
, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5D, 0xF7
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
};
-
-ibool srv_use_native_aio = FALSE;
ulint srv_pool_size = ULINT_MAX; /* size in database pages;
MySQL originally sets this
@@ -151,8 +153,9 @@ dulint srv_archive_recovery_limit_lsn;
ulint srv_lock_wait_timeout = 1024 * 1024 * 1024;
-char* srv_unix_file_flush_method_str = NULL;
-ulint srv_unix_file_flush_method = 0;
+char* srv_file_flush_method_str = NULL;
+ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
/* If the following is != 0 we do not allow inserts etc. This protects
the user from forgetting the innodb_force_recovery keyword to my.cnf */
@@ -281,6 +284,9 @@ time_t srv_last_monitor_time;
mutex_t srv_innodb_monitor_mutex;
+ulint srv_main_thread_process_no = 0;
+ulint srv_main_thread_id = 0;
+
/*
IMPLEMENTATION OF THE SERVER MAIN PROGRAM
=========================================
@@ -2046,13 +2052,15 @@ srv_table_reserve_slot_for_mysql(void)
}
/*******************************************************************
-Puts a MySQL OS thread to wait for a lock to be released. */
+Puts a MySQL OS thread to wait for a lock to be released. If an error
+occurs during the wait trx->error_state associated with thr is
+!= DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
+are possible errors. DB_DEADLOCK is returned if selective deadlock
+resolution chose this transaction as a victim. */
-ibool
+void
srv_suspend_mysql_thread(
/*=====================*/
- /* out: TRUE if the lock wait timeout was
- exceeded */
que_thr_t* thr) /* in: query thread associated with the MySQL
OS thread */
{
@@ -2060,6 +2068,7 @@ srv_suspend_mysql_thread(
os_event_t event;
double wait_time;
trx_t* trx;
+ ibool had_dict_lock = FALSE;
ut_ad(!mutex_own(&kernel_mutex));
@@ -2069,15 +2078,28 @@ srv_suspend_mysql_thread(
mutex_enter(&kernel_mutex);
+ trx->error_state = DB_SUCCESS;
+
if (thr->state == QUE_THR_RUNNING) {
- /* The lock has already been released: no need to suspend */
+ ut_ad(thr->is_active == TRUE);
+
+ /* The lock has already been released or this transaction
+ was chosen as a deadlock victim: no need to suspend */
+
+ if (trx->was_chosen_as_deadlock_victim) {
+
+ trx->error_state = DB_DEADLOCK;
+ trx->was_chosen_as_deadlock_victim = FALSE;
+ }
mutex_exit(&kernel_mutex);
- return(FALSE);
+ return;
}
+ ut_ad(thr->is_active == FALSE);
+
slot = srv_table_reserve_slot_for_mysql();
event = slot->event;
@@ -2101,18 +2123,22 @@ srv_suspend_mysql_thread(
srv_conc_force_exit_innodb(thr_get_trx(thr));
/* Release possible foreign key check latch */
- if (trx->has_dict_foreign_key_check_lock) {
+ if (trx->dict_operation_lock_mode == RW_S_LATCH) {
+
+ had_dict_lock = TRUE;
- rw_lock_s_unlock(&dict_foreign_key_check_lock);
+ row_mysql_unfreeze_data_dictionary(trx);
}
+ ut_a(trx->dict_operation_lock_mode == 0);
+
/* Wait for the release */
os_event_wait(event);
- if (trx->has_dict_foreign_key_check_lock) {
+ if (had_dict_lock) {
- rw_lock_s_lock(&dict_foreign_key_check_lock);
+ row_mysql_freeze_data_dictionary(trx);
}
/* Return back inside InnoDB */
@@ -2127,14 +2153,19 @@ srv_suspend_mysql_thread(
wait_time = ut_difftime(ut_time(), slot->suspend_time);
+ if (trx->was_chosen_as_deadlock_victim) {
+
+ trx->error_state = DB_DEADLOCK;
+ trx->was_chosen_as_deadlock_victim = FALSE;
+ }
+
mutex_exit(&kernel_mutex);
if (srv_lock_wait_timeout < 100000000 &&
wait_time > (double)srv_lock_wait_timeout) {
- return(TRUE);
- }
- return(FALSE);
+ trx->error_state = DB_LOCK_WAIT_TIMEOUT;
+ }
}
/************************************************************************
@@ -2300,9 +2331,19 @@ srv_sprintf_innodb_monitor(
"ROW OPERATIONS\n"
"--------------\n");
buf += sprintf(buf,
- "%ld queries inside InnoDB, %ld queries in queue; main thread: %s\n",
- srv_conc_n_threads, srv_conc_n_waiting_threads,
+ "%ld queries inside InnoDB, %ld queries in queue\n",
+ srv_conc_n_threads, srv_conc_n_waiting_threads);
+#ifdef UNIV_LINUX
+ buf += sprintf(buf,
+ "Main thread process no %lu, state: %s\n",
+ srv_main_thread_process_no,
+ srv_main_thread_op_info);
+#else
+ buf += sprintf(buf,
+ "Main thread id %lu, state: %s\n",
+ srv_main_thread_id,
srv_main_thread_op_info);
+#endif
buf += sprintf(buf,
"Number of rows inserted %lu, updated %lu, deleted %lu, read %lu\n",
srv_n_rows_inserted,
@@ -2636,6 +2677,9 @@ srv_master_thread(
UT_NOT_USED(arg);
+ srv_main_thread_process_no = os_proc_get_number();
+ srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
+
srv_table_reserve_slot(SRV_MASTER);
mutex_enter(&kernel_mutex);
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index dfa122b2ece..d6e8a8dcb4a 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -56,6 +56,10 @@ Created 2/16/1996 Heikki Tuuri
#include "srv0start.h"
#include "que0que.h"
+ibool srv_start_has_been_called = FALSE;
+
+ulint srv_sizeof_trx_t_in_ha_innodb_cc;
+
ibool srv_startup_is_before_trx_rollback_phase = FALSE;
ibool srv_is_being_started = FALSE;
ibool srv_was_started = FALSE;
@@ -515,7 +519,7 @@ srv_calc_high32(
}
/*************************************************************************
-Creates or opens the log files. */
+Creates or opens the log files and closes them. */
static
ulint
open_or_create_log_file(
@@ -640,7 +644,7 @@ open_or_create_log_file(
}
/*************************************************************************
-Creates or opens database data files. */
+Creates or opens database data files and closes them. */
static
ulint
open_or_create_data_files(
@@ -960,36 +964,91 @@ innobase_start_or_create_for_mysql(void)
"InnoDB: !!!!!!!!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!!!!!!!\n");
#endif
+ if (srv_sizeof_trx_t_in_ha_innodb_cc != (ulint)sizeof(trx_t)) {
+ fprintf(stderr,
+ "InnoDB: Error: trx_t size is %lu in ha_innodb.cc but %lu in srv0start.c\n"
+ "InnoDB: Check that pthread_mutex_t is defined in the same way in these\n"
+ "InnoDB: compilation modules. Cannot continue.\n",
+ srv_sizeof_trx_t_in_ha_innodb_cc, (ulint)sizeof(trx_t));
+ return(DB_ERROR);
+ }
+
+ /* Since InnoDB does not currently clean up all its internal data
+ structures in MySQL Embedded Server Library server_end(), we
+ print an error message if someone tries to start up InnoDB a
+ second time during the process lifetime. */
+
+ if (srv_start_has_been_called) {
+ fprintf(stderr,
+"InnoDB: Error:startup called second time during the process lifetime.\n"
+"InnoDB: In the MySQL Embedded Server Library you cannot call server_init()\n"
+"InnoDB: more than once during the process lifetime.\n");
+ }
+
+ srv_start_has_been_called = TRUE;
+
log_do_write = TRUE;
/* yydebug = TRUE; */
srv_is_being_started = TRUE;
srv_startup_is_before_trx_rollback_phase = TRUE;
+ os_aio_use_native_aio = FALSE;
+
+#ifdef __WIN__
+ if (os_get_os_version() == OS_WIN95
+ || os_get_os_version() == OS_WIN31
+ || os_get_os_version() == OS_WINNT) {
+
+ /* On Win 95, 98, ME, Win32 subsystem for Windows 3.1,
+ and NT use simulated aio. In NT Windows provides async i/o,
+ but when run in conjunction with InnoDB Hot Backup, it seemed
+ to corrupt the data files. */
+
+ os_aio_use_native_aio = FALSE;
+ } else {
+ /* On Win 2000 and XP use async i/o */
+ os_aio_use_native_aio = TRUE;
+ }
+#endif
+ if (srv_file_flush_method_str == NULL) {
+ /* These are the default options */
- if (0 == ut_strcmp(srv_unix_file_flush_method_str, "fdatasync")) {
+ srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
+
+ srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
+#ifndef __WIN__
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
- } else if (0 == ut_strcmp(srv_unix_file_flush_method_str, "O_DSYNC")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
- } else if (0 == ut_strcmp(srv_unix_file_flush_method_str,
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
"littlesync")) {
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
- } else if (0 == ut_strcmp(srv_unix_file_flush_method_str, "nosync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
+#else
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
+ srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
+ os_aio_use_native_aio = FALSE;
+
+ } else if (0 == ut_strcmp(srv_file_flush_method_str, "unbuffered")) {
+ srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
+ os_aio_use_native_aio = FALSE;
+
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ "async_unbuffered")) {
+ srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
+#endif
} else {
fprintf(stderr,
"InnoDB: Unrecognized value %s for innodb_flush_method\n",
- srv_unix_file_flush_method_str);
+ srv_file_flush_method_str);
return(DB_ERROR);
}
- /*
- printf("srv_unix set to %lu\n", srv_unix_file_flush_method);
- */
- os_aio_use_native_aio = srv_use_native_aio;
-
err = srv_boot();
if (err != DB_SUCCESS) {
@@ -999,34 +1058,15 @@ innobase_start_or_create_for_mysql(void)
/* Restrict the maximum number of file i/o threads */
if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) {
+
srv_n_file_io_threads = SRV_MAX_N_IO_THREADS;
}
-#if !(defined(WIN_ASYNC_IO) || defined(POSIX_ASYNC_IO))
- /* In simulated aio we currently have use only for 4 threads */
-
- os_aio_use_native_aio = FALSE;
-
- srv_n_file_io_threads = 4;
-#endif
-
-#ifdef __WIN__
- if (os_get_os_version() == OS_WIN95
- || os_get_os_version() == OS_WIN31) {
+ if (!os_aio_use_native_aio) {
+ /* In simulated aio we currently have use only for 4 threads */
- /* On Win 95, 98, ME, and Win32 subsystem for Windows 3.1 use
- simulated aio */
+ srv_n_file_io_threads = 4;
- os_aio_use_native_aio = FALSE;
- srv_n_file_io_threads = 4;
- } else {
- /* On NT and Win 2000 always use aio */
- os_aio_use_native_aio = TRUE;
- }
-#endif
- os_aio_use_native_aio = FALSE;
-
- if (!os_aio_use_native_aio) {
os_aio_init(8 * SRV_N_PENDING_IOS_PER_THREAD
* srv_n_file_io_threads,
srv_n_file_io_threads,
@@ -1047,15 +1087,6 @@ innobase_start_or_create_for_mysql(void)
lock_sys_create(srv_lock_table_size);
-#ifdef POSIX_ASYNC_IO
- if (os_aio_use_native_aio) {
- /* There is only one thread per async io array:
- one for ibuf i/o, one for log i/o, one for ordinary reads,
- one for ordinary writes; we need only 4 i/o threads */
-
- srv_n_file_io_threads = 4;
- }
-#endif
/* Create i/o-handler threads: */
for (i = 0; i < srv_n_file_io_threads; i++) {
@@ -1365,7 +1396,7 @@ innobase_start_or_create_for_mysql(void)
if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
fprintf(stderr,
"InnoDB: Error: pthread_mutex_trylock returns an unexpected value on\n"
- "InnoDB: success! Cannot continue.\n");
+"InnoDB: success! Cannot continue.\n");
exit(1);
}
@@ -1375,11 +1406,17 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_unlock(&srv_os_test_mutex);
- if (srv_print_verbose_log)
- {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Started\n");
+ if (srv_print_verbose_log) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Started\n");
}
+
+ if (srv_force_recovery > 0) {
+ fprintf(stderr,
+ "InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
+ srv_force_recovery);
+ }
+
return((int) DB_SUCCESS);
}
diff --git a/innobase/stamp-h.in b/innobase/stamp-h.in
deleted file mode 100644
index 9788f70238c..00000000000
--- a/innobase/stamp-h.in
+++ /dev/null
@@ -1 +0,0 @@
-timestamp
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index fe837b119f3..b214bca0470 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -663,7 +663,8 @@ rw_lock_own(
/*========*/
/* out: TRUE if locked */
rw_lock_t* lock, /* in: rw-lock */
- ulint lock_type) /* in: lock type */
+ ulint lock_type) /* in: lock type: RW_LOCK_SHARED,
+ RW_LOCK_EX */
{
rw_lock_debug_t* info;
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 3ea996afd6b..376be2e723a 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -901,8 +901,7 @@ sync_thread_levels_empty_gen(
if (slot->latch != NULL && (!dict_mutex_allowed ||
(slot->level != SYNC_DICT
- && slot->level != SYNC_FOREIGN_KEY_CHECK
- && slot->level != SYNC_PURGE_IS_RUNNING))) {
+ && slot->level != SYNC_DICT_OPERATION))) {
lock = slot->latch;
mutex = slot->latch;
@@ -1087,12 +1086,10 @@ sync_thread_add_level(
SYNC_IBUF_PESS_INSERT_MUTEX));
} else if (level == SYNC_DICT_AUTOINC_MUTEX) {
ut_a(sync_thread_levels_g(array, SYNC_DICT_AUTOINC_MUTEX));
- } else if (level == SYNC_FOREIGN_KEY_CHECK) {
- ut_a(sync_thread_levels_g(array, SYNC_FOREIGN_KEY_CHECK));
+ } else if (level == SYNC_DICT_OPERATION) {
+ ut_a(sync_thread_levels_g(array, SYNC_DICT_OPERATION));
} else if (level == SYNC_DICT_HEADER) {
ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER));
- } else if (level == SYNC_PURGE_IS_RUNNING) {
- ut_a(sync_thread_levels_g(array, SYNC_PURGE_IS_RUNNING));
} else if (level == SYNC_DICT) {
ut_a(buf_debug_prints
|| sync_thread_levels_g(array, SYNC_DICT));
diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c
index 97362d00b4b..d58240d3c11 100644
--- a/innobase/trx/trx0purge.c
+++ b/innobase/trx/trx0purge.c
@@ -209,9 +209,6 @@ trx_purge_sys_create(void)
purge_sys->purge_undo_no = ut_dulint_zero;
purge_sys->next_stored = FALSE;
- rw_lock_create(&(purge_sys->purge_is_running));
- rw_lock_set_level(&(purge_sys->purge_is_running),
- SYNC_PURGE_IS_RUNNING);
rw_lock_create(&(purge_sys->latch));
rw_lock_set_level(&(purge_sys->latch), SYNC_PURGE_LATCH);
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index 4c2ee5dc9be..1f0e0c58ac7 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -254,7 +254,7 @@ loop:
mutex_exit(&kernel_mutex);
if (trx->dict_operation) {
- mutex_enter(&(dict_sys->mutex));
+ row_mysql_lock_data_dictionary(trx);
}
que_run_threads(thr);
@@ -290,14 +290,14 @@ loop:
fprintf(stderr,
"InnoDB: Table found: dropping table %s in recovery\n", table->name);
- err = row_drop_table_for_mysql(table->name, trx,
- TRUE);
+ err = row_drop_table_for_mysql(table->name, trx);
+
ut_a(err == (int) DB_SUCCESS);
}
}
if (trx->dict_operation) {
- mutex_exit(&(dict_sys->mutex));
+ row_mysql_unlock_data_dictionary(trx);
}
fprintf(stderr, "InnoDB: Rolling back of trx id %lu %lu completed\n",
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 994a6777924..f0077f941de 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -23,7 +23,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "thr0loc.h"
#include "btr0sea.h"
-
+#include "os0proc.h"
/* Copy of the prototype for innobase_mysql_print_thd: this
copy MUST be equal to the one in mysql/sql/ha_innobase.cc ! */
@@ -85,12 +85,14 @@ trx_create(
trx->conc_state = TRX_NOT_STARTED;
trx->start_time = time(NULL);
+ trx->isolation_level = TRX_ISO_REPEATABLE_READ;
trx->check_foreigns = TRUE;
trx->check_unique_secondary = TRUE;
trx->dict_operation = FALSE;
trx->mysql_thd = NULL;
+ trx->mysql_query_str = NULL;
trx->n_mysql_tables_in_use = 0;
trx->mysql_n_tables_locked = 0;
@@ -127,12 +129,13 @@ trx_create(
trx->graph = NULL;
trx->wait_lock = NULL;
+ trx->was_chosen_as_deadlock_victim = FALSE;
UT_LIST_INIT(trx->wait_thrs);
trx->lock_heap = mem_heap_create_in_buffer(256);
UT_LIST_INIT(trx->trx_locks);
- trx->has_dict_foreign_key_check_lock = FALSE;
+ trx->dict_operation_lock_mode = 0;
trx->has_search_latch = FALSE;
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
@@ -175,6 +178,8 @@ trx_allocate_for_mysql(void)
mutex_exit(&kernel_mutex);
trx->mysql_thread_id = os_thread_get_curr_id();
+
+ trx->mysql_process_no = os_proc_get_number();
return(trx);
}
@@ -257,6 +262,8 @@ trx_free(
ut_a(!trx->has_search_latch);
ut_a(!trx->auto_inc_lock);
+ ut_a(trx->dict_operation_lock_mode == 0);
+
if (trx->lock_heap) {
mem_heap_free(trx->lock_heap);
}
@@ -1497,9 +1504,12 @@ trx_print(
default: buf += sprintf(buf, " state %lu", trx->conc_state);
}
+#ifdef UNIV_LINUX
+ buf += sprintf(buf, ", process no %lu", trx->mysql_process_no);
+#else
buf += sprintf(buf, ", OS thread id %lu",
os_thread_pf(trx->mysql_thread_id));
-
+#endif
if (ut_strlen(trx->op_info) > 0) {
buf += sprintf(buf, " %s", trx->op_info);
}
diff --git a/isam/pack_isam.c b/isam/pack_isam.c
index ebe616714f5..09825dd137f 100644
--- a/isam/pack_isam.c
+++ b/isam/pack_isam.c
@@ -67,7 +67,7 @@ struct st_file_buffer {
char *buffer,*pos,*end;
my_off_t pos_in_file;
int bits;
- uint byte;
+ uint bytes;
};
struct st_huff_tree;
@@ -1835,7 +1835,7 @@ static void init_file_buffer(File file, pbool read_buffer)
file_buffer.pos=file_buffer.buffer;
file_buffer.bits=BITS_SAVED;
}
- file_buffer.byte=0;
+ file_buffer.bytes=0;
}
@@ -1866,13 +1866,13 @@ static void write_bits (register ulong value, register uint bits)
{
if ((file_buffer.bits-=(int) bits) >= 0)
{
- file_buffer.byte|=value << file_buffer.bits;
+ file_buffer.bytes|=value << file_buffer.bits;
}
else
{
reg3 uint byte_buff;
bits= (uint) -file_buffer.bits;
- byte_buff=file_buffer.byte | (uint) (value >> bits);
+ byte_buff=file_buffer.bytes | (uint) (value >> bits);
#if BITS_SAVED == 32
*file_buffer.pos++= (byte) (byte_buff >> 24) ;
*file_buffer.pos++= (byte) (byte_buff >> 16) ;
@@ -1898,7 +1898,7 @@ static void write_bits (register ulong value, register uint bits)
if (file_buffer.pos >= file_buffer.end)
VOID(flush_buffer((uint) ~0));
file_buffer.bits=(int) (BITS_SAVED - bits);
- file_buffer.byte=(uint) (value << (BITS_SAVED - bits));
+ file_buffer.bytes=(uint) (value << (BITS_SAVED - bits));
}
return;
}
@@ -1910,7 +1910,7 @@ static void flush_bits (void)
uint bits,byte_buff;
bits=(file_buffer.bits) & ~7;
- byte_buff = file_buffer.byte >> bits;
+ byte_buff = file_buffer.bytes >> bits;
bits=BITS_SAVED - bits;
while (bits > 0)
{
@@ -1918,7 +1918,7 @@ static void flush_bits (void)
*file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ;
}
file_buffer.bits=BITS_SAVED;
- file_buffer.byte=0;
+ file_buffer.bytes=0;
return;
}
diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c
index 0945aed6772..84c360ee5dc 100644
--- a/libmysql/errmsg.c
+++ b/libmysql/errmsg.c
@@ -50,6 +50,7 @@ const char *client_errors[]=
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:",
+ "SSL connection error",
"Invalid connection handle",
"Invalid use of null pointer",
"Statement not prepared",
@@ -68,8 +69,8 @@ const char *client_errors[]=
"Can't open shared memory. Map of memory don't create for client (%lu)",
"Can't open shared memory. %s event don't create for client (%lu)",
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
- "Can't open shared memory. Can't send the request event to server (%lu)"
- "Wrong or unknow protocol"
+ "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Wrong or unknown protocol"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
@@ -103,6 +104,7 @@ const char *client_errors[]=
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:",
+ "SSL connection error",
"Invalid connection handle",
"Invalid use of null pointer",
"Statement not prepared",
@@ -121,8 +123,8 @@ const char *client_errors[]=
"Can't open shared memory. Map of memory don't create for client (%lu)",
"Can't open shared memory. %s event don't create for client (%lu)",
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
- "Can't open shared memory. Can't send the request event to server (%lu)"
- "Wrong or unknow protocol"
+ "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Wrong or unknown protocol"
};
#else /* ENGLISH */
@@ -154,6 +156,7 @@ const char *client_errors[]=
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:",
+ "SSL connection error",
"Invalid connection handle",
"Invalid use of null pointer",
"Statement not prepared",
@@ -172,8 +175,8 @@ const char *client_errors[]=
"Can't open shared memory. Map of memory don't create for client (%lu)",
"Can't open shared memory. %s event don't create for client (%lu)",
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
- "Can't open shared memory. Can't send the request event to server (%lu)"
- "Wrong or unknow protocol"
+ "Can't open shared memory. Can't send the request event to server (%lu)",
+ "Wrong or unknown protocol"
};
#endif
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 535a79e0557..7b7d14f0a50 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -242,7 +242,7 @@ my_bool my_connect(my_socket s, const struct sockaddr *name,
{
tv.tv_sec = (long) timeout;
tv.tv_usec = 0;
-#if defined(HPUX) && defined(THREAD)
+#if defined(HPUX10) && defined(THREAD)
if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) >= 0)
break;
#else
@@ -1807,6 +1807,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
#endif
init_sigpipe_variables
DBUG_ENTER("mysql_real_connect");
+ LINT_INIT(host_info);
DBUG_PRINT("enter",("host: %s db: %s user: %s",
host ? host : "(Null)",
@@ -2188,15 +2189,18 @@ Try also with PIPE or TCP/IP
options->ssl_capath,
options->ssl_cipher)))
{
- /* TODO: Change to SSL error */
- net->last_errno= CR_SERVER_LOST;
+ net->last_errno= CR_SSL_CONNECTION_ERROR;
strmov(net->last_error,ER(net->last_errno));
goto error;
}
DBUG_PRINT("info", ("IO layer change in progress..."));
- /* TODO: Add proper error checking here, with return error message */
- sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),
- mysql->net.vio, (long) (mysql->options.connect_timeout));
+ if(sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd),
+ mysql->net.vio, (long) (mysql->options.connect_timeout)))
+ {
+ net->last_errno= CR_SSL_CONNECTION_ERROR;
+ strmov(net->last_error,ER(net->last_errno));
+ goto error;
+ }
DBUG_PRINT("info", ("IO layer change done!"));
}
#endif /* HAVE_OPENSSL */
diff --git a/libmysql/password.c b/libmysql/password.c
index 9b154603b98..1c2c5589215 100644
--- a/libmysql/password.c
+++ b/libmysql/password.c
@@ -91,7 +91,7 @@ void make_scrambled_password(char *to,const char *password)
sprintf(to,"%08lx%08lx",hash_res[0],hash_res[1]);
}
-static inline uint char_val(char X)
+static inline unsigned int char_val(char X)
{
return (uint) (X >= '0' && X <= '9' ? X-'0' :
X >= 'A' && X <= 'Z' ? X-'A'+10 :
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 09681fa3a63..4726cbb44a7 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -506,13 +506,13 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
exit(1);
}
opt_noacl = 1; // No permissions
- if (acl_init(opt_noacl))
+ if (acl_init((THD*) 0,opt_noacl))
{
mysql_server_end();
return 1;
}
if (!opt_noacl)
- (void) grant_init();
+ (void) grant_init((THD*) 0);
init_max_user_conn();
init_update_queries();
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 2b9b6cedcf6..6749de06ee2 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -119,8 +119,8 @@ static int FTB_WORD_cmp(my_off_t *v, FTB_WORD *a, FTB_WORD *b)
static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b)
{
/* ORDER BY word DESC, ndepth DESC */
- int i= mi_compare_text(cs, (*b)->word+1,(*b)->len-1,
- (*a)->word+1,(*a)->len-1,0);
+ int i= mi_compare_text(cs, (uchar*) (*b)->word+1,(*b)->len-1,
+ (uchar*) (*a)->word+1,(*a)->len-1,0);
if (!i)
i=CMP_NUM((*b)->ndepth,(*a)->ndepth);
return i;
@@ -255,7 +255,7 @@ static void _ftb_init_index_search(FT_INFO *ftb)
r= mi_compare_text(ftb->charset,
info->lastkey + (ftbw->flags&FTB_FLAG_TRUNC),
ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
- ftbw->word + (ftbw->flags&FTB_FLAG_TRUNC),
+ (uchar*) ftbw->word + (ftbw->flags&FTB_FLAG_TRUNC),
ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
0);
}
@@ -348,9 +348,9 @@ static int _ftb_strstr(const byte *s0, const byte *e0,
if (s0 >= e0)
return 0;
p=s1+1;
- while (s0 < e0 && p < e1 && cs->to_upper[(uint) (uchar) *s0++] ==
- cs->to_upper[(uint) (uchar) *p++])
- /* no-op */;
+ while (s0 < e0 && p < e1 && cs->to_upper[(uint) (uchar) *s0] ==
+ cs->to_upper[(uint) (uchar) *p])
+ s0++, p++;
if (p >= e1)
return 1;
}
@@ -473,7 +473,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
r= mi_compare_text(ftb->charset,
info->lastkey + (ftbw->flags&FTB_FLAG_TRUNC),
ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
- ftbw->word + (ftbw->flags&FTB_FLAG_TRUNC),
+ (uchar*) ftbw->word + (ftbw->flags&FTB_FLAG_TRUNC),
ftbw->len - (ftbw->flags&FTB_FLAG_TRUNC),
0);
}
@@ -578,7 +578,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
for (a=0, b=ftb->queue.elements, c=(a+b)/2; b-a>1; c=(a+b)/2)
{
ftbw=ftb->list[c];
- if (mi_compare_text(ftb->charset, word.pos, word.len,
+ if (mi_compare_text(ftb->charset, (uchar*) word.pos, word.len,
(uchar*) ftbw->word+1, ftbw->len-1,
(my_bool) (ftbw->flags&FTB_FLAG_TRUNC)) >0)
b=c;
@@ -588,7 +588,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
for (; c>=0; c--)
{
ftbw=ftb->list[c];
- if (mi_compare_text(ftb->charset, word.pos,word.len,
+ if (mi_compare_text(ftb->charset, (uchar*) word.pos, word.len,
(uchar*) ftbw->word+1,ftbw->len-1,
(my_bool) (ftbw->flags&FTB_FLAG_TRUNC)))
break;
diff --git a/myisam/ft_nlq_search.c b/myisam/ft_nlq_search.c
index 7225896c69e..f9c276de32f 100644
--- a/myisam/ft_nlq_search.c
+++ b/myisam/ft_nlq_search.c
@@ -155,7 +155,8 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
if (doc_cnt)
{
word->weight*=GWS_IN_USE;
- if (word->weight < 0) word->weight=0;
+ if (word->weight < 0)
+ word->weight=0;
}
DBUG_RETURN(0);
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index 60e6fc0519a..d33aa2718b7 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -157,6 +157,7 @@ static int _mi_find_writepos(MI_INFO *info,
ulong *length) /* length of block at filepos */
{
MI_BLOCK_INFO block_info;
+ ulong tmp;
DBUG_ENTER("_mi_find_writepos");
if (info->s->state.dellink != HA_OFFSET_ERROR)
@@ -182,21 +183,22 @@ static int _mi_find_writepos(MI_INFO *info,
{
/* No deleted blocks; Allocate a new block */
*filepos=info->state->data_file_length;
- if ((*length=reclength+3 + test(reclength >= (65520-3))) <
+ if ((tmp=reclength+3 + test(reclength >= (65520-3))) <
info->s->base.min_block_length)
- *length=info->s->base.min_block_length;
+ tmp= info->s->base.min_block_length;
else
- *length= ((*length+MI_DYN_ALIGN_SIZE-1) &
- (~ (ulong) (MI_DYN_ALIGN_SIZE-1)));
+ tmp= ((tmp+MI_DYN_ALIGN_SIZE-1) &
+ (~ (ulong) (MI_DYN_ALIGN_SIZE-1)));
if (info->state->data_file_length >
- (info->s->base.max_data_file_length- *length))
+ (info->s->base.max_data_file_length - tmp))
{
my_errno=HA_ERR_RECORD_FILE_FULL;
DBUG_RETURN(-1);
}
- if (*length > MI_MAX_BLOCK_LENGTH)
- *length=MI_MAX_BLOCK_LENGTH;
- info->state->data_file_length+= *length;
+ if (tmp > MI_MAX_BLOCK_LENGTH)
+ tmp=MI_MAX_BLOCK_LENGTH;
+ *length= tmp;
+ info->state->data_file_length+= tmp;
info->s->state.split++;
info->update|=HA_STATE_WRITE_AT_END;
}
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index e4e70f649a4..8f0da612c3a 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -583,7 +583,8 @@ byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf)
/* to simplify initial init of info->rec_buf in mi_open and mi_extra */
if (length == (ulong) -1)
- length= max(info->s->base.pack_reclength,info->s->base.max_key_length);
+ length= max(info->s->base.pack_reclength+info->s->base.pack_bits,
+ info->s->base.max_key_length);
extra= ((info->s->options & HA_OPTION_PACK_RECORD) ?
ALIGN_SIZE(MI_MAX_DYN_BLOCK_HEADER)+MI_SPLIT_LENGTH+
diff --git a/myisam/mi_page.c b/myisam/mi_page.c
index 064e9239e73..1d40980e309 100644
--- a/myisam/mi_page.c
+++ b/myisam/mi_page.c
@@ -66,7 +66,9 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
page+keyinfo->block_length > info->state->key_file_length ||
(page & (MI_MIN_KEY_BLOCK_LENGTH-1)))
{
- DBUG_PRINT("error",("Trying to write inside key status region: %lu",
+ DBUG_PRINT("error",("Trying to write inside key status region: key_start: %lu length: %lu page: %lu",
+ (long) info->s->base.keystart,
+ (long) info->state->key_file_length,
(long) page));
my_errno=EINVAL;
return(-1);
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index 5d22ebfe5b5..58f9ebdb735 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -845,8 +845,9 @@ int _mi_init_bulk_insert(MI_INFO *info, ulong cache_size)
{
params->info=info;
params->keynr=i;
+ /* Only allocate a 16'th of the buffer at a time */
init_tree(&info->bulk_insert[i],
- cache_size / num_keys / 4 + 10,
+ cache_size / num_keys / 16 + 10,
cache_size / num_keys, 0,
(qsort_cmp2)keys_compare, 0,
(tree_element_free) keys_free, (void *)params++);
diff --git a/myisam/sort.c b/myisam/sort.c
index 0e69e41ed5c..50618e43991 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -488,7 +488,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
printf("Key %d - Merging %u keys\n",sinfo->key+1, sinfo->keys);
if (merge_many_buff(sinfo, keys, (uchar **)mergebuf,
dynamic_element(&sinfo->buffpek, 0, BUFFPEK *),
- &maxbuffer, &sinfo->tempfile))
+ (int*) &maxbuffer, &sinfo->tempfile))
{
got_error=1;
continue;
diff --git a/myisammrg/Makefile.am b/myisammrg/Makefile.am
index 299b1a20d6e..6a6824affba 100644
--- a/myisammrg/Makefile.am
+++ b/myisammrg/Makefile.am
@@ -21,7 +21,7 @@ libmyisammrg_a_SOURCES = myrg_open.c myrg_extra.c myrg_info.c myrg_locking.c \
myrg_rrnd.c myrg_update.c myrg_delete.c myrg_rsame.c \
myrg_panic.c myrg_close.c myrg_create.c myrg_static.c \
myrg_rkey.c myrg_rfirst.c myrg_rlast.c myrg_rnext.c \
- myrg_rprev.c myrg_queue.c myrg_write.c
+ myrg_rprev.c myrg_queue.c myrg_write.c myrg_range.c
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/myisammrg/myrg_range.c b/myisammrg/myrg_range.c
new file mode 100644
index 00000000000..7644ae40c7b
--- /dev/null
+++ b/myisammrg/myrg_range.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "myrg_def.h"
+
+ha_rows myrg_records_in_range(MYRG_INFO *info, int inx, const byte *start_key,
+ uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key, uint end_key_len,
+ enum ha_rkey_function end_search_flag)
+{
+ ha_rows records=0, res;
+ MYRG_TABLE *table;
+
+ for (table=info->open_tables ; table != info->end_table ; table++)
+ {
+ res=mi_records_in_range(table->table, inx,
+ start_key, start_key_len, start_search_flag,
+ end_key, end_key_len, end_search_flag);
+ if (res == HA_POS_ERROR)
+ return HA_POS_ERROR;
+ if (records > HA_POS_ERROR - res)
+ return HA_POS_ERROR-1;
+ records+=res;
+ }
+ return records;
+}
+
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index cf9b6653c5a..d585243c6bc 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -56,6 +56,7 @@ sleep_until_file_deleted ()
sleep $SLEEP_TIME_AFTER_RESTART
return
fi
+ sleep 1
loop=`expr $loop - 1`
done
}
@@ -314,6 +315,17 @@ while test $# -gt 0; do
DO_DDD=1
USE_RUNNING_SERVER=""
;;
+ --valgrind)
+ VALGRIND="valgrind --alignment=8 --leak-check=yes"
+ EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc"
+ EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc"
+ SLEEP_TIME_AFTER_RESTART=120
+ SLEEP_TIME_FOR_DELETE=120
+ ;;
+ --valgrind-options=*)
+ TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"`
+ VALGRIND="$VALGRIND $TMP"
+ ;;
--skip-*)
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT $1"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT $1"
@@ -374,6 +386,7 @@ fi
[ -d $MYSQL_TEST_DIR/var ] || mkdir $MYSQL_TEST_DIR/var
[ -d $MYSQL_TEST_DIR/var/tmp ] || mkdir $MYSQL_TEST_DIR/var/tmp
[ -d $MYSQL_TEST_DIR/var/run ] || mkdir $MYSQL_TEST_DIR/var/run
+[ -d $MYSQL_TEST_DIR/var/log ] || mkdir $MYSQL_TEST_DIR/var/log
if test ${COLUMNS:-0} -lt 80 ; then COLUMNS=80 ; fi
E=`$EXPR $COLUMNS - 8`
@@ -382,7 +395,7 @@ DASH72=`$ECHO '-----------------------------------------------------------------
# on source dist, we pick up freshly build executables
# on binary, use what is installed
if [ x$SOURCE_DIST = x1 ] ; then
- MYSQLD="$BASEDIR/sql/mysqld"
+ MYSQLD="$VALGRIND $BASEDIR/sql/mysqld"
if [ -f "$BASEDIR/client/.libs/lt-mysqltest" ] ; then
MYSQL_TEST="$BASEDIR/client/.libs/lt-mysqltest"
elif [ -f "$BASEDIR/client/.libs/mysqltest" ] ; then
@@ -405,9 +418,9 @@ if [ x$SOURCE_DIST = x1 ] ; then
else
if test -x "$BASEDIR/libexec/mysqld"
then
- MYSQLD="$BASEDIR/libexec/mysqld"
+ MYSQLD="$VALGRIND $BASEDIR/libexec/mysqld"
else
- MYSQLD="$BASEDIR/bin/mysqld"
+ MYSQLD="$VALGRIND $BASEDIR/bin/mysqld"
fi
MYSQL_TEST="$BASEDIR/bin/mysqltest"
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
@@ -459,8 +472,8 @@ fi
MYSQL_TEST_ARGS="--no-defaults --socket=$MASTER_MYSOCK --database=$DB \
- --user=$DBUSER --password=$DBPASSWD --silent -v \
- --tmpdir=$MYSQL_TMP_DIR"
+ --user=$DBUSER --password=$DBPASSWD --silent -v --skip-safemalloc \
+ --tmpdir=$MYSQL_TMP_DIR --port=$MASTER_MYPORT"
MYSQL_TEST_BIN=$MYSQL_TEST
MYSQL_TEST="$MYSQL_TEST $MYSQL_TEST_ARGS"
GDB_CLIENT_INIT=$MYSQL_TMP_DIR/gdbinit.client
@@ -706,7 +719,7 @@ manager_launch()
ident=$1
shift
if [ $USE_MANAGER = 0 ] ; then
- $@ >$CUR_MYERR 2>&1 &
+ $@ >> $CUR_MYERR 2>&1 &
sleep 2 #hack
return
fi
@@ -1052,6 +1065,8 @@ run_testcase ()
slave_init_script=$TESTDIR/$tname-slave.sh
slave_master_info_file=$TESTDIR/$tname-slave-master-info.opt
echo $tname > $CURRENT_TEST
+ echo "CURRENT_TEST: $tname" >> $SLAVE_MYERR
+ echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
SKIP_SLAVE=`$EXPR \( $tname : rpl \) = 0`
if [ $USE_MANAGER = 1 ] ; then
many_slaves=`$EXPR \( $tname : rpl_failsafe \) != 0`
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 0abf48041d6..ef4dfc307bf 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -133,20 +133,20 @@ id parent_id level
1202 107 2
1204 107 2
update ignore t1 set id=1023 where id=1010;
-select * from t1 where parent_id=102;
+select * from t1 where parent_id=102 order by parent_id,id;
id parent_id level
1008 102 2
-1015 102 2
1010 102 2
+1015 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 where used; Using index
+1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
explain select level,id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 where used; Using index
+1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
explain select level,id,parent_id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 where used
+1 SIMPLE t1 ref level level 1 const 1 Using where
select level,id from t1 where level=1;
level id
1 1002
@@ -203,7 +203,7 @@ a
2
check table t1;
Table Op Msg_type Msg_text
-test.t1 check error The handler for the table doesn't support check/repair
+test.t1 check error The handler for the table doesn't support check
drop table t1;
create table t1 (a int,b varchar(20)) type=bdb;
insert into t1 values (1,""), (2,"testing");
@@ -625,7 +625,7 @@ id parent_id level
1016 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 where used; Using index
+1 SIMPLE t1 ref level level 1 const 1 Using where; Using index
select level,id from t1 where level=1;
level id
1 1004
diff --git a/mysql-test/r/bdb_cache.result b/mysql-test/r/bdb_cache.result
new file mode 100644
index 00000000000..e5c6923162a
--- /dev/null
+++ b/mysql-test/r/bdb_cache.result
@@ -0,0 +1,100 @@
+drop table if exists t1, t2, t3;
+flush status;
+set autocommit=0;
+create table t1 (a int not null) type=bdb;
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+drop table t1;
+commit;
+set autocommit=1;
+begin;
+create table t1 (a int not null) type=bdb;
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+drop table t1;
+commit;
+create table t1 (a int not null) type=bdb;
+create table t2 (a int not null) type=bdb;
+create table t3 (a int not null) type=bdb;
+insert into t1 values (1),(2);
+insert into t2 values (1),(2);
+insert into t3 values (1),(2);
+select * from t1;
+a
+1
+2
+select * from t2;
+a
+1
+2
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+begin;
+select * from t1;
+a
+1
+2
+select * from t2;
+a
+1
+2
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+insert into t1 values (3);
+insert into t2 values (3);
+insert into t1 values (4);
+select * from t1;
+a
+1
+2
+3
+4
+select * from t2;
+a
+1
+2
+3
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 3
+show status like "Qcache_hits";
+Variable_name Value
+Qcache_hits 0
+commit;
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 1
diff --git a/mysql-test/r/bool.result b/mysql-test/r/bool.result
new file mode 100644
index 00000000000..cb82c6baa0f
--- /dev/null
+++ b/mysql-test/r/bool.result
@@ -0,0 +1,74 @@
+DROP TABLE IF EXISTS t1;
+SELECT IF(NULL AND 1, 1, 2), IF(1 AND NULL, 1, 2);
+IF(NULL AND 1, 1, 2) IF(1 AND NULL, 1, 2)
+2 2
+SELECT NULL AND 1, 1 AND NULL, 0 AND NULL, NULL and 0;
+NULL AND 1 1 AND NULL 0 AND NULL NULL and 0
+NULL NULL 0 0
+create table t1 (a int);
+insert into t1 values (0),(1),(NULL);
+SELECT * FROM t1 WHERE IF(a AND 1, 0, 1);
+a
+0
+NULL
+SELECT * FROM t1 WHERE IF(1 AND a, 0, 1);
+a
+0
+NULL
+SELECT * FROM t1 where NOT(a AND 1);
+a
+0
+SELECT * FROM t1 where NOT(1 AND a);
+a
+0
+SELECT * FROM t1 where (a AND 1)=0;
+a
+0
+SELECT * FROM t1 where (1 AND a)=0;
+a
+0
+SELECT * FROM t1 where (1 AND a)=1;
+a
+1
+SELECT * FROM t1 where (1 AND a) IS NULL;
+a
+NULL
+SET @a=0, @b=0;
+SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
+a
+SELECT * FROM t1 WHERE NOT(a>=0 AND NULL AND (@b:=@b+1));
+a
+SELECT * FROM t1 WHERE a=2 OR (NULL AND (@a:=@a+1));
+a
+SELECT * FROM t1 WHERE NOT(a=2 OR (NULL AND (@b:=@b+1)));
+a
+SELECT @a, @b;
+@a @b
+0 6
+DROP TABLE t1;
+drop table if exists t;
+create table t(a int, b int);
+insert into t values(null, null), (0, null), (1, null), (null, 0), (null, 1), (0, 0), (0, 1), (1, 0), (1, 1);
+select ifnull(A, 'N') as A, ifnull(B, 'N') as B, ifnull(not A, 'N') as nA, ifnull(not B, 'N') as nB, ifnull(A and B, 'N') as AB, ifnull(not (A and B), 'N') as `n(AB)`, ifnull((not A or not B), 'N') as nAonB, ifnull(A or B, 'N') as AoB, ifnull(not(A or B), 'N') as `n(AoB)`, ifnull(not A and not B, 'N') as nAnB from t;
+A B nA nB AB n(AB) nAonB AoB n(AoB) nAnB
+N N N N N N N N N N
+0 N 1 N 0 1 1 N N N
+1 N 0 N N N N 1 0 0
+N 0 N 1 0 1 1 N N N
+N 1 N 0 N N N 1 0 0
+0 0 1 1 0 1 1 0 1 1
+0 1 1 0 0 1 1 1 0 0
+1 0 0 1 0 1 1 1 0 0
+1 1 0 0 1 0 0 1 0 0
+select ifnull(A=1, 'N') as A, ifnull(B=1, 'N') as B, ifnull(not (A=1), 'N') as nA, ifnull(not (B=1), 'N') as nB, ifnull((A=1) and (B=1), 'N') as AB, ifnull(not ((A=1) and (B=1)), 'N') as `n(AB)`, ifnull((not (A=1) or not (B=1)), 'N') as nAonB, ifnull((A=1) or (B=1), 'N') as AoB, ifnull(not((A=1) or (B=1)), 'N') as `n(AoB)`, ifnull(not (A=1) and not (B=1), 'N') as nAnB from t;
+A B nA nB AB n(AB) nAonB AoB n(AoB) nAnB
+N N N N N N N N N N
+0 N 1 N 0 1 1 N N N
+1 N 0 N N N N 1 0 0
+N 0 N 1 0 1 1 N N N
+N 1 N 0 N N N 1 0 0
+0 0 1 1 0 1 1 0 1 1
+0 1 1 0 0 1 1 1 0 0
+1 0 0 1 0 1 1 1 0 0
+1 1 0 0 1 0 0 1 0 0
+drop table t;
diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result
index 10f149e7a9b..3ad3465fac0 100644
--- a/mysql-test/r/compare.result
+++ b/mysql-test/r/compare.result
@@ -3,7 +3,7 @@ CREATE TABLE t1 (id CHAR(12) not null, PRIMARY KEY (id));
insert into t1 values ('000000000001'),('000000000002');
explain select * from t1 where id=000000000001;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index PRIMARY PRIMARY 12 NULL 2 where used; Using index
+1 SIMPLE t1 index PRIMARY PRIMARY 12 NULL 2 Using where; Using index
select * from t1 where id=000000000001;
id
000000000001
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 49a42872fa3..0be0d624fca 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -62,7 +62,7 @@ insert into t1 (b) values ("hello"),("my"),("world");
create table t2 (key (b)) select * from t1;
explain select * from t2 where b="world";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref B B 21 const 1 where used
+1 SIMPLE t2 ref B B 21 const 1 Using where
select * from t2 where b="world";
a B
3 world
diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result
index 057e0308313..fec5ece8ddf 100644
--- a/mysql-test/r/distinct.result
+++ b/mysql-test/r/distinct.result
@@ -175,7 +175,7 @@ explain SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 index a a 5 NULL 6 Using index; Using temporary
1 SIMPLE t2 index a a 4 NULL 5 Using index; Distinct
-1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 t2.a 1 where used; Distinct
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 t2.a 1 Using where; Distinct
SELECT distinct t3.a FROM t3,t2,t1 WHERE t3.a=t1.b AND t1.a=t2.a;
a
1
@@ -190,7 +190,7 @@ insert into t3 select * from t4;
explain select distinct t1.a from t1,t3 where t1.a=t3.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 2 Using index; Using temporary
-1 SIMPLE t3 ref a a 5 t1.a 10 where used; Using index; Distinct
+1 SIMPLE t3 ref a a 5 t1.a 10 Using where; Using index; Distinct
select distinct t1.a from t1,t3 where t1.a=t3.a;
a
1
@@ -278,10 +278,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index id id 4 NULL 2 Using index; Using temporary
1 SIMPLE t2 index id id 8 NULL 1 Using index; Distinct
1 SIMPLE t3 index id id 8 NULL 1 Using index; Distinct
-1 SIMPLE j_lj_t2 index id id 4 NULL 2 where used; Using index; Distinct
-1 SIMPLE t2_lj index id id 8 NULL 1 where used; Using index; Distinct
-1 SIMPLE j_lj_t3 index id id 4 NULL 2 where used; Using index; Distinct
-1 SIMPLE t3_lj index id id 8 NULL 1 where used; Using index; Distinct
+1 SIMPLE j_lj_t2 index id id 4 NULL 2 Using where; Using index; Distinct
+1 SIMPLE t2_lj index id id 8 NULL 1 Using where; Using index; Distinct
+1 SIMPLE j_lj_t3 index id id 4 NULL 2 Using where; Using index; Distinct
+1 SIMPLE t3_lj index id id 8 NULL 1 Using where; Using index; Distinct
SELECT DISTINCT
t1.id
from
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index 0d97aeaf531..dafed9a7d41 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -10,13 +10,13 @@ id str
3 foo
explain select * from t1 where str is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref str str 11 const 1 where used
+1 SIMPLE t1 ref str str 11 const 1 Using where
explain select * from t1 where str="foo";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const str str 11 const 1
explain select * from t1 ignore key (str) where str="foo";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 4 where used
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
explain select * from t1 use key (str,str) where str="foo";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const str str 11 const 1
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index ea632732017..a991981bf21 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -85,6 +85,9 @@ Full-text search in MySQL implements vector space model
select * from t1 where MATCH a,b AGAINST ('"text search" +"now support"' IN BOOLEAN MODE);
a b
MySQL has now support for full-text search
+select * from t1 where MATCH a,b AGAINST ('"text i"' IN BOOLEAN MODE);
+a b
+Full-text indexes are called collections
select * from t1 where MATCH a AGAINST ("search" IN BOOLEAN MODE);
a b
Full-text search in MySQL implements vector space model
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 5433194c719..4a1012f73bf 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
from_days(to_days("960101")) to_days(960201)-to_days("19960101") to_days(date_add(curdate(), interval 1 day))-to_days(curdate()) weekday("1997-11-29")
1996-01-01 31 1 5
@@ -84,6 +84,12 @@ select yearweek("2000-01-01",1) as '2000', yearweek("2001-01-01",1) as '2001', y
select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', yearweek("2002-01-06",1) as '2002',yearweek("2003-01-06",1) as '2003', yearweek("2004-01-06",1) as '2004', yearweek("2005-01-06",1) as '2005', yearweek("2006-01-06",1) as '2006';
2000 2001 2002 2003 2004 2005 2006
200001 200101 200201 200302 200402 200501 200601
+select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3);
+week(19981231,2) week(19981231,3) week(20000101,2) week(20000101,3)
+52 53 52 52
+select week(20001231,2),week(20001231,3);
+week(20001231,2) week(20001231,3)
+1 52
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v')
1998-53 1998-53
@@ -372,3 +378,19 @@ select extract(MONTH FROM "0000-00-00"),extract(MONTH FROM d),extract(MONTH FROM
extract(MONTH FROM "0000-00-00") extract(MONTH FROM d) extract(MONTH FROM dt) extract(MONTH FROM t) extract(MONTH FROM c)
0 0 0 0 0
drop table t1;
+CREATE TABLE t1 ( start datetime default NULL);
+INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00');
+CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL);
+INSERT INTO t2 VALUES (20021029165106,20021105164731);
+CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
+INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
+select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
+start ctime1 ctime2
+2002-11-04 00:00:00 20021029165106 20021105164731
+select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
+start ctime1 ctime2
+2002-11-04 00:00:00 20021029165106 20021105164731
+select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
+start ctime1 ctime2
+2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
+drop table t1,t2,t3;
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 449d7bcb818..86a8eb2dd22 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
CREATE TABLE t1 (
spID int(10) unsigned,
userID int(10) unsigned,
@@ -234,10 +234,10 @@ userid count(*)
1 2
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range spID spID 5 NULL 2 where used; Using index
+1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range spID spID 5 NULL 2 where used; Using index
+1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index
select spid,count(*) from t1 where spid between 1 and 2 group by spid;
spid count(*)
1 1
@@ -417,3 +417,38 @@ xID xID1 Level
3 134 ***
4 185 ****
drop table t1;
+CREATE TABLE t1 (
+pid int(11) unsigned NOT NULL default '0',
+c1id int(11) unsigned default NULL,
+c2id int(11) unsigned default NULL,
+value int(11) unsigned NOT NULL default '0',
+UNIQUE KEY pid2 (pid,c1id,c2id),
+UNIQUE KEY pid (pid,value)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (1, 1, NULL, 1),(1, 2, NULL, 2),(1, NULL, 3, 3),(1, 4, NULL, 4),(1, 5, NULL, 5);
+CREATE TABLE t2 (
+id int(11) unsigned NOT NULL default '0',
+active enum('Yes','No') NOT NULL default 'Yes',
+PRIMARY KEY (id)
+) TYPE=MyISAM;
+INSERT INTO t2 VALUES (1, 'Yes'),(2, 'No'),(4, 'Yes'),(5, 'No');
+CREATE TABLE t3 (
+id int(11) unsigned NOT NULL default '0',
+active enum('Yes','No') NOT NULL default 'Yes',
+PRIMARY KEY (id)
+);
+INSERT INTO t3 VALUES (3, 'Yes');
+select * from t1 AS m LEFT JOIN t2 AS c1 ON m.c1id =
+c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND
+c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL);
+pid c1id c2id value id active id active
+1 1 NULL 1 1 Yes NULL NULL
+1 NULL 3 3 NULL NULL 3 Yes
+1 4 NULL 4 4 Yes NULL NULL
+select max(value) from t1 AS m LEFT JOIN t2 AS c1 ON
+m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id =
+c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS
+NOT NULL);
+max(value)
+4
+drop table t1,t2,t3;
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index 8fe87cdda8b..ffd62ceabb6 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -66,7 +66,7 @@ a
alter table t1 type=myisam;
explain select * from t1 where a in (869751,736494,226312,802616);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range uniq_id uniq_id 4 NULL 4 where used; Using index
+1 SIMPLE t1 range uniq_id uniq_id 4 NULL 4 Using where; Using index
drop table t1;
create table t1 (x int not null, y int not null, key x (x), unique y (y))
type=heap;
@@ -159,17 +159,17 @@ create table t1 (btn char(10) not null, key(btn)) type=heap;
insert into t1 values ("hello"),("hello"),("hello"),("hello"),("hello"),("a"),("b"),("c"),("d"),("e"),("f"),("g"),("h"),("i");
explain select * from t1 where btn like "q%";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL btn NULL NULL NULL 14 where used
+1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where
select * from t1 where btn like "q%";
btn
alter table t1 add column new_col char(1) not null, add key (btn,new_col), drop key btn;
update t1 set new_col=btn;
explain select * from t1 where btn="a";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL btn NULL NULL NULL 14 where used
+1 SIMPLE t1 ALL btn NULL NULL NULL 14 Using where
explain select * from t1 where btn="a" and new_col="a";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref btn btn 11 const,const 10 where used
+1 SIMPLE t1 ref btn btn 11 const,const 10 Using where
drop table t1;
CREATE TABLE t1 (
a int default NULL,
@@ -182,7 +182,7 @@ SELECT * FROM t1 WHERE a=NULL;
a b
explain SELECT * FROM t1 WHERE a IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 5 const 10 where used
+1 SIMPLE t1 ref a a 5 const 10 Using where
SELECT * FROM t1 WHERE a<=>NULL;
a b
NULL 99
@@ -190,7 +190,7 @@ SELECT * FROM t1 WHERE b=NULL;
a b
explain SELECT * FROM t1 WHERE b IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref b b 5 const 1 where used
+1 SIMPLE t1 ref b b 5 const 1 Using where
SELECT * FROM t1 WHERE b<=>NULL;
a b
99 NULL
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 8f139799577..81064143872 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -140,13 +140,13 @@ id parent_id level
1015 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 12 where used; Using index
+1 SIMPLE t1 ref level level 1 const 12 Using where; Using index
explain select level,id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 12 where used; Using index
+1 SIMPLE t1 ref level level 1 const 12 Using where; Using index
explain select level,id,parent_id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 12 where used
+1 SIMPLE t1 ref level level 1 const 12 Using where
select level,id from t1 where level=1;
level id
1 1002
@@ -165,7 +165,7 @@ level id parent_id
1 1007 101
optimize table t1;
Table Op Msg_type Msg_text
-test.t1 optimize error The handler for the table doesn't support check/repair
+test.t1 optimize error The handler for the table doesn't support optimize
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 id A 87 NULL NULL BTREE
@@ -189,7 +189,7 @@ create table t1 (a int) type=innodb;
insert into t1 values (1), (2);
optimize table t1;
Table Op Msg_type Msg_text
-test.t1 optimize error The handler for the table doesn't support check/repair
+test.t1 optimize error The handler for the table doesn't support optimize
delete from t1 where a = 1;
select * from t1;
a
@@ -208,7 +208,7 @@ create index skr on t1 (a);
insert into t1 values (3,""), (4,"testing");
analyze table t1;
Table Op Msg_type Msg_text
-test.t1 analyze error The handler for the table doesn't support check/repair
+test.t1 analyze error The handler for the table doesn't support analyze
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 skr 1 a A 3 NULL NULL YES BTREE
@@ -597,7 +597,7 @@ id parent_id level
1016 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 6 where used; Using index
+1 SIMPLE t1 ref level level 1 const 6 Using where; Using index
select level,id from t1 where level=1;
level id
1 1004
@@ -724,7 +724,7 @@ world 2
hello 1
optimize table t1;
Table Op Msg_type Msg_text
-test.t1 optimize error The handler for the table doesn't support check/repair
+test.t1 optimize error The handler for the table doesn't support optimize
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 a A 2 NULL NULL BTREE
@@ -759,7 +759,7 @@ create table t1 (a int primary key,b int, c int, d int, e int, f int, g int, h
insert into t1 values (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
explain select * from t1 where a > 0 and a < 50;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 where used
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where
drop table t1;
create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) type=innodb;
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
@@ -988,7 +988,7 @@ BEGIN;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT @@tx_isolation,@@global.tx_isolation;
@@tx_isolation @@global.tx_isolation
-SERIALIZABLE READ-COMMITTED
+SERIALIZABLE REPEATABLE-READ
insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David');
select id, code, name from t1 order by id;
id code name
diff --git a/mysql-test/r/isam.result b/mysql-test/r/isam.result
index 5cb218dc4ce..e8f7898f1eb 100644
--- a/mysql-test/r/isam.result
+++ b/mysql-test/r/isam.result
@@ -47,14 +47,14 @@ test.t1 optimize status OK
check table t1,t2;
Table Op Msg_type Msg_text
test.t1 check status OK
-test.t2 check error The handler for the table doesn't support check/repair
+test.t2 check error The handler for the table doesn't support check
repair table t1,t2;
Table Op Msg_type Msg_text
test.t1 repair status OK
-test.t2 repair error The handler for the table doesn't support check/repair
+test.t2 repair error The handler for the table doesn't support repair
check table t2,t1;
Table Op Msg_type Msg_text
-test.t2 check error The handler for the table doesn't support check/repair
+test.t2 check error The handler for the table doesn't support check
test.t1 check status OK
lock tables t1 write;
check table t2,t1;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 9c44792724b..700b73d3eca 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -95,7 +95,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7
-1 SIMPLE t2 eq_ref PRIMARY PRIMARY 8 t1.a 1 where used
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 8 t1.a 1 Using where
select t1.*,t2.*,t3.a from t1 left join t2 on (t1.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
grp a c id a c d a
1 1 a 1 1 a 1 1
@@ -313,11 +313,11 @@ Lilliana Angelovska NULL NULL
explain select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner) where t2.id is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
-1 SIMPLE t2 ALL NULL NULL NULL NULL 3 where used; Not exists
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where; Not exists
explain select t1.name, t2.name, t2.id from t1 left join t2 on (t1.id = t2.owner) where t2.name is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
-1 SIMPLE t2 ALL NULL NULL NULL NULL 3 where used
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
select count(*) from t1 left join t2 on (t1.id = t2.owner);
count(*)
4
@@ -333,11 +333,11 @@ Lilliana Angelovska NULL NULL
explain select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner) where t2.id is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
-1 SIMPLE t2 ALL NULL NULL NULL NULL 3 where used; Not exists
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where; Not exists
explain select t1.name, t2.name, t2.id from t2 right join t1 on (t1.id = t2.owner) where t2.name is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3
-1 SIMPLE t2 ALL NULL NULL NULL NULL 3 where used
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where
select count(*) from t2 right join t1 on (t1.id = t2.owner);
count(*)
4
@@ -620,7 +620,7 @@ INSERT INTO t2 VALUES (1,1);
explain SELECT * from t1 left join t2 on t1.id=t2.id where t2.id IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
-1 SIMPLE t2 index id id 8 NULL 1 where used; Using index; Not exists
+1 SIMPLE t2 index id id 8 NULL 1 Using where; Using index; Not exists
SELECT * from t1 left join t2 on t1.id=t2.id where t2.id IS NULL;
id name id idx
2 no NULL NULL
@@ -640,7 +640,7 @@ insert into t2 values (10,1),(20,2),(30,3);
explain select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL PRIMARY 4 NULL 3 Using index
-1 SIMPLE t1 eq_ref PRIMARY PRIMARY 2 const 1 where used; Using index
+1 SIMPLE t1 eq_ref PRIMARY PRIMARY 2 const 1 Using where; Using index
select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
fooID barID fooID
10 1 NULL
diff --git a/mysql-test/r/key_diff.result b/mysql-test/r/key_diff.result
index bdeff4f60d8..8097186bde1 100644
--- a/mysql-test/r/key_diff.result
+++ b/mysql-test/r/key_diff.result
@@ -36,7 +36,7 @@ a a a a
explain select t1.*,t2.* from t1,t1 as t2 where t1.A=t2.B;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a NULL NULL NULL 5
-1 SIMPLE t2 ALL b NULL NULL NULL 5 where used
+1 SIMPLE t2 ALL b NULL NULL NULL 5 Using where
select t1.*,t2.* from t1,t1 as t2 where t1.A=t2.B order by binary t1.a,t2.a;
a b a b
A B a a
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 27ce8e1d915..45b5bd9ddb7 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -35,10 +35,10 @@ insert into t1 select NULL,message from t2;
create table t3 (a int not null, b char(20), key(a)) type=MERGE UNION=(test.t1,test.t2);
explain select * from t3 where a < 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range a a 4 NULL 10 where used
+1 SIMPLE t3 range a a 4 NULL 10 Using where
explain select * from t3 where a > 10 and a < 20;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range a a 4 NULL 10 where used
+1 SIMPLE t3 range a a 4 NULL 10 Using where
select * from t3 where a = 10;
a b
10 Testing
@@ -541,3 +541,58 @@ select max(b) from t1 where a = 2;
max(b)
1
drop table if exists t,t1,t2;
+drop table if exists t1, t2, t3, t4, t5, t6;
+create table t1 (a int not null);
+create table t2 (a int not null);
+insert into t1 values (1);
+insert into t2 values (2);
+create temporary table t3 (a int not null) TYPE=MERGE UNION=(t1,t2);
+select * from t3;
+a
+1
+2
+create temporary table t4 (a int not null);
+create temporary table t5 (a int not null);
+insert into t4 values (1);
+insert into t5 values (2);
+create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5);
+select * from t6;
+a
+1
+2
+drop table if exists t1, t2, t3, t4, t5, t6;
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (
+fileset_id tinyint(3) unsigned NOT NULL default '0',
+file_code varchar(32) NOT NULL default '',
+fileset_root_id tinyint(3) unsigned NOT NULL default '0',
+PRIMARY KEY (fileset_id,file_code),
+KEY files (fileset_id,fileset_root_id)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (2, '0000000111', 1), (2, '0000000112', 1), (2, '0000000113', 1),
+(2, '0000000114', 1), (2, '0000000115', 1), (2, '0000000116', 1), (2, '0000000117', 1),
+(2, '0000000118', 1), (2, '0000000119', 1), (2, '0000000120', 1);
+CREATE TABLE t2 (
+fileset_id tinyint(3) unsigned NOT NULL default '0',
+file_code varchar(32) NOT NULL default '',
+fileset_root_id tinyint(3) unsigned NOT NULL default '0',
+PRIMARY KEY (fileset_id,file_code),
+KEY files (fileset_id,fileset_root_id)
+) TYPE=MRG_MyISAM UNION=(t1);
+EXPLAIN SELECT * FROM t2 IGNORE INDEX (files) WHERE fileset_id = 2
+AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
+table type possible_keys key key_len ref rows Extra
+t2 range PRIMARY PRIMARY 33 NULL 5 Using where
+EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
+AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
+table type possible_keys key key_len ref rows Extra
+t2 range PRIMARY,files PRIMARY 33 NULL 5 Using where
+EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
+AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
+table type possible_keys key key_len ref rows Extra
+t1 range PRIMARY,files PRIMARY 33 NULL 5 Using where
+EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
+AND file_code = '0000000115' LIMIT 1;
+table type possible_keys key key_len ref rows Extra
+t2 const PRIMARY,files PRIMARY 33 const,const 1
+DROP TABLE IF EXISTS t1, t2;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index 9dff4fba825..ce3f7e90f6b 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -150,4 +150,29 @@ n n
delete t1,t2 from t2 left outer join t1 using (n);
select * from t2 left outer join t1 using (n);
n n
-drop table if exists t1,t2 ;
+drop table t1,t2 ;
+create table t1 (n int(10) not null primary key, d int(10));
+create table t2 (n int(10) not null primary key, d int(10));
+insert into t1 values(1,1);
+insert into t2 values(1,10),(2,20);
+LOCK TABLES t1 write, t2 read;
+DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
+Table 't2' was locked with a READ lock and can't be updated
+UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
+Table 't2' was locked with a READ lock and can't be updated
+UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
+Table 't2' was locked with a READ lock and can't be updated
+unlock tables;
+LOCK TABLES t1 write, t2 write;
+UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
+select * from t1;
+n d
+1 10
+DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
+select * from t1;
+n d
+select * from t2;
+n d
+2 20
+unlock tables;
+drop table t1,t2;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 29818f28c45..6b9c3a53305 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -75,6 +75,218 @@ explain select a,b,c from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 4
drop table t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2), (3);
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 VALUES (1), (2), (3);
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+DROP TABLE t1;
+drop table if exists t1;
+create table t1 ( t1 char(255), key(t1(250)));
+insert t1 values ('137513751375137513751375137513751375137569516951695169516951695169516951695169');
+insert t1 values ('178417841784178417841784178417841784178403420342034203420342034203420342034203');
+insert t1 values ('213872387238723872387238723872387238723867376737673767376737673767376737673767');
+insert t1 values ('242624262426242624262426242624262426242607890789078907890789078907890789078907');
+insert t1 values ('256025602560256025602560256025602560256011701170117011701170117011701170117011');
+insert t1 values ('276027602760276027602760276027602760276001610161016101610161016101610161016101');
+insert t1 values ('281528152815281528152815281528152815281564956495649564956495649564956495649564');
+insert t1 values ('292129212921292129212921292129212921292102100210021002100210021002100210021002');
+insert t1 values ('380638063806380638063806380638063806380634483448344834483448344834483448344834');
+insert t1 values ('411641164116411641164116411641164116411616301630163016301630163016301630163016');
+insert t1 values ('420842084208420842084208420842084208420899889988998899889988998899889988998899');
+insert t1 values ('438443844384438443844384438443844384438482448244824482448244824482448244824482');
+insert t1 values ('443244324432443244324432443244324432443239613961396139613961396139613961396139');
+insert t1 values ('485448544854485448544854485448544854485477847784778477847784778477847784778477');
+insert t1 values ('494549454945494549454945494549454945494555275527552755275527552755275527552755');
+insert t1 values ('538647864786478647864786478647864786478688918891889188918891889188918891889188');
+insert t1 values ('565556555655565556555655565556555655565554845484548454845484548454845484548454');
+insert t1 values ('607860786078607860786078607860786078607856665666566656665666566656665666566656');
+insert t1 values ('640164016401640164016401640164016401640141274127412741274127412741274127412741');
+insert t1 values ('719471947194719471947194719471947194719478717871787178717871787178717871787178');
+insert t1 values ('742574257425742574257425742574257425742549604960496049604960496049604960496049');
+insert t1 values ('887088708870887088708870887088708870887035963596359635963596359635963596359635');
+insert t1 values ('917791779177917791779177917791779177917773857385738573857385738573857385738573');
+insert t1 values ('933293329332933293329332933293329332933278987898789878987898789878987898789878');
+insert t1 values ('963896389638963896389638963896389638963877807780778077807780778077807780778077');
+delete from t1 where t1>'2';
+insert t1 values ('70'), ('84'), ('60'), ('20'), ('76'), ('89'), ('49'), ('50'),
+('88'), ('61'), ('42'), ('98'), ('39'), ('30'), ('25'), ('66'), ('61'), ('48'),
+('80'), ('84'), ('98'), ('19'), ('91'), ('42'), ('47');
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+drop table if exists t1;
+create table t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
+int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17
+int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
+i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34
+int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int,
+i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51
+int, i52 int, i53 int, i54 int, i55 int, i56 int, i57 int, i58 int, i59 int,
+i60 int, i61 int, i62 int, i63 int, i64 int, i65 int, i66 int, i67 int, i68
+int, i69 int, i70 int, i71 int, i72 int, i73 int, i74 int, i75 int, i76 int,
+i77 int, i78 int, i79 int, i80 int, i81 int, i82 int, i83 int, i84 int, i85
+int, i86 int, i87 int, i88 int, i89 int, i90 int, i91 int, i92 int, i93 int,
+i94 int, i95 int, i96 int, i97 int, i98 int, i99 int, i100 int, i101 int, i102
+int, i103 int, i104 int, i105 int, i106 int, i107 int, i108 int, i109 int, i110
+int, i111 int, i112 int, i113 int, i114 int, i115 int, i116 int, i117 int, i118
+int, i119 int, i120 int, i121 int, i122 int, i123 int, i124 int, i125 int, i126
+int, i127 int, i128 int, i129 int, i130 int, i131 int, i132 int, i133 int, i134
+int, i135 int, i136 int, i137 int, i138 int, i139 int, i140 int, i141 int, i142
+int, i143 int, i144 int, i145 int, i146 int, i147 int, i148 int, i149 int, i150
+int, i151 int, i152 int, i153 int, i154 int, i155 int, i156 int, i157 int, i158
+int, i159 int, i160 int, i161 int, i162 int, i163 int, i164 int, i165 int, i166
+int, i167 int, i168 int, i169 int, i170 int, i171 int, i172 int, i173 int, i174
+int, i175 int, i176 int, i177 int, i178 int, i179 int, i180 int, i181 int, i182
+int, i183 int, i184 int, i185 int, i186 int, i187 int, i188 int, i189 int, i190
+int, i191 int, i192 int, i193 int, i194 int, i195 int, i196 int, i197 int, i198
+int, i199 int, i200 int, i201 int, i202 int, i203 int, i204 int, i205 int, i206
+int, i207 int, i208 int, i209 int, i210 int, i211 int, i212 int, i213 int, i214
+int, i215 int, i216 int, i217 int, i218 int, i219 int, i220 int, i221 int, i222
+int, i223 int, i224 int, i225 int, i226 int, i227 int, i228 int, i229 int, i230
+int, i231 int, i232 int, i233 int, i234 int, i235 int, i236 int, i237 int, i238
+int, i239 int, i240 int, i241 int, i242 int, i243 int, i244 int, i245 int, i246
+int, i247 int, i248 int, i249 int, i250 int, i251 int, i252 int, i253 int, i254
+int, i255 int, i256 int, i257 int, i258 int, i259 int, i260 int, i261 int, i262
+int, i263 int, i264 int, i265 int, i266 int, i267 int, i268 int, i269 int, i270
+int, i271 int, i272 int, i273 int, i274 int, i275 int, i276 int, i277 int, i278
+int, i279 int, i280 int, i281 int, i282 int, i283 int, i284 int, i285 int, i286
+int, i287 int, i288 int, i289 int, i290 int, i291 int, i292 int, i293 int, i294
+int, i295 int, i296 int, i297 int, i298 int, i299 int, i300 int, i301 int, i302
+int, i303 int, i304 int, i305 int, i306 int, i307 int, i308 int, i309 int, i310
+int, i311 int, i312 int, i313 int, i314 int, i315 int, i316 int, i317 int, i318
+int, i319 int, i320 int, i321 int, i322 int, i323 int, i324 int, i325 int, i326
+int, i327 int, i328 int, i329 int, i330 int, i331 int, i332 int, i333 int, i334
+int, i335 int, i336 int, i337 int, i338 int, i339 int, i340 int, i341 int, i342
+int, i343 int, i344 int, i345 int, i346 int, i347 int, i348 int, i349 int, i350
+int, i351 int, i352 int, i353 int, i354 int, i355 int, i356 int, i357 int, i358
+int, i359 int, i360 int, i361 int, i362 int, i363 int, i364 int, i365 int, i366
+int, i367 int, i368 int, i369 int, i370 int, i371 int, i372 int, i373 int, i374
+int, i375 int, i376 int, i377 int, i378 int, i379 int, i380 int, i381 int, i382
+int, i383 int, i384 int, i385 int, i386 int, i387 int, i388 int, i389 int, i390
+int, i391 int, i392 int, i393 int, i394 int, i395 int, i396 int, i397 int, i398
+int, i399 int, i400 int, i401 int, i402 int, i403 int, i404 int, i405 int, i406
+int, i407 int, i408 int, i409 int, i410 int, i411 int, i412 int, i413 int, i414
+int, i415 int, i416 int, i417 int, i418 int, i419 int, i420 int, i421 int, i422
+int, i423 int, i424 int, i425 int, i426 int, i427 int, i428 int, i429 int, i430
+int, i431 int, i432 int, i433 int, i434 int, i435 int, i436 int, i437 int, i438
+int, i439 int, i440 int, i441 int, i442 int, i443 int, i444 int, i445 int, i446
+int, i447 int, i448 int, i449 int, i450 int, i451 int, i452 int, i453 int, i454
+int, i455 int, i456 int, i457 int, i458 int, i459 int, i460 int, i461 int, i462
+int, i463 int, i464 int, i465 int, i466 int, i467 int, i468 int, i469 int, i470
+int, i471 int, i472 int, i473 int, i474 int, i475 int, i476 int, i477 int, i478
+int, i479 int, i480 int, i481 int, i482 int, i483 int, i484 int, i485 int, i486
+int, i487 int, i488 int, i489 int, i490 int, i491 int, i492 int, i493 int, i494
+int, i495 int, i496 int, i497 int, i498 int, i499 int, i500 int, i501 int, i502
+int, i503 int, i504 int, i505 int, i506 int, i507 int, i508 int, i509 int, i510
+int, i511 int, i512 int, i513 int, i514 int, i515 int, i516 int, i517 int, i518
+int, i519 int, i520 int, i521 int, i522 int, i523 int, i524 int, i525 int, i526
+int, i527 int, i528 int, i529 int, i530 int, i531 int, i532 int, i533 int, i534
+int, i535 int, i536 int, i537 int, i538 int, i539 int, i540 int, i541 int, i542
+int, i543 int, i544 int, i545 int, i546 int, i547 int, i548 int, i549 int, i550
+int, i551 int, i552 int, i553 int, i554 int, i555 int, i556 int, i557 int, i558
+int, i559 int, i560 int, i561 int, i562 int, i563 int, i564 int, i565 int, i566
+int, i567 int, i568 int, i569 int, i570 int, i571 int, i572 int, i573 int, i574
+int, i575 int, i576 int, i577 int, i578 int, i579 int, i580 int, i581 int, i582
+int, i583 int, i584 int, i585 int, i586 int, i587 int, i588 int, i589 int, i590
+int, i591 int, i592 int, i593 int, i594 int, i595 int, i596 int, i597 int, i598
+int, i599 int, i600 int, i601 int, i602 int, i603 int, i604 int, i605 int, i606
+int, i607 int, i608 int, i609 int, i610 int, i611 int, i612 int, i613 int, i614
+int, i615 int, i616 int, i617 int, i618 int, i619 int, i620 int, i621 int, i622
+int, i623 int, i624 int, i625 int, i626 int, i627 int, i628 int, i629 int, i630
+int, i631 int, i632 int, i633 int, i634 int, i635 int, i636 int, i637 int, i638
+int, i639 int, i640 int, i641 int, i642 int, i643 int, i644 int, i645 int, i646
+int, i647 int, i648 int, i649 int, i650 int, i651 int, i652 int, i653 int, i654
+int, i655 int, i656 int, i657 int, i658 int, i659 int, i660 int, i661 int, i662
+int, i663 int, i664 int, i665 int, i666 int, i667 int, i668 int, i669 int, i670
+int, i671 int, i672 int, i673 int, i674 int, i675 int, i676 int, i677 int, i678
+int, i679 int, i680 int, i681 int, i682 int, i683 int, i684 int, i685 int, i686
+int, i687 int, i688 int, i689 int, i690 int, i691 int, i692 int, i693 int, i694
+int, i695 int, i696 int, i697 int, i698 int, i699 int, i700 int, i701 int, i702
+int, i703 int, i704 int, i705 int, i706 int, i707 int, i708 int, i709 int, i710
+int, i711 int, i712 int, i713 int, i714 int, i715 int, i716 int, i717 int, i718
+int, i719 int, i720 int, i721 int, i722 int, i723 int, i724 int, i725 int, i726
+int, i727 int, i728 int, i729 int, i730 int, i731 int, i732 int, i733 int, i734
+int, i735 int, i736 int, i737 int, i738 int, i739 int, i740 int, i741 int, i742
+int, i743 int, i744 int, i745 int, i746 int, i747 int, i748 int, i749 int, i750
+int, i751 int, i752 int, i753 int, i754 int, i755 int, i756 int, i757 int, i758
+int, i759 int, i760 int, i761 int, i762 int, i763 int, i764 int, i765 int, i766
+int, i767 int, i768 int, i769 int, i770 int, i771 int, i772 int, i773 int, i774
+int, i775 int, i776 int, i777 int, i778 int, i779 int, i780 int, i781 int, i782
+int, i783 int, i784 int, i785 int, i786 int, i787 int, i788 int, i789 int, i790
+int, i791 int, i792 int, i793 int, i794 int, i795 int, i796 int, i797 int, i798
+int, i799 int, i800 int, i801 int, i802 int, i803 int, i804 int, i805 int, i806
+int, i807 int, i808 int, i809 int, i810 int, i811 int, i812 int, i813 int, i814
+int, i815 int, i816 int, i817 int, i818 int, i819 int, i820 int, i821 int, i822
+int, i823 int, i824 int, i825 int, i826 int, i827 int, i828 int, i829 int, i830
+int, i831 int, i832 int, i833 int, i834 int, i835 int, i836 int, i837 int, i838
+int, i839 int, i840 int, i841 int, i842 int, i843 int, i844 int, i845 int, i846
+int, i847 int, i848 int, i849 int, i850 int, i851 int, i852 int, i853 int, i854
+int, i855 int, i856 int, i857 int, i858 int, i859 int, i860 int, i861 int, i862
+int, i863 int, i864 int, i865 int, i866 int, i867 int, i868 int, i869 int, i870
+int, i871 int, i872 int, i873 int, i874 int, i875 int, i876 int, i877 int, i878
+int, i879 int, i880 int, i881 int, i882 int, i883 int, i884 int, i885 int, i886
+int, i887 int, i888 int, i889 int, i890 int, i891 int, i892 int, i893 int, i894
+int, i895 int, i896 int, i897 int, i898 int, i899 int, i900 int, i901 int, i902
+int, i903 int, i904 int, i905 int, i906 int, i907 int, i908 int, i909 int, i910
+int, i911 int, i912 int, i913 int, i914 int, i915 int, i916 int, i917 int, i918
+int, i919 int, i920 int, i921 int, i922 int, i923 int, i924 int, i925 int, i926
+int, i927 int, i928 int, i929 int, i930 int, i931 int, i932 int, i933 int, i934
+int, i935 int, i936 int, i937 int, i938 int, i939 int, i940 int, i941 int, i942
+int, i943 int, i944 int, i945 int, i946 int, i947 int, i948 int, i949 int, i950
+int, i951 int, i952 int, i953 int, i954 int, i955 int, i956 int, i957 int, i958
+int, i959 int, i960 int, i961 int, i962 int, i963 int, i964 int, i965 int, i966
+int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974
+int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982
+int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990
+int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998
+int, i999 int, i1000 int) row_format=dynamic;
+insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+drop table if exists t1;
CREATE TABLE `t1` (
`post_id` mediumint(8) unsigned NOT NULL auto_increment,
`topic_id` mediumint(8) unsigned NOT NULL default '0',
@@ -100,14 +312,6 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
-CREATE TABLE t1 (a INT);
-INSERT INTO t1 VALUES (1), (2), (3);
-LOCK TABLES t1 WRITE;
-INSERT INTO t1 VALUES (1), (2), (3);
-OPTIMIZE TABLE t1;
-Table Op Msg_type Msg_text
-test.t1 optimize status OK
-DROP TABLE t1;
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255), KEY t1 (a, b, c));
Specified key was too long. Max key length is 500
CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index e6e3b7155a3..07724a56025 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -30,7 +30,7 @@ SELECT (NULL OR NULL) IS NULL;
1
select NULL AND 0, 0 and NULL;
NULL AND 0 0 and NULL
-NULL 0
+0 0
select inet_ntoa(null),inet_aton(null),inet_aton("122.256"),inet_aton("122.226."),inet_aton("");
inet_ntoa(null) inet_aton(null) inet_aton("122.256") inet_aton("122.226.") inet_aton("")
NULL NULL NULL NULL NULL
diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result
index cbc8b913f45..85687df411b 100644
--- a/mysql-test/r/null_key.result
+++ b/mysql-test/r/null_key.result
@@ -3,37 +3,37 @@ create table t1 (a int, b int not null,unique key (a,b),index(b)) type=myisam;
insert ignore into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(null,7),(9,9),(8,8),(7,7),(null,9),(null,9),(6,6);
explain select * from t1 where a is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 5 const 3 where used; Using index
+1 SIMPLE t1 ref a a 5 const 3 Using where; Using index
explain select * from t1 where a is null and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 9 const,const 1 where used; Using index
+1 SIMPLE t1 ref a,b a 9 const,const 1 Using where; Using index
explain select * from t1 where a is null and b = 7;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 9 const,const 1 where used; Using index
+1 SIMPLE t1 ref a,b a 9 const,const 1 Using where; Using index
explain select * from t1 where a=2 and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const a,b a 9 const,const 1
explain select * from t1 where a<=>b limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 9 NULL 12 where used; Using index
+1 SIMPLE t1 index NULL a 9 NULL 12 Using where; Using index
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 9 NULL 3 where used; Using index
+1 SIMPLE t1 range a,b a 9 NULL 3 Using where; Using index
explain select * from t1 where (a is null or a = 7) and b=7;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b b 4 const 2 where used
+1 SIMPLE t1 ref a,b b 4 const 2 Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 where used; Using index
+1 SIMPLE t1 ref a,b a 5 const 3 Using where; Using index
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 9 NULL 2 where used; Using index
+1 SIMPLE t1 range a,b a 9 NULL 2 Using where; Using index
explain select * from t1 where a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 1 where used; Using index
+1 SIMPLE t1 range a a 5 NULL 1 Using where; Using index
explain select * from t1 where a > 8 and a < 9;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 1 where used; Using index
+1 SIMPLE t1 range a a 5 NULL 1 Using where; Using index
select * from t1 where a is null;
a b
NULL 7
@@ -66,43 +66,43 @@ NULL 9
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 where used
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b = 2 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 where used
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b = 7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 where used
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a=2 and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 1 where used
+1 SIMPLE t1 ref a,b a 5 const 1 Using where
explain select * from t1 where a<=>b limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 12 where used
+1 SIMPLE t1 ALL NULL NULL NULL NULL 12 Using where
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 and c=0 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 5 where used
+1 SIMPLE t1 range a,b a 5 NULL 5 Using where
explain select * from t1 where (a is null or a = 7) and b=7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 4 where used
+1 SIMPLE t1 range a,b a 5 NULL 4 Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 where used
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 where used
+1 SIMPLE t1 ref a,b a 5 const 3 Using where
explain select * from t1 where a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 1 where used
+1 SIMPLE t1 range a a 5 NULL 1 Using where
explain select * from t1 where a is null and b=7 or a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 4 where used
+1 SIMPLE t1 range a,b a 5 NULL 4 Using where
explain select * from t1 where a > 8 and a < 9;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 1 where used
+1 SIMPLE t1 range a a 5 NULL 1 Using where
explain select * from t1 where b like "6%";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range b b 12 NULL 1 where used
+1 SIMPLE t1 range b b 12 NULL 1 Using where
select * from t1 where a is null;
a b c
NULL 7 0
@@ -152,7 +152,7 @@ INSERT INTO t1 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4
INSERT INTO t2 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4),(9,NULL),(10,NULL);
explain select id from t1 where uniq_id is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref idx1 idx1 5 const 1 where used
+1 SIMPLE t1 ref idx1 idx1 5 const 1 Using where
explain select id from t1 where uniq_id =1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const idx1 idx1 5 const 1
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 64e2c9f5240..5645961a178 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -264,13 +264,13 @@ create table t1 (a int not null, b int, c varchar(10), key (a, b, c));
insert into t1 values (1, NULL, NULL), (1, NULL, 'b'), (1, 1, NULL), (1, 1, 'b'), (1, 1, 'b'), (2, 1, 'a'), (2, 1, 'b'), (2, 2, 'a'), (2, 2, 'b'), (2, 3, 'c'),(1,3,'b');
explain select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 20 NULL 2 where used; Using index
+1 SIMPLE t1 range a a 20 NULL 2 Using where; Using index
select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
a b c
1 NULL b
explain select * from t1 where a >= 1 and a < 3 order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 4 NULL 10 where used; Using index
+1 SIMPLE t1 range a a 4 NULL 10 Using where; Using index
select * from t1 where a >= 1 and a < 3 order by a desc;
a b c
2 3 c
@@ -286,7 +286,7 @@ a b c
1 NULL NULL
explain select * from t1 where a = 1 order by a desc, b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 4 const 5 where used; Using index
+1 SIMPLE t1 ref a a 4 const 5 Using where; Using index
select * from t1 where a = 1 order by a desc, b desc;
a b c
1 3 b
@@ -297,30 +297,30 @@ a b c
1 NULL NULL
explain select * from t1 where a = 1 and b is null order by a desc, b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 9 const,const 2 where used; Using index; Using filesort
+1 SIMPLE t1 ref a a 9 const,const 2 Using where; Using index; Using filesort
select * from t1 where a = 1 and b is null order by a desc, b desc;
a b c
1 NULL NULL
1 NULL b
explain select * from t1 where a >= 1 and a < 3 and b >0 order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 9 NULL 8 where used; Using index; Using filesort
+1 SIMPLE t1 range a a 9 NULL 8 Using where; Using index; Using filesort
explain select * from t1 where a = 2 and b >0 order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 9 NULL 5 where used; Using index
+1 SIMPLE t1 range a a 9 NULL 5 Using where; Using index
explain select * from t1 where a = 2 and b is null order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 9 const,const 1 where used; Using index; Using filesort
+1 SIMPLE t1 ref a a 9 const,const 1 Using where; Using index; Using filesort
explain select * from t1 where a = 2 and (b is null or b > 0) order by a
desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 9 NULL 6 where used; Using index
+1 SIMPLE t1 range a a 9 NULL 6 Using where; Using index
explain select * from t1 where a = 2 and b > 0 order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 9 NULL 5 where used; Using index
+1 SIMPLE t1 range a a 9 NULL 5 Using where; Using index
explain select * from t1 where a = 2 and b < 2 order by a desc,b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 9 NULL 2 where used; Using index; Using filesort
+1 SIMPLE t1 range a a 9 NULL 2 Using where; Using index; Using filesort
alter table t1 modify b int not null, modify c varchar(10) not null;
explain select * from t1 order by a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
@@ -356,14 +356,14 @@ a b c
1 0
explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 18 NULL 3 where used; Using index
+1 SIMPLE t1 range a a 18 NULL 3 Using where; Using index
select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
a b c
1 1 b
1 1 b
explain select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 4 NULL 6 where used; Using index
+1 SIMPLE t1 range a a 4 NULL 6 Using where; Using index
select * from t1 where a < 2 and b <= 1 order by a desc, b desc;
a b c
1 1 b
@@ -387,7 +387,7 @@ a b c
1 1
explain select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 8 NULL 10 where used; Using index
+1 SIMPLE t1 range a a 8 NULL 10 Using where; Using index
select * from t1 where a between 1 and 3 and b <= 1 order by a desc, b desc;
a b c
2 1 b
@@ -399,7 +399,7 @@ a b c
1 0
explain select * from t1 where a between 0 and 1 order by a desc, b desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 4 NULL 5 where used; Using index
+1 SIMPLE t1 range a a 4 NULL 5 Using where; Using index
select * from t1 where a between 0 and 1 order by a desc, b desc;
a b c
1 3 b
@@ -452,24 +452,24 @@ EXPLAIN select t1.gid, t2.sid, t3.uid from t3, t2, t1 where t2.gid = t1.gid and
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index
1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 where used; Using index
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t1.gid,t3.skr;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 where used
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where
EXPLAIN SELECT t1.gid, t2.sid, t3.uid from t2, t1, t3 where t2.gid = t1.gid and t2.uid = t3.uid order by t3.uid, t1.gid;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
1 SIMPLE t2 eq_ref PRIMARY,uid PRIMARY 4 t1.gid 1
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 where used; Using index
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t2.uid 1 Using where; Using index
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.gid = t3.uid order by t3.skr,t1.gid;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index PRIMARY PRIMARY 4 NULL 6 Using index; Using temporary; Using filesort
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 where used
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.gid 1 Using where
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.skr = t3.uid order by t1.gid,t3.skr;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.skr 1 where used
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 t1.skr 1 Using where
drop table t1,t2,t3;
CREATE TABLE t1 (
`titre` char(80) NOT NULL default '',
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index a09f4608142..a37313a150a 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -320,6 +320,9 @@ insert into t1 select * from t2;
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
+show status like "Qcache_lowmem_prunes";
+Variable_name Value
+Qcache_lowmem_prunes 0
select a as a1, a as a2 from t1;
select a as a2, a as a3 from t1;
select a as a3, a as a4 from t1;
@@ -330,6 +333,9 @@ Qcache_hits 4
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
+show status like "Qcache_lowmem_prunes";
+Variable_name Value
+Qcache_lowmem_prunes 2
reset query cache;
insert into t2 select * from t1;
insert into t1 select * from t2;
diff --git a/mysql-test/r/rpl000007.result b/mysql-test/r/rpl000007.result
deleted file mode 100644
index 6889f6af2bc..00000000000
--- a/mysql-test/r/rpl000007.result
+++ /dev/null
@@ -1,20 +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;
-drop table if exists foo;
-create table foo (n int);
-insert into foo values(4);
-drop table if exists foo;
-create table foo (s char(20));
-load data infile '../../std_data/words.dat' into table foo;
-insert into foo values('five');
-drop table if exists bar;
-create table bar (m int);
-insert into bar values(15);
-select foo.n,bar.m from foo,bar;
-n m
-4 15
-drop table if exists bar,foo;
diff --git a/mysql-test/r/rpl_replicate_do.result b/mysql-test/r/rpl_replicate_do.result
new file mode 100644
index 00000000000..aabda54640c
--- /dev/null
+++ b/mysql-test/r/rpl_replicate_do.result
@@ -0,0 +1,28 @@
+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 table if exists t11;
+drop table if exists t11;
+create table t2 (n int);
+insert into t2 values(4);
+create table t2 (s char(20));
+load data infile '../../std_data/words.dat' into table t2;
+insert into t2 values('five');
+create table t1 (m int);
+insert into t1 values(15),(16),(17);
+update t1 set m=20 where m=16;
+delete from t1 where m=17;
+create table t11 select * from t1;
+select * from t1;
+m
+15
+20
+select * from t2;
+n
+4
+select * from t11;
+Table 'test.t11' doesn't exist
+drop table if exists t1,t2,t3,t11;
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index a5928edfaa3..2582b875daa 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -1,3 +1,5 @@
+drop table if exists t1, t2, t3, t4;
+drop table if exists t1, t2, t3, t4;
start slave;
Could not initialize master info structure, check permisions on master.info
start slave;
@@ -8,7 +10,6 @@ reset slave;
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
reset master;
start slave;
-drop table if exists t1, t2, t3, t4;
create temporary table temp_table (a char(80) not null);
insert into temp_table values ("testing temporary tables");
create table t1 (s text);
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 3a15e419fa5..2615ee542e3 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -1328,19 +1328,19 @@ 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 where used; Using index
+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 index NULL fld3 30 NULL 1199 where used; Using index
+1 SIMPLE t2 index NULL fld3 30 NULL 1199 Using where; Using index
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 index NULL fld3 30 NULL 1199 where used; Using index
+1 SIMPLE t2 index NULL fld3 30 NULL 1199 Using where; Using index
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 where used; Using index
+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 where used; Using index
+1 SIMPLE t2 ref fld3 fld3 30 const 1 Using where; Using index
explain select fld3 from t2 ignore index (fld3,not_used);
Key column 'not_used' doesn't exist in table
explain select fld3 from t2 use index (not_used);
@@ -1351,7 +1351,7 @@ 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 where used; Using index
+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
@@ -1371,7 +1371,7 @@ fld1
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 where used; Using index
+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
@@ -1380,7 +1380,7 @@ fld1
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 where used; Using index
+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
@@ -1807,8 +1807,8 @@ select distinct fld3 from t2,t3 where t2.companynr = 34 and t2.fld1=t3.t2nr orde
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 where used; Using temporary; Using filesort
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 t2.fld1 1 where used; Using index
+1 SIMPLE t2 ALL fld1 NULL NULL NULL 1199 Using where; Using temporary; Using filesort
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 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
@@ -2575,11 +2575,11 @@ companynr companyname
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 1199
-1 SIMPLE t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 where used; Not exists
+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 1199 where used; Not exists
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where; Not exists
select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
companynr companynr
37 36
@@ -2587,7 +2587,7 @@ companynr companynr
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 t2 ALL NULL NULL NULL NULL 1199 Using temporary
-1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 where used; Using index
+1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using where; Using index
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
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index 84a00bfea34..45f879e182b 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -72,3 +72,25 @@ id val elt(two.val,'one','two')
2 1 one
4 2 two
drop table t1,t2;
+drop table if exists t1;
+CREATE TABLE t1 (
+d datetime default NULL
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES ('2002-10-24 14:50:32'),('2002-10-24 14:50:33'),('2002-10-24 14:50:34'),('2002-10-24 14:50:34'),('2002-10-24 14:50:34'),('2002-10-24 14:50:35'),('2002-10-24 14:50:35'),('2002-10-24 14:50:35'),('2002-10-24 14:50:35'),('2002-10-24 14:50:36'),('2002-10-24 14:50:36'),('2002-10-24 14:50:36'),('2002-10-24 14:50:36'),('2002-10-24 14:50:37'),('2002-10-24 14:50:37'),('2002-10-24 14:50:37'),('2002-10-24 14:50:37'),('2002-10-24 14:50:38'),('2002-10-24 14:50:38'),('2002-10-24 14:50:38'),('2002-10-24 14:50:39'),('2002-10-24 14:50:39'),('2002-10-24 14:50:39'),('2002-10-24 14:50:39'),('2002-10-24 14:50:40'),('2002-10-24 14:50:40'),('2002-10-24 14:50:40');
+flush status;
+select * from t1 group by d;
+d
+2002-10-24 14:50:32
+2002-10-24 14:50:33
+2002-10-24 14:50:34
+2002-10-24 14:50:35
+2002-10-24 14:50:36
+2002-10-24 14:50:37
+2002-10-24 14:50:38
+2002-10-24 14:50:39
+2002-10-24 14:50:40
+show status like "created_tmp%tables";
+Variable_name Value
+Created_tmp_disk_tables 0
+Created_tmp_tables 1
+drop table t1;
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 22cfd2ceefa..1e58b8da42e 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -76,5 +76,5 @@ date numfacture expedition
0000-00-00 00:00:00 1212 0001-00-00 00:00:00
EXPLAIN SELECT * FROM t1 WHERE expedition='0001-00-00 00:00:00';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref expedition expedition 8 const 1 where used
+1 SIMPLE t1 ref expedition expedition 8 const 1 Using where
drop table t1;
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index 6550e981f5e..0e60eefc9c7 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -346,3 +346,14 @@ a
1234567890
9999999999
drop table t1;
+create table t1(a decimal(10,0));
+insert into t1 values ("1e4294967295");
+select * from t1;
+a
+99999999999
+delete from t1;
+insert into t1 values("1e4294967297");
+select * from t1;
+a
+99999999999
+drop table t1;
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 7421c040766..1b0b359c533 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -19,14 +19,14 @@ i @vv1:=if(sv1.i,1,0) @vv2:=if(sv2.i,1,0) @vv3:=if(sv3.i,1,0) @vv1+@vv2+@vv3
2 1 0 0 1
explain select * from t1 where i=@vv1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref i i 4 const 1 where used
+1 SIMPLE t1 ref i i 4 const 1 Using where
explain select * from t1 where @vv1:=@vv1+1 and i=@vv1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 3 where used
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
explain select @vv1:=i from t1 where i=@vv1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL i 4 NULL 3 where used; Using index
+1 SIMPLE t1 index NULL i 4 NULL 3 Using where; Using index
explain select * from t1 where i=@vv1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref i i 4 const 1 where used
+1 SIMPLE t1 ref i i 4 const 1 Using where
drop table t1,t2;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index 03454f101d4..fbbf7fcb8f4 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -105,7 +105,6 @@ show global variables like 'table_type';
Variable_name Value
table_type INNODB
set GLOBAL query_cache_size=100000;
-set GLOBAL safe_show_database=0;
set myisam_max_sort_file_size=10000, GLOBAL myisam_max_sort_file_size=20000;
show variables like 'myisam_max_sort_file_size';
Variable_name Value
@@ -168,6 +167,10 @@ convert_character_set cp1251_koi8
select @@timestamp>0;
@@timestamp>0
1
+set @@rand_seed1=10000000,@@rand_seed2=1000000;
+select ROUND(RAND(),5);
+ROUND(RAND(),5)
+0.02887
set big_tables=OFFF;
Variable 'big_tables' can't be set to the value of 'OFFF'
set big_tables="OFFF";
@@ -273,7 +276,6 @@ set global query_cache_type=demand;
set read_buffer_size=100;
set read_rnd_buffer_size=100;
set global rpl_recovery_rank=100;
-set global safe_show_database=1;
set global server_id=100;
set global slave_net_timeout=100;
set global slow_launch_time=100;
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 0df93b5f220..608d4bf5042 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -39,7 +39,7 @@ select * from t1;
update ignore t1 set id=id+1; # This will change all rows
select * from t1;
update ignore t1 set id=1023 where id=1010;
-select * from t1 where parent_id=102;
+select * from t1 where parent_id=102 order by parent_id,id;
explain select level from t1 where level=1;
explain select level,id from t1 where level=1;
explain select level,id,parent_id from t1 where level=1;
diff --git a/mysql-test/t/bdb_cache-master.opt b/mysql-test/t/bdb_cache-master.opt
new file mode 100644
index 00000000000..5f0ebff98f6
--- /dev/null
+++ b/mysql-test/t/bdb_cache-master.opt
@@ -0,0 +1 @@
+--set-variable=query_cache_size=1M
diff --git a/mysql-test/t/bdb_cache.test b/mysql-test/t/bdb_cache.test
new file mode 100644
index 00000000000..aa5572886c5
--- /dev/null
+++ b/mysql-test/t/bdb_cache.test
@@ -0,0 +1,50 @@
+-- source include/have_bdb.inc
+-- source include/have_query_cache.inc
+
+#
+# Without auto_commit.
+#
+drop table if exists t1, t2, t3;
+flush status;
+set autocommit=0;
+create table t1 (a int not null) type=bdb;
+insert into t1 values (1),(2),(3);
+select * from t1;
+show status like "Qcache_queries_in_cache";
+drop table t1;
+commit;
+set autocommit=1;
+begin;
+create table t1 (a int not null) type=bdb;
+insert into t1 values (1),(2),(3);
+select * from t1;
+show status like "Qcache_queries_in_cache";
+drop table t1;
+commit;
+create table t1 (a int not null) type=bdb;
+create table t2 (a int not null) type=bdb;
+create table t3 (a int not null) type=bdb;
+insert into t1 values (1),(2);
+insert into t2 values (1),(2);
+insert into t3 values (1),(2);
+select * from t1;
+select * from t2;
+select * from t3;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+begin;
+select * from t1;
+select * from t2;
+select * from t3;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+insert into t1 values (3);
+insert into t2 values (3);
+insert into t1 values (4);
+select * from t1;
+select * from t2;
+select * from t3;
+show status like "Qcache_queries_in_cache";
+show status like "Qcache_hits";
+commit;
+show status like "Qcache_queries_in_cache"; \ No newline at end of file
diff --git a/mysql-test/t/bool.test b/mysql-test/t/bool.test
new file mode 100644
index 00000000000..10f97fefb73
--- /dev/null
+++ b/mysql-test/t/bool.test
@@ -0,0 +1,51 @@
+#
+# Test of boolean operations with NULL
+#
+
+DROP TABLE IF EXISTS t1;
+
+SELECT IF(NULL AND 1, 1, 2), IF(1 AND NULL, 1, 2);
+SELECT NULL AND 1, 1 AND NULL, 0 AND NULL, NULL and 0;
+
+create table t1 (a int);
+insert into t1 values (0),(1),(NULL);
+SELECT * FROM t1 WHERE IF(a AND 1, 0, 1);
+SELECT * FROM t1 WHERE IF(1 AND a, 0, 1);
+SELECT * FROM t1 where NOT(a AND 1);
+SELECT * FROM t1 where NOT(1 AND a);
+SELECT * FROM t1 where (a AND 1)=0;
+SELECT * FROM t1 where (1 AND a)=0;
+SELECT * FROM t1 where (1 AND a)=1;
+SELECT * FROM t1 where (1 AND a) IS NULL;
+
+# Verify that NULL optimisation works in AND clause:
+SET @a=0, @b=0;
+SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
+SELECT * FROM t1 WHERE NOT(a>=0 AND NULL AND (@b:=@b+1));
+SELECT * FROM t1 WHERE a=2 OR (NULL AND (@a:=@a+1));
+SELECT * FROM t1 WHERE NOT(a=2 OR (NULL AND (@b:=@b+1)));
+SELECT @a, @b;
+DROP TABLE t1;
+
+
+# Test boolean operators in select part
+# NULLs are represented as N for readability
+# Read nA as !A, AB as A && B, AoB as A || B
+# Result table makes ANSI happy
+
+drop table if exists t;
+create table t(a int, b int);
+insert into t values(null, null), (0, null), (1, null), (null, 0), (null, 1), (0, 0), (0, 1), (1, 0), (1, 1);
+
+# Below test is valid untill we have True/False implemented as 1/0
+# To comply to all rules it must show that: n(AB) = nAonB, n(AoB) = nAnB
+
+select ifnull(A, 'N') as A, ifnull(B, 'N') as B, ifnull(not A, 'N') as nA, ifnull(not B, 'N') as nB, ifnull(A and B, 'N') as AB, ifnull(not (A and B), 'N') as `n(AB)`, ifnull((not A or not B), 'N') as nAonB, ifnull(A or B, 'N') as AoB, ifnull(not(A or B), 'N') as `n(AoB)`, ifnull(not A and not B, 'N') as nAnB from t;
+
+# This should work with any internal representation of True/False
+# Result must be same as above
+
+select ifnull(A=1, 'N') as A, ifnull(B=1, 'N') as B, ifnull(not (A=1), 'N') as nA, ifnull(not (B=1), 'N') as nB, ifnull((A=1) and (B=1), 'N') as AB, ifnull(not ((A=1) and (B=1)), 'N') as `n(AB)`, ifnull((not (A=1) or not (B=1)), 'N') as nAonB, ifnull((A=1) or (B=1), 'N') as AoB, ifnull(not((A=1) or (B=1)), 'N') as `n(AoB)`, ifnull(not (A=1) and not (B=1), 'N') as nAnB from t;
+
+
+drop table t;
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 6483045f4ed..5a64f2614aa 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -40,6 +40,7 @@ select * from t1 where MATCH a,b AGAINST ('"Now sUPPort"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"text search" "now support"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"text search" -"now support"' IN BOOLEAN MODE);
select * from t1 where MATCH a,b AGAINST ('"text search" +"now support"' IN BOOLEAN MODE);
+select * from t1 where MATCH a,b AGAINST ('"text i"' IN BOOLEAN MODE);
# boolean w/o index:
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index a052f5f2d92..2ff57959965 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -1,7 +1,7 @@
#
# time functions
#
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
select from_days(to_days("960101")),to_days(960201)-to_days("19960101"),to_days(date_add(curdate(), interval 1 day))-to_days(curdate()),weekday("1997-11-29");
select period_add("9602",-12),period_diff(199505,"9404") ;
@@ -34,6 +34,9 @@ select yearweek("2000-01-01",0) as '2000', yearweek("2001-01-01",0) as '2001', y
select yearweek("2000-01-06",0) as '2000', yearweek("2001-01-06",0) as '2001', yearweek("2002-01-06",0) as '2002',yearweek("2003-01-06",0) as '2003', yearweek("2004-01-06",0) as '2004', yearweek("2005-01-06",0) as '2005', yearweek("2006-01-06",0) as '2006';
select yearweek("2000-01-01",1) as '2000', yearweek("2001-01-01",1) as '2001', yearweek("2002-01-01",1) as '2002',yearweek("2003-01-01",1) as '2003', yearweek("2004-01-01",1) as '2004', yearweek("2005-01-01",1) as '2005', yearweek("2006-01-01",1) as '2006';
select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', yearweek("2002-01-06",1) as '2002',yearweek("2003-01-06",1) as '2003', yearweek("2004-01-06",1) as '2004', yearweek("2005-01-06",1) as '2005', yearweek("2006-01-06",1) as '2006';
+select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3);
+select week(20001231,2),week(20001231,3);
+
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
select date_format('1999-12-31','%x-%v'),date_format('2000-01-01','%x-%v');
@@ -160,3 +163,20 @@ select yearweek("0000-00-00"),yearweek(d),yearweek(dt),yearweek(t),yearweek(c) f
select to_days("0000-00-00"),to_days(d),to_days(dt),to_days(t),to_days(c) from t1;
select extract(MONTH FROM "0000-00-00"),extract(MONTH FROM d),extract(MONTH FROM dt),extract(MONTH FROM t),extract(MONTH FROM c) from t1;
drop table t1;
+
+#
+# Test problem with TIMESTAMP and BETWEEN
+#
+
+CREATE TABLE t1 ( start datetime default NULL);
+INSERT INTO t1 VALUES ('2002-10-21 00:00:00'),('2002-10-28 00:00:00'),('2002-11-04 00:00:00');
+CREATE TABLE t2 ( ctime1 timestamp(14) NOT NULL, ctime2 timestamp(14) NOT NULL);
+INSERT INTO t2 VALUES (20021029165106,20021105164731);
+CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
+INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
+
+# The following statement should be fixed to return a row in 4.1
+select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
+select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
+select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
+drop table t1,t2,t3;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 072a1830f57..2f2f50c4085 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -2,7 +2,7 @@
# Test of group (Failed for Lars Hoss <lh@pbm.de>)
#
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
CREATE TABLE t1 (
spID int(10) unsigned,
userID int(10) unsigned,
@@ -312,3 +312,42 @@ insert into t1 values (1,244,NULL),(2,243,NULL),(134,223,NULL),(185,186,NULL);
select S.ID as xID, S.ID1 as xID1 from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2;
select S.ID as xID, S.ID1 as xID1, repeat('*',count(distinct yS.ID)) as Level from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2 group by xID order by xID1;
drop table t1;
+
+#
+# Problem with MAX and LEFT JOIN
+#
+
+CREATE TABLE t1 (
+ pid int(11) unsigned NOT NULL default '0',
+ c1id int(11) unsigned default NULL,
+ c2id int(11) unsigned default NULL,
+ value int(11) unsigned NOT NULL default '0',
+ UNIQUE KEY pid2 (pid,c1id,c2id),
+ UNIQUE KEY pid (pid,value)
+) TYPE=MyISAM;
+
+INSERT INTO t1 VALUES (1, 1, NULL, 1),(1, 2, NULL, 2),(1, NULL, 3, 3),(1, 4, NULL, 4),(1, 5, NULL, 5);
+
+CREATE TABLE t2 (
+ id int(11) unsigned NOT NULL default '0',
+ active enum('Yes','No') NOT NULL default 'Yes',
+ PRIMARY KEY (id)
+) TYPE=MyISAM;
+
+INSERT INTO t2 VALUES (1, 'Yes'),(2, 'No'),(4, 'Yes'),(5, 'No');
+
+CREATE TABLE t3 (
+ id int(11) unsigned NOT NULL default '0',
+ active enum('Yes','No') NOT NULL default 'Yes',
+ PRIMARY KEY (id)
+);
+INSERT INTO t3 VALUES (3, 'Yes');
+
+select * from t1 AS m LEFT JOIN t2 AS c1 ON m.c1id =
+c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id = c2.id AND
+c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS NOT NULL);
+select max(value) from t1 AS m LEFT JOIN t2 AS c1 ON
+m.c1id = c1.id AND c1.active = 'Yes' LEFT JOIN t3 AS c2 ON m.c2id =
+c2.id AND c2.active = 'Yes' WHERE m.pid=1 AND (c1.id IS NOT NULL OR c2.id IS
+NOT NULL);
+drop table t1,t2,t3;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 86e787db0a3..2199f50fb16 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -185,3 +185,55 @@ CREATE TABLE t ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0
select max(b) from t where a = 2;
select max(b) from t1 where a = 2;
drop table if exists t,t1,t2;
+
+#
+# temporary merge tables
+#
+drop table if exists t1, t2, t3, t4, t5, t6;
+create table t1 (a int not null);
+create table t2 (a int not null);
+insert into t1 values (1);
+insert into t2 values (2);
+create temporary table t3 (a int not null) TYPE=MERGE UNION=(t1,t2);
+select * from t3;
+create temporary table t4 (a int not null);
+create temporary table t5 (a int not null);
+insert into t4 values (1);
+insert into t5 values (2);
+create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5);
+select * from t6;
+drop table if exists t1, t2, t3, t4, t5, t6;
+
+#
+# testing merge::records_in_range and optimizer
+#
+
+DROP TABLE IF EXISTS t1, t2;
+CREATE TABLE t1 (
+ fileset_id tinyint(3) unsigned NOT NULL default '0',
+ file_code varchar(32) NOT NULL default '',
+ fileset_root_id tinyint(3) unsigned NOT NULL default '0',
+ PRIMARY KEY (fileset_id,file_code),
+ KEY files (fileset_id,fileset_root_id)
+) TYPE=MyISAM;
+INSERT INTO t1 VALUES (2, '0000000111', 1), (2, '0000000112', 1), (2, '0000000113', 1),
+(2, '0000000114', 1), (2, '0000000115', 1), (2, '0000000116', 1), (2, '0000000117', 1),
+(2, '0000000118', 1), (2, '0000000119', 1), (2, '0000000120', 1);
+CREATE TABLE t2 (
+ fileset_id tinyint(3) unsigned NOT NULL default '0',
+ file_code varchar(32) NOT NULL default '',
+ fileset_root_id tinyint(3) unsigned NOT NULL default '0',
+ PRIMARY KEY (fileset_id,file_code),
+ KEY files (fileset_id,fileset_root_id)
+) TYPE=MRG_MyISAM UNION=(t1);
+
+EXPLAIN SELECT * FROM t2 IGNORE INDEX (files) WHERE fileset_id = 2
+AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
+EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
+AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
+EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
+AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
+EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
+AND file_code = '0000000115' LIMIT 1;
+DROP TABLE IF EXISTS t1, t2;
+
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 7d855dd54ea..b3a51ff65bc 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -147,4 +147,30 @@ insert into t2 values (1),(2),(4),(8),(16),(32);
select * from t2 left outer join t1 using (n);
delete t1,t2 from t2 left outer join t1 using (n);
select * from t2 left outer join t1 using (n);
-drop table if exists t1,t2 ;
+drop table t1,t2 ;
+
+#
+# Test with locking
+#
+
+create table t1 (n int(10) not null primary key, d int(10));
+create table t2 (n int(10) not null primary key, d int(10));
+insert into t1 values(1,1);
+insert into t2 values(1,10),(2,20);
+LOCK TABLES t1 write, t2 read;
+--error 1099
+DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
+--error 1099
+UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
+# The following should be fixed to not give an error
+--error 1099
+UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
+unlock tables;
+LOCK TABLES t1 write, t2 write;
+UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
+select * from t1;
+DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
+select * from t1;
+select * from t2;
+unlock tables;
+drop table t1,t2;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index c69b87f325a..9c261ebf5bb 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -68,6 +68,227 @@ explain select a,b,c from t1;
drop table t1;
#
+# Test of OPTIMIZE of locked and modified tables
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2), (3);
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 VALUES (1), (2), (3);
+OPTIMIZE TABLE t1;
+DROP TABLE t1;
+
+#
+# Test of optimize, when only mi_sort_index (but not mi_repair*) is done
+# in ha_myisam::repair, and index size is changed (decreased).
+#
+
+drop table if exists t1;
+create table t1 ( t1 char(255), key(t1(250)));
+insert t1 values ('137513751375137513751375137513751375137569516951695169516951695169516951695169');
+insert t1 values ('178417841784178417841784178417841784178403420342034203420342034203420342034203');
+insert t1 values ('213872387238723872387238723872387238723867376737673767376737673767376737673767');
+insert t1 values ('242624262426242624262426242624262426242607890789078907890789078907890789078907');
+insert t1 values ('256025602560256025602560256025602560256011701170117011701170117011701170117011');
+insert t1 values ('276027602760276027602760276027602760276001610161016101610161016101610161016101');
+insert t1 values ('281528152815281528152815281528152815281564956495649564956495649564956495649564');
+insert t1 values ('292129212921292129212921292129212921292102100210021002100210021002100210021002');
+insert t1 values ('380638063806380638063806380638063806380634483448344834483448344834483448344834');
+insert t1 values ('411641164116411641164116411641164116411616301630163016301630163016301630163016');
+insert t1 values ('420842084208420842084208420842084208420899889988998899889988998899889988998899');
+insert t1 values ('438443844384438443844384438443844384438482448244824482448244824482448244824482');
+insert t1 values ('443244324432443244324432443244324432443239613961396139613961396139613961396139');
+insert t1 values ('485448544854485448544854485448544854485477847784778477847784778477847784778477');
+insert t1 values ('494549454945494549454945494549454945494555275527552755275527552755275527552755');
+insert t1 values ('538647864786478647864786478647864786478688918891889188918891889188918891889188');
+insert t1 values ('565556555655565556555655565556555655565554845484548454845484548454845484548454');
+insert t1 values ('607860786078607860786078607860786078607856665666566656665666566656665666566656');
+insert t1 values ('640164016401640164016401640164016401640141274127412741274127412741274127412741');
+insert t1 values ('719471947194719471947194719471947194719478717871787178717871787178717871787178');
+insert t1 values ('742574257425742574257425742574257425742549604960496049604960496049604960496049');
+insert t1 values ('887088708870887088708870887088708870887035963596359635963596359635963596359635');
+insert t1 values ('917791779177917791779177917791779177917773857385738573857385738573857385738573');
+insert t1 values ('933293329332933293329332933293329332933278987898789878987898789878987898789878');
+insert t1 values ('963896389638963896389638963896389638963877807780778077807780778077807780778077');
+delete from t1 where t1>'2';
+insert t1 values ('70'), ('84'), ('60'), ('20'), ('76'), ('89'), ('49'), ('50'),
+('88'), ('61'), ('42'), ('98'), ('39'), ('30'), ('25'), ('66'), ('61'), ('48'),
+('80'), ('84'), ('98'), ('19'), ('91'), ('42'), ('47');
+optimize table t1;
+check table t1;
+drop table t1;
+
+#
+# test of myisam with huge number of packed fields
+#
+
+drop table if exists t1;
+create table t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8
+int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17
+int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int,
+i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34
+int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int,
+i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51
+int, i52 int, i53 int, i54 int, i55 int, i56 int, i57 int, i58 int, i59 int,
+i60 int, i61 int, i62 int, i63 int, i64 int, i65 int, i66 int, i67 int, i68
+int, i69 int, i70 int, i71 int, i72 int, i73 int, i74 int, i75 int, i76 int,
+i77 int, i78 int, i79 int, i80 int, i81 int, i82 int, i83 int, i84 int, i85
+int, i86 int, i87 int, i88 int, i89 int, i90 int, i91 int, i92 int, i93 int,
+i94 int, i95 int, i96 int, i97 int, i98 int, i99 int, i100 int, i101 int, i102
+int, i103 int, i104 int, i105 int, i106 int, i107 int, i108 int, i109 int, i110
+int, i111 int, i112 int, i113 int, i114 int, i115 int, i116 int, i117 int, i118
+int, i119 int, i120 int, i121 int, i122 int, i123 int, i124 int, i125 int, i126
+int, i127 int, i128 int, i129 int, i130 int, i131 int, i132 int, i133 int, i134
+int, i135 int, i136 int, i137 int, i138 int, i139 int, i140 int, i141 int, i142
+int, i143 int, i144 int, i145 int, i146 int, i147 int, i148 int, i149 int, i150
+int, i151 int, i152 int, i153 int, i154 int, i155 int, i156 int, i157 int, i158
+int, i159 int, i160 int, i161 int, i162 int, i163 int, i164 int, i165 int, i166
+int, i167 int, i168 int, i169 int, i170 int, i171 int, i172 int, i173 int, i174
+int, i175 int, i176 int, i177 int, i178 int, i179 int, i180 int, i181 int, i182
+int, i183 int, i184 int, i185 int, i186 int, i187 int, i188 int, i189 int, i190
+int, i191 int, i192 int, i193 int, i194 int, i195 int, i196 int, i197 int, i198
+int, i199 int, i200 int, i201 int, i202 int, i203 int, i204 int, i205 int, i206
+int, i207 int, i208 int, i209 int, i210 int, i211 int, i212 int, i213 int, i214
+int, i215 int, i216 int, i217 int, i218 int, i219 int, i220 int, i221 int, i222
+int, i223 int, i224 int, i225 int, i226 int, i227 int, i228 int, i229 int, i230
+int, i231 int, i232 int, i233 int, i234 int, i235 int, i236 int, i237 int, i238
+int, i239 int, i240 int, i241 int, i242 int, i243 int, i244 int, i245 int, i246
+int, i247 int, i248 int, i249 int, i250 int, i251 int, i252 int, i253 int, i254
+int, i255 int, i256 int, i257 int, i258 int, i259 int, i260 int, i261 int, i262
+int, i263 int, i264 int, i265 int, i266 int, i267 int, i268 int, i269 int, i270
+int, i271 int, i272 int, i273 int, i274 int, i275 int, i276 int, i277 int, i278
+int, i279 int, i280 int, i281 int, i282 int, i283 int, i284 int, i285 int, i286
+int, i287 int, i288 int, i289 int, i290 int, i291 int, i292 int, i293 int, i294
+int, i295 int, i296 int, i297 int, i298 int, i299 int, i300 int, i301 int, i302
+int, i303 int, i304 int, i305 int, i306 int, i307 int, i308 int, i309 int, i310
+int, i311 int, i312 int, i313 int, i314 int, i315 int, i316 int, i317 int, i318
+int, i319 int, i320 int, i321 int, i322 int, i323 int, i324 int, i325 int, i326
+int, i327 int, i328 int, i329 int, i330 int, i331 int, i332 int, i333 int, i334
+int, i335 int, i336 int, i337 int, i338 int, i339 int, i340 int, i341 int, i342
+int, i343 int, i344 int, i345 int, i346 int, i347 int, i348 int, i349 int, i350
+int, i351 int, i352 int, i353 int, i354 int, i355 int, i356 int, i357 int, i358
+int, i359 int, i360 int, i361 int, i362 int, i363 int, i364 int, i365 int, i366
+int, i367 int, i368 int, i369 int, i370 int, i371 int, i372 int, i373 int, i374
+int, i375 int, i376 int, i377 int, i378 int, i379 int, i380 int, i381 int, i382
+int, i383 int, i384 int, i385 int, i386 int, i387 int, i388 int, i389 int, i390
+int, i391 int, i392 int, i393 int, i394 int, i395 int, i396 int, i397 int, i398
+int, i399 int, i400 int, i401 int, i402 int, i403 int, i404 int, i405 int, i406
+int, i407 int, i408 int, i409 int, i410 int, i411 int, i412 int, i413 int, i414
+int, i415 int, i416 int, i417 int, i418 int, i419 int, i420 int, i421 int, i422
+int, i423 int, i424 int, i425 int, i426 int, i427 int, i428 int, i429 int, i430
+int, i431 int, i432 int, i433 int, i434 int, i435 int, i436 int, i437 int, i438
+int, i439 int, i440 int, i441 int, i442 int, i443 int, i444 int, i445 int, i446
+int, i447 int, i448 int, i449 int, i450 int, i451 int, i452 int, i453 int, i454
+int, i455 int, i456 int, i457 int, i458 int, i459 int, i460 int, i461 int, i462
+int, i463 int, i464 int, i465 int, i466 int, i467 int, i468 int, i469 int, i470
+int, i471 int, i472 int, i473 int, i474 int, i475 int, i476 int, i477 int, i478
+int, i479 int, i480 int, i481 int, i482 int, i483 int, i484 int, i485 int, i486
+int, i487 int, i488 int, i489 int, i490 int, i491 int, i492 int, i493 int, i494
+int, i495 int, i496 int, i497 int, i498 int, i499 int, i500 int, i501 int, i502
+int, i503 int, i504 int, i505 int, i506 int, i507 int, i508 int, i509 int, i510
+int, i511 int, i512 int, i513 int, i514 int, i515 int, i516 int, i517 int, i518
+int, i519 int, i520 int, i521 int, i522 int, i523 int, i524 int, i525 int, i526
+int, i527 int, i528 int, i529 int, i530 int, i531 int, i532 int, i533 int, i534
+int, i535 int, i536 int, i537 int, i538 int, i539 int, i540 int, i541 int, i542
+int, i543 int, i544 int, i545 int, i546 int, i547 int, i548 int, i549 int, i550
+int, i551 int, i552 int, i553 int, i554 int, i555 int, i556 int, i557 int, i558
+int, i559 int, i560 int, i561 int, i562 int, i563 int, i564 int, i565 int, i566
+int, i567 int, i568 int, i569 int, i570 int, i571 int, i572 int, i573 int, i574
+int, i575 int, i576 int, i577 int, i578 int, i579 int, i580 int, i581 int, i582
+int, i583 int, i584 int, i585 int, i586 int, i587 int, i588 int, i589 int, i590
+int, i591 int, i592 int, i593 int, i594 int, i595 int, i596 int, i597 int, i598
+int, i599 int, i600 int, i601 int, i602 int, i603 int, i604 int, i605 int, i606
+int, i607 int, i608 int, i609 int, i610 int, i611 int, i612 int, i613 int, i614
+int, i615 int, i616 int, i617 int, i618 int, i619 int, i620 int, i621 int, i622
+int, i623 int, i624 int, i625 int, i626 int, i627 int, i628 int, i629 int, i630
+int, i631 int, i632 int, i633 int, i634 int, i635 int, i636 int, i637 int, i638
+int, i639 int, i640 int, i641 int, i642 int, i643 int, i644 int, i645 int, i646
+int, i647 int, i648 int, i649 int, i650 int, i651 int, i652 int, i653 int, i654
+int, i655 int, i656 int, i657 int, i658 int, i659 int, i660 int, i661 int, i662
+int, i663 int, i664 int, i665 int, i666 int, i667 int, i668 int, i669 int, i670
+int, i671 int, i672 int, i673 int, i674 int, i675 int, i676 int, i677 int, i678
+int, i679 int, i680 int, i681 int, i682 int, i683 int, i684 int, i685 int, i686
+int, i687 int, i688 int, i689 int, i690 int, i691 int, i692 int, i693 int, i694
+int, i695 int, i696 int, i697 int, i698 int, i699 int, i700 int, i701 int, i702
+int, i703 int, i704 int, i705 int, i706 int, i707 int, i708 int, i709 int, i710
+int, i711 int, i712 int, i713 int, i714 int, i715 int, i716 int, i717 int, i718
+int, i719 int, i720 int, i721 int, i722 int, i723 int, i724 int, i725 int, i726
+int, i727 int, i728 int, i729 int, i730 int, i731 int, i732 int, i733 int, i734
+int, i735 int, i736 int, i737 int, i738 int, i739 int, i740 int, i741 int, i742
+int, i743 int, i744 int, i745 int, i746 int, i747 int, i748 int, i749 int, i750
+int, i751 int, i752 int, i753 int, i754 int, i755 int, i756 int, i757 int, i758
+int, i759 int, i760 int, i761 int, i762 int, i763 int, i764 int, i765 int, i766
+int, i767 int, i768 int, i769 int, i770 int, i771 int, i772 int, i773 int, i774
+int, i775 int, i776 int, i777 int, i778 int, i779 int, i780 int, i781 int, i782
+int, i783 int, i784 int, i785 int, i786 int, i787 int, i788 int, i789 int, i790
+int, i791 int, i792 int, i793 int, i794 int, i795 int, i796 int, i797 int, i798
+int, i799 int, i800 int, i801 int, i802 int, i803 int, i804 int, i805 int, i806
+int, i807 int, i808 int, i809 int, i810 int, i811 int, i812 int, i813 int, i814
+int, i815 int, i816 int, i817 int, i818 int, i819 int, i820 int, i821 int, i822
+int, i823 int, i824 int, i825 int, i826 int, i827 int, i828 int, i829 int, i830
+int, i831 int, i832 int, i833 int, i834 int, i835 int, i836 int, i837 int, i838
+int, i839 int, i840 int, i841 int, i842 int, i843 int, i844 int, i845 int, i846
+int, i847 int, i848 int, i849 int, i850 int, i851 int, i852 int, i853 int, i854
+int, i855 int, i856 int, i857 int, i858 int, i859 int, i860 int, i861 int, i862
+int, i863 int, i864 int, i865 int, i866 int, i867 int, i868 int, i869 int, i870
+int, i871 int, i872 int, i873 int, i874 int, i875 int, i876 int, i877 int, i878
+int, i879 int, i880 int, i881 int, i882 int, i883 int, i884 int, i885 int, i886
+int, i887 int, i888 int, i889 int, i890 int, i891 int, i892 int, i893 int, i894
+int, i895 int, i896 int, i897 int, i898 int, i899 int, i900 int, i901 int, i902
+int, i903 int, i904 int, i905 int, i906 int, i907 int, i908 int, i909 int, i910
+int, i911 int, i912 int, i913 int, i914 int, i915 int, i916 int, i917 int, i918
+int, i919 int, i920 int, i921 int, i922 int, i923 int, i924 int, i925 int, i926
+int, i927 int, i928 int, i929 int, i930 int, i931 int, i932 int, i933 int, i934
+int, i935 int, i936 int, i937 int, i938 int, i939 int, i940 int, i941 int, i942
+int, i943 int, i944 int, i945 int, i946 int, i947 int, i948 int, i949 int, i950
+int, i951 int, i952 int, i953 int, i954 int, i955 int, i956 int, i957 int, i958
+int, i959 int, i960 int, i961 int, i962 int, i963 int, i964 int, i965 int, i966
+int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974
+int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982
+int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990
+int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998
+int, i999 int, i1000 int) row_format=dynamic;
+insert into t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+drop table if exists t1;
+
+#
# Test of REPAIR that once failed
#
CREATE TABLE `t1` (
@@ -95,16 +316,6 @@ CHECK TABLE t1;
drop table t1;
#
-# Test of OPTIMIZE of locked and modified tables
-#
-CREATE TABLE t1 (a INT);
-INSERT INTO t1 VALUES (1), (2), (3);
-LOCK TABLES t1 WRITE;
-INSERT INTO t1 VALUES (1), (2), (3);
-OPTIMIZE TABLE t1;
-DROP TABLE t1;
-
-#
# Test of creating table with too long key
#
@@ -114,3 +325,4 @@ CREATE TABLE t1 (a varchar(255), b varchar(255), c varchar(255));
--error 1071
ALTER TABLE t1 ADD INDEX t1 (a, b, c);
DROP TABLE t1;
+
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index a0d2a34ee76..6c3f3d6ac52 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -206,6 +206,7 @@ insert into t2 select * from t1; # 2584
insert into t1 select * from t2; # 4181
show status like "Qcache_hits";
+show status like "Qcache_lowmem_prunes";
disable_result_log;
select a as a1, a as a2 from t1;
select a as a2, a as a3 from t1;
@@ -215,6 +216,7 @@ select a as a1, a as a2 from t1;
enable_result_log;
show status like "Qcache_hits";
show status like "Qcache_queries_in_cache";
+show status like "Qcache_lowmem_prunes";
reset query cache;
#
# Query bigger then query_cache_limit
diff --git a/mysql-test/t/rpl000007-slave.opt b/mysql-test/t/rpl000007-slave.opt
deleted file mode 100644
index 9ff99337d1f..00000000000
--- a/mysql-test/t/rpl000007-slave.opt
+++ /dev/null
@@ -1 +0,0 @@
---replicate-do-table=test.bar
diff --git a/mysql-test/t/rpl000007.test b/mysql-test/t/rpl000007.test
deleted file mode 100644
index 8ff1e1782cc..00000000000
--- a/mysql-test/t/rpl000007.test
+++ /dev/null
@@ -1,24 +0,0 @@
-#this one assumes we are ignoring updates on table foo, but doing
-#the ones on bar
-source include/master-slave.inc;
-connection slave;
-drop table if exists foo;
-create table foo (n int);
-insert into foo values(4);
-connection master;
-drop table if exists foo;
-create table foo (s char(20));
-load data infile '../../std_data/words.dat' into table foo;
-insert into foo values('five');
-drop table if exists bar;
-create table bar (m int);
-insert into bar values(15);
-save_master_pos;
-connection slave;
-sync_with_master;
-select foo.n,bar.m from foo,bar;
-connection master;
-drop table if exists bar,foo;
-save_master_pos;
-connection slave;
-sync_with_master;
diff --git a/mysql-test/t/rpl_replicate_do-slave.opt b/mysql-test/t/rpl_replicate_do-slave.opt
new file mode 100644
index 00000000000..da345474216
--- /dev/null
+++ b/mysql-test/t/rpl_replicate_do-slave.opt
@@ -0,0 +1 @@
+--replicate-do-table=test.t1
diff --git a/mysql-test/t/rpl_replicate_do.test b/mysql-test/t/rpl_replicate_do.test
new file mode 100644
index 00000000000..0800062dc05
--- /dev/null
+++ b/mysql-test/t/rpl_replicate_do.test
@@ -0,0 +1,30 @@
+# This test assumes we are ignoring updates on table t2, but doing
+# updates on t1
+
+source include/master-slave.inc;
+drop table if exists t11;
+connection slave;
+drop table if exists t11;
+create table t2 (n int);
+insert into t2 values(4);
+connection master;
+create table t2 (s char(20));
+load data infile '../../std_data/words.dat' into table t2;
+insert into t2 values('five');
+create table t1 (m int);
+insert into t1 values(15),(16),(17);
+update t1 set m=20 where m=16;
+delete from t1 where m=17;
+create table t11 select * from t1;
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from t1;
+select * from t2;
+--error 1146
+select * from t11;
+connection master;
+drop table if exists t1,t2,t3,t11;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test
index f328e938f61..c552936d93f 100644
--- a/mysql-test/t/rpl_rotate_logs.test
+++ b/mysql-test/t/rpl_rotate_logs.test
@@ -10,10 +10,12 @@
# - Test creating a duplicate key error and recover from it
#
connect (master,localhost,root,,test,0,master.sock);
+drop table if exists t1, t2, t3, t4;
connect (slave,localhost,root,,test,0,slave.sock);
system cat /dev/null > var/slave-data/master.info;
system chmod 000 var/slave-data/master.info;
connection slave;
+drop table if exists t1, t2, t3, t4;
--error 1201
start slave;
system chmod 600 var/slave-data/master.info;
@@ -31,8 +33,6 @@ connection slave;
start slave;
connection master;
-drop table if exists t1, t2, t3, t4;
-
#
# Test FLUSH LOGS
#
diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test
index 3cf18bae9fe..10168cf13c7 100644
--- a/mysql-test/t/temp_table.test
+++ b/mysql-test/t/temp_table.test
@@ -60,3 +60,21 @@ insert into t2 values (1,1),(2,1),(3,1),(4,2);
# do a query using ELT, a join and an ORDER BY.
select one.id, two.val, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
drop table t1,t2;
+
+#
+# In MySQL 4.0.4 doing a GROUP BY on a NULL column created a disk based
+# temporary table when a memory based one would be good enough.
+
+drop table if exists t1;
+
+CREATE TABLE t1 (
+ d datetime default NULL
+) TYPE=MyISAM;
+
+
+INSERT INTO t1 VALUES ('2002-10-24 14:50:32'),('2002-10-24 14:50:33'),('2002-10-24 14:50:34'),('2002-10-24 14:50:34'),('2002-10-24 14:50:34'),('2002-10-24 14:50:35'),('2002-10-24 14:50:35'),('2002-10-24 14:50:35'),('2002-10-24 14:50:35'),('2002-10-24 14:50:36'),('2002-10-24 14:50:36'),('2002-10-24 14:50:36'),('2002-10-24 14:50:36'),('2002-10-24 14:50:37'),('2002-10-24 14:50:37'),('2002-10-24 14:50:37'),('2002-10-24 14:50:37'),('2002-10-24 14:50:38'),('2002-10-24 14:50:38'),('2002-10-24 14:50:38'),('2002-10-24 14:50:39'),('2002-10-24 14:50:39'),('2002-10-24 14:50:39'),('2002-10-24 14:50:39'),('2002-10-24 14:50:40'),('2002-10-24 14:50:40'),('2002-10-24 14:50:40');
+
+flush status;
+select * from t1 group by d;
+show status like "created_tmp%tables";
+drop table t1;
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index 95420539611..7f73ec34e3a 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -220,3 +220,13 @@ create table t1 (a decimal unsigned zerofill);
insert into t1 values (-99999999999999),(-1),('+1'),('01'),('+00000000000001'),('+1234567890'),(99999999999999);
select * from t1;
drop table t1;
+
+# Exponent overflow bug
+create table t1(a decimal(10,0));
+insert into t1 values ("1e4294967295");
+select * from t1;
+delete from t1;
+insert into t1 values("1e4294967297");
+select * from t1;
+drop table t1;
+
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 564a6b864e8..552777743f8 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -66,7 +66,6 @@ set table_type=MYISAM, table_type="HEAP", global table_type="INNODB";
show local variables like 'table_type';
show global variables like 'table_type';
set GLOBAL query_cache_size=100000;
-set GLOBAL safe_show_database=0;
set myisam_max_sort_file_size=10000, GLOBAL myisam_max_sort_file_size=20000;
show variables like 'myisam_max_sort_file_size';
@@ -95,6 +94,10 @@ set global character set default, session character set default;
show variables like "convert_character_set";
select @@timestamp>0;
+set @@rand_seed1=10000000,@@rand_seed2=1000000;
+select ROUND(RAND(),5);
+
+
# The following should give errors
--error 1231
@@ -189,7 +192,6 @@ set global query_cache_type=demand;
set read_buffer_size=100;
set read_rnd_buffer_size=100;
set global rpl_recovery_rank=100;
-set global safe_show_database=1;
set global server_id=100;
set global slave_net_timeout=100;
set global slow_launch_time=100;
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 5c0a531c37c..2661363de11 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -56,11 +56,10 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
-# test_fn removed 980815 since it not upp to date test_dir
-noinst_PROGRAMS = test_charset charset2html @THREAD_LPROGRAMS@
+noinst_PROGRAMS = charset2html @THREAD_LPROGRAMS@
# test_dir_DEPENDENCIES= $(LIBRARIES)
# testhash_DEPENDENCIES= $(LIBRARIES)
-test_charset_DEPENDENCIES= $(LIBRARIES)
+# test_charset_DEPENDENCIES= $(LIBRARIES)
charset2html_DEPENDENCIES= $(LIBRARIES)
EXTRA_PROGRAMS =
DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
diff --git a/mysys/hash.c b/mysys/hash.c
index 2ef17be5341..7707e7019c9 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -84,7 +84,12 @@ void hash_free(HASH *hash)
/* some helper functions */
-inline byte*
+/*
+ This function is char* instead of byte* as HPUX11 compiler can't
+ handle inline functions that are not defined as native types
+*/
+
+inline char*
hash_key(HASH *hash,const byte *record,uint *length,my_bool first)
{
if (hash->get_key)
@@ -105,7 +110,7 @@ static uint hash_rec_mask(HASH *hash,HASH_LINK *pos,uint buffmax,
uint maxlength)
{
uint length;
- byte *key=hash_key(hash,pos->data,&length,0);
+ byte *key= (byte*) hash_key(hash,pos->data,&length,0);
return hash_mask((*hash->calc_hashnr)(hash->charset,key,length),
buffmax,maxlength);
}
@@ -159,10 +164,10 @@ uint calc_hashnr(CHARSET_INFO *cs, const byte *key, uint len)
#ifndef __SUNPRO_C /* SUNPRO can't handle this */
inline
#endif
-uint rec_hashnr(HASH *hash,const byte *record)
+unsigned int rec_hashnr(HASH *hash,const byte *record)
{
uint length;
- byte *key=hash_key(hash,record,&length,0);
+ byte *key= (byte*) hash_key(hash,record,&length,0);
return (*hash->calc_hashnr)(hash->charset,key,length);
}
@@ -249,7 +254,7 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink)
static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length)
{
uint rec_keylength;
- byte *rec_key=hash_key(hash,pos->data,&rec_keylength,1);
+ byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1);
return (length && length != rec_keylength) ||
(hash->flags & HASH_CASE_INSENSITIVE ?
my_strncasecmp(hash->charset, rec_key,key,rec_keylength) :
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 5a573bff0f7..6a037f13f05 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -595,13 +595,14 @@ static int flush_key_blocks_int(File file, enum flush_type type)
count++;
}
/* Only allocate a new buffer if its bigger than the one we have */
- if (count <= FLUSH_CACHE ||
- !(cache=(SEC_LINK**) my_malloc(sizeof(SEC_LINK*)*count,MYF(0))))
+ if (count > FLUSH_CACHE)
{
- cache=cache_buff; /* Fall back to safe buffer */
- count=FLUSH_CACHE;
+ if (!(cache=(SEC_LINK**) my_malloc(sizeof(SEC_LINK*)*count,MYF(0))))
+ {
+ cache=cache_buff; /* Fall back to safe buffer */
+ count=FLUSH_CACHE;
+ }
}
- end=cache+count;
}
/* Go through the keys and write them to buffer to be flushed */
diff --git a/mysys/my_aes.c b/mysys/my_aes.c
index a3618e44b82..16d326d7d1f 100644
--- a/mysys/my_aes.c
+++ b/mysys/my_aes.c
@@ -60,19 +60,19 @@ static int my_aes_create_key(KEYINSTANCE *aes_key,
enum encrypt_dir direction, const char *key,
int key_length)
{
- char rkey[AES_KEY_LENGTH/8]; /* The real key to be used for encryption */
- char *rkey_end=rkey+AES_KEY_LENGTH/8; /* Real key boundary */
- char *ptr; /* Start of the real key*/
+ uint8 rkey[AES_KEY_LENGTH/8]; /* The real key to be used for encryption */
+ uint8 *rkey_end=rkey+AES_KEY_LENGTH/8; /* Real key boundary */
+ uint8 *ptr; /* Start of the real key*/
const char *sptr; /* Start of the working key */
const char *key_end=key+key_length; /* Working key boundary*/
- bzero(rkey,AES_KEY_LENGTH/8); /* Set initial key */
+ bzero((char*) rkey,AES_KEY_LENGTH/8); /* Set initial key */
for (ptr= rkey, sptr= key; sptr < key_end; ptr++,sptr++)
{
if (ptr == rkey_end)
ptr= rkey; /* Just loop over tmp_key until we used all key */
- *ptr^= *sptr;
+ *ptr^= (uint8) *sptr;
}
#ifdef AES_USE_KEY_BITS
/*
@@ -128,7 +128,7 @@ int my_aes_encrypt(const char* source, int source_length, char* dest,
const char* key, int key_length)
{
KEYINSTANCE aes_key;
- char block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */
+ uint8 block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */
int rc; /* result codes */
int num_blocks; /* number of complete blocks */
char pad_len; /* pad size for the last block */
@@ -141,7 +141,8 @@ int my_aes_encrypt(const char* source, int source_length, char* dest,
for (i = num_blocks; i > 0; i--) /* Encode complete blocks */
{
- rijndaelEncrypt(aes_key.rk, aes_key.nr, source, dest);
+ rijndaelEncrypt(aes_key.rk, aes_key.nr, (const uint8*) source,
+ (uint8*) dest);
source+= AES_BLOCK_SIZE;
dest+= AES_BLOCK_SIZE;
}
@@ -150,7 +151,7 @@ int my_aes_encrypt(const char* source, int source_length, char* dest,
pad_len = AES_BLOCK_SIZE - (source_length - AES_BLOCK_SIZE*num_blocks);
memcpy(block, source, 16 - pad_len);
bfill(block + AES_BLOCK_SIZE - pad_len, pad_len, pad_len);
- rijndaelEncrypt(aes_key.rk, aes_key.nr, block, dest);
+ rijndaelEncrypt(aes_key.rk, aes_key.nr, block, (uint8*) dest);
return AES_BLOCK_SIZE*(num_blocks + 1);
}
@@ -175,7 +176,7 @@ int my_aes_decrypt(const char *source, int source_length, char *dest,
const char *key, int key_length)
{
KEYINSTANCE aes_key;
- char block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */
+ uint8 block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */
int rc; /* Result codes */
int num_blocks; /* Number of complete blocks */
uint pad_len; /* Pad size for the last block */
@@ -191,12 +192,13 @@ int my_aes_decrypt(const char *source, int source_length, char *dest,
for (i = num_blocks-1; i > 0; i--) /* Decode all but last blocks */
{
- rijndaelDecrypt(aes_key.rk, aes_key.nr, source, dest);
+ rijndaelDecrypt(aes_key.rk, aes_key.nr, (const uint8*) source,
+ (uint8*) dest);
source+= AES_BLOCK_SIZE;
dest+= AES_BLOCK_SIZE;
}
- rijndaelDecrypt(aes_key.rk, aes_key.nr, source, block);
+ rijndaelDecrypt(aes_key.rk, aes_key.nr, (const uint8*) source, block);
/* Use last char in the block as size */
pad_len = (uint) (uchar) block[AES_BLOCK_SIZE-1];
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index f494cce8dbe..1ab86476e41 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -29,7 +29,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
mem_root->min_malloc= 32;
mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8;
mem_root->error_handler= 0;
- mem_root->block_num= 0;
+ mem_root->block_num= 4; /* We shift this with >>2 */
mem_root->first_block_usage= 0;
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
if (pre_alloc_size)
@@ -69,10 +69,11 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
reg2 USED_MEM **prev;
Size= ALIGN_SIZE(Size);
- if ( (*(prev= &mem_root->free)) != NULL )
+ if ((*(prev= &mem_root->free)) != NULL)
{
- if( (*prev)->left < Size &&
- mem_root->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP )
+ if ((*prev)->left < Size &&
+ mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP &&
+ (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP)
{
next= *prev;
*prev= next->next; /* Remove block from list */
@@ -85,7 +86,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
}
if (! next)
{ /* Time to alloc new block */
- block_size= mem_root->block_size*((mem_root->block_num>>2)+1);
+ block_size= mem_root->block_size * (mem_root->block_num >> 2);
get_size= Size+ALIGN_SIZE(sizeof(USED_MEM));
get_size= max(get_size, block_size);
@@ -177,10 +178,8 @@ void free_root(MEM_ROOT *root, myf MyFlags)
root->free=root->pre_alloc;
root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
root->free->next=0;
- root->block_num= 1;
}
- else
- root->block_num= 0;
+ root->block_num= 4;
root->first_block_usage= 0;
DBUG_VOID_RETURN;
}
diff --git a/mysys/my_append.c b/mysys/my_append.c
index 2e08b4b4c05..dc5ed084bb3 100644
--- a/mysys/my_append.c
+++ b/mysys/my_append.c
@@ -22,7 +22,7 @@
#include <sys/utime.h>
#elif defined(HAVE_UTIME_H)
#include <utime.h>
-#elif !defined(HPUX)
+#elif !defined(HPUX10)
struct utimbuf {
time_t actime;
time_t modtime;
diff --git a/mysys/my_copy.c b/mysys/my_copy.c
index 253608c5306..a899835ea62 100644
--- a/mysys/my_copy.c
+++ b/mysys/my_copy.c
@@ -22,7 +22,7 @@
#include <sys/utime.h>
#elif defined(HAVE_UTIME_H)
#include <utime.h>
-#elif !defined(HPUX)
+#elif !defined(HPUX10)
#include <time.h>
struct utimbuf {
time_t actime;
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index 54a5c71c695..07e8ecec6ac 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -435,7 +435,7 @@ int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr)
this has to be added here.
****************************************************************************/
-#if defined(HPUX) || defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT)
+#if defined(HPUX10) || defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT)
int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
struct timespec *abstime)
diff --git a/mysys/my_redel.c b/mysys/my_redel.c
index 8474dab0d13..b5a79d9454b 100644
--- a/mysys/my_redel.c
+++ b/mysys/my_redel.c
@@ -23,7 +23,7 @@
#include <sys/utime.h>
#elif defined(HAVE_UTIME_H)
#include <utime.h>
-#elif !defined(HPUX)
+#elif !defined(HPUX10)
struct utimbuf {
time_t actime;
time_t modtime;
diff --git a/mysys/my_static.c b/mysys/my_static.c
index 1eb6220f185..bbf7582a454 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -60,7 +60,7 @@ USED_MEM* my_once_root_block=0; /* pointer to first block */
uint my_once_extra=ONCE_ALLOC_INIT; /* Memory to alloc / block */
/* from my_tempnam */
-#ifndef HAVE_TEMPNAM
+#if !defined(HAVE_TEMPNAM) || defined(HPUX11)
int _my_tempnam_used=0;
#endif
diff --git a/mysys/my_static.h b/mysys/my_static.h
index 10b2e0fc2d2..c1893f4074f 100644
--- a/mysys/my_static.h
+++ b/mysys/my_static.h
@@ -65,7 +65,7 @@ extern const char *soundex_map;
extern USED_MEM* my_once_root_block;
extern uint my_once_extra;
-#ifndef HAVE_TEMPNAM
+#if !defined(HAVE_TEMPNAM) || defined(HPUX11)
extern int _my_tempnam_used;
#endif
diff --git a/mysys/my_tempnam.c b/mysys/my_tempnam.c
index 6c17aa5b165..4fa2dd2abc4 100644
--- a/mysys/my_tempnam.c
+++ b/mysys/my_tempnam.c
@@ -23,6 +23,12 @@
#include "mysys_priv.h"
#include <m_string.h>
+
+/* HPUX 11.0 doesn't allow us to change the environ pointer */
+#ifdef HPUX11
+#undef HAVE_TEMPNAM
+#endif
+
#include "my_static.h"
#include "mysys_err.h"
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index d1343d4c2d3..ed468b5ef50 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -730,11 +730,11 @@ static pthread_cond_t COND_thread_count;
static pthread_mutex_t LOCK_thread_count;
static uint thread_count;
-#ifdef HPUX
+#ifdef HPUX10
typedef int * fd_set_ptr;
#else
typedef fd_set * fd_set_ptr;
-#endif /* HPUX */
+#endif /* HPUX10 */
static void *test_thread(void *arg)
{
diff --git a/mysys/tree.c b/mysys/tree.c
index 3e20820ebd9..364b6992108 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -53,7 +53,8 @@
#define BLACK 1
#define RED 0
-#define DEFAULT_ALLOC_SIZE (8192-MALLOC_OVERHEAD)
+#define DEFAULT_ALLOC_SIZE 8192
+#define DEFAULT_ALIGN_SIZE 8192
static void delete_tree_element(TREE *,TREE_ELEMENT *);
static int tree_walk_left_root_right(TREE *,TREE_ELEMENT *,
@@ -80,8 +81,9 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
DBUG_ENTER("init_tree");
DBUG_PRINT("enter",("tree: %lx size: %d",tree,size));
- if (!default_alloc_size)
- default_alloc_size= DEFAULT_ALLOC_SIZE;
+ if (default_alloc_size < DEFAULT_ALLOC_SIZE)
+ default_alloc_size= DEFAULT_ALLOC_SIZE;
+ default_alloc_size= MY_ALIGN(default_alloc_size, DEFAULT_ALIGN_SIZE);
bzero((gptr) &tree->null_element,sizeof(tree->null_element));
tree->root= &tree->null_element;
tree->compare=compare;
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 72c869f3f64..3ffa62d27c0 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -104,6 +104,7 @@ SUFFIXES = .sh
-e 's!@''CXX''@!@CXX@!'\
-e 's!@''GXX''@!@GXX@!'\
-e 's!@''PERL''@!@PERL@!' \
+ -e 's!@''ASFLAGS''@!@SAVE_ASFLAGS@!'\
-e 's!@''CFLAGS''@!@SAVE_CFLAGS@!'\
-e 's!@''CXXFLAGS''@!@SAVE_CXXFLAGS@!'\
-e 's!@''LDFLAGS''@!@SAVE_LDFLAGS@!'\
diff --git a/scripts/mysqlbug.sh b/scripts/mysqlbug.sh
index bd5cb497e59..8dbc931b7f6 100644
--- a/scripts/mysqlbug.sh
+++ b/scripts/mysqlbug.sh
@@ -8,7 +8,7 @@ VERSION="@VERSION@@MYSQL_SERVER_SUFFIX@"
COMPILATION_COMMENT="@COMPILATION_COMMENT@"
BUGmysql="mysql@lists.mysql.com"
# This is set by configure
-COMP_ENV_INFO="CC='@CC@' CFLAGS='@CFLAGS@' CXX='@CXX@' CXXFLAGS='@CXXFLAGS@' LDFLAGS='@LDFLAGS@'"
+COMP_ENV_INFO="CC='@CC@' CFLAGS='@CFLAGS@' CXX='@CXX@' CXXFLAGS='@CXXFLAGS@' LDFLAGS='@LDFLAGS@' ASFLAGS='@ASFLAGS@'"
CONFIGURE_LINE="@CONF_COMMAND@"
LIBC_INFO=""
diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh
index b868006ee40..3165a01362c 100644
--- a/scripts/mysqld_multi.sh
+++ b/scripts/mysqld_multi.sh
@@ -4,7 +4,7 @@ use Getopt::Long;
use POSIX qw(strftime);
$|=1;
-$VER="2.4";
+$VER="2.5";
$opt_config_file = undef();
$opt_example = 0;
@@ -212,6 +212,7 @@ sub start_mysqlds()
}
else
{
+ $options[$j]=~ s/;/\\;/g;
$tmp.= " $options[$j]";
}
}
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 9dea2eb3935..96d3437f96d 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -204,7 +204,7 @@ else
fi
USER_OPTION=""
-if test -w /
+if test -w / -o "$USER" = "root"
then
if test "$user" != "root" -o $SET_USER = 1
then
@@ -215,6 +215,7 @@ then
if test -n "$open_files"
then
ulimit -n $open_files
+ args="open-files-limit=$open_files $args"
fi
if test -n "$core_file_size"
then
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index bc23c0e5d95..b8d4a0a9a38 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -90,6 +90,7 @@ my %opt = (
Getopt::Long::Configure(qw(no_ignore_case)); # disambuguate -p and -P
GetOptions( \%opt,
"help",
+ "host|h=s",
"user|u=s",
"password|p=s",
"port|P=s",
diff --git a/sql-bench/Results/ATIS-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/ATIS-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..e0192d49a3d
--- /dev/null
+++ b/sql-bench/Results/ATIS-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,20 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 12:35:44
+
+ATIS table test
+
+Creating tables
+Time for create_table (28): 0 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Inserting data
+Time to insert (9768): 3 wallclock secs ( 0.52 usr 0.31 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Retrieving data
+Time for select_simple_join (500): 1 wallclock secs ( 0.60 usr 0.29 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_join (100): 2 wallclock secs ( 0.44 usr 0.27 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_key_prefix_join (100): 10 wallclock secs ( 3.58 usr 2.30 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_distinct (800): 10 wallclock secs ( 1.60 usr 0.81 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_group (2800): 11 wallclock secs ( 1.44 usr 0.52 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Removing tables
+Time to drop_table (28): 0 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Total time: 37 wallclock secs ( 8.20 usr 4.50 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
diff --git a/sql-bench/Results/RUN-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/RUN-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..ba144b8d226
--- /dev/null
+++ b/sql-bench/Results/RUN-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,109 @@
+Benchmark DBD suite: 2.14
+Date of test: 2002-10-23 12:35:44
+Running tests on: Linux 2.4.4-SMP alpha
+Arguments:
+Comments: Alpha DS20 2x500 MHz, 2G memory, key_buffer=16M, query_cache=16M; cxx 6.3 + ccc 6.2.9
+Limits from:
+Server version: MySQL 4.0.5 beta
+Optimization: None
+Hardware:
+
+ATIS: Total time: 37 wallclock secs ( 8.20 usr 4.50 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+alter-table: Total time: 277 wallclock secs ( 0.33 usr 0.14 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+big-tables: Total time: 39 wallclock secs ( 8.71 usr 8.56 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+connect: Total time: 209 wallclock secs (62.48 usr 49.95 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+create: Total time: 288 wallclock secs (10.88 usr 3.48 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+insert: Total time: 2381 wallclock secs (693.26 usr 241.11 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+select: Total time: 1298 wallclock secs (66.92 usr 20.96 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+transactions: Test skipped because the database doesn't support transactions
+wisconsin: Total time: 17 wallclock secs ( 3.66 usr 2.13 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+All 9 test executed successfully
+
+Totals per operation:
+Operation seconds usr sys cpu tests
+alter_table_add 154.00 0.18 0.06 0.00 992
+alter_table_drop 116.00 0.07 0.03 0.00 496
+connect 14.00 8.17 2.02 0.00 10000
+connect+select_1_row 17.00 8.80 2.79 0.00 10000
+connect+select_simple 16.00 8.86 2.57 0.00 10000
+count 50.00 0.04 0.00 0.00 100
+count_distinct 32.00 0.44 0.07 0.00 1000
+count_distinct_2 32.00 0.44 0.08 0.00 1000
+count_distinct_big 54.00 7.37 4.25 0.00 120
+count_distinct_group 50.00 1.14 0.52 0.00 1000
+count_distinct_group_on_key 38.00 0.48 0.12 0.00 1000
+count_distinct_group_on_key_parts 50.00 1.15 0.47 0.00 1000
+count_distinct_key_prefix 28.00 0.44 0.09 0.00 1000
+count_group_on_key_parts 37.00 1.02 0.48 0.00 1000
+count_on_key 453.00 16.74 3.59 0.00 50100
+create+drop 15.00 2.92 0.95 0.00 10000
+create_MANY_tables 238.00 1.84 0.51 0.00 10000
+create_index 4.00 0.00 0.00 0.00 8
+create_key+drop 19.00 4.55 0.94 0.00 10000
+create_table 0.00 0.00 0.00 0.00 31
+delete_all_many_keys 47.00 0.02 0.01 0.00 1
+delete_big 0.00 0.00 0.00 0.00 1
+delete_big_many_keys 47.00 0.02 0.01 0.00 128
+delete_key 4.00 0.88 0.55 0.00 10000
+delete_range 9.00 0.00 0.00 0.00 12
+drop_index 3.00 0.00 0.00 0.00 8
+drop_table 0.00 0.00 0.00 0.00 28
+drop_table_when_MANY_tables 10.00 0.67 0.44 0.00 10000
+insert 134.00 28.43 15.57 0.00 350768
+insert_duplicates 30.00 4.71 5.50 0.00 100000
+insert_key 98.00 13.49 3.80 0.00 100000
+insert_many_fields 14.00 0.32 0.11 0.00 2000
+insert_select_1_key 6.00 0.00 0.00 0.00 1
+insert_select_2_keys 8.00 0.00 0.00 0.00 1
+min_max 23.00 0.02 0.00 0.00 60
+min_max_on_key 188.00 27.44 5.93 0.00 85000
+multiple_value_insert 7.00 1.88 0.05 0.00 100000
+order_by_big 40.00 17.31 12.40 0.00 10
+order_by_big_key 31.00 18.84 12.61 0.00 10
+order_by_big_key2 30.00 17.35 12.38 0.00 10
+order_by_big_key_desc 32.00 19.23 12.70 0.00 10
+order_by_big_key_diff 36.00 17.33 12.44 0.00 10
+order_by_big_key_prefix 30.00 17.36 12.49 0.00 10
+order_by_key2_diff 5.00 1.67 1.04 0.00 500
+order_by_key_prefix 2.00 0.92 0.56 0.00 500
+order_by_range 5.00 0.97 0.55 0.00 500
+outer_join 67.00 0.00 0.00 0.00 10
+outer_join_found 63.00 0.01 0.00 0.00 10
+outer_join_not_found 40.00 0.01 0.00 0.00 500
+outer_join_on_key 40.00 0.01 0.00 0.00 10
+select_1_row 27.00 5.70 6.78 0.00 100000
+select_1_row_cache 22.00 3.16 5.87 0.00 100000
+select_2_rows 30.00 5.96 7.15 0.00 100000
+select_big 31.00 18.08 12.50 0.00 80
+select_big_str 20.00 8.04 6.08 0.00 10000
+select_cache 89.00 3.03 0.74 0.00 10000
+select_cache2 91.00 3.53 0.76 0.00 10000
+select_column+column 30.00 5.07 5.64 0.00 100000
+select_diff_key 163.00 0.27 0.04 0.00 500
+select_distinct 10.00 1.60 0.81 0.00 800
+select_group 106.00 1.49 0.53 0.00 2911
+select_group_when_MANY_tables 6.00 0.90 0.65 0.00 10000
+select_join 2.00 0.44 0.27 0.00 100
+select_key 142.00 77.87 17.06 0.00 200000
+select_key2 142.00 74.50 19.30 0.00 200000
+select_key2_return_key 133.00 73.16 13.81 0.00 200000
+select_key2_return_prim 132.00 70.56 13.25 0.00 200000
+select_key_prefix 141.00 73.88 18.25 0.00 200000
+select_key_prefix_join 10.00 3.58 2.30 0.00 100
+select_key_return_key 146.00 82.66 16.24 0.00 200000
+select_many_fields 25.00 8.38 8.45 0.00 2000
+select_range 242.00 8.57 4.60 0.00 410
+select_range_key2 19.00 6.12 1.72 0.00 25010
+select_range_prefix 18.00 6.28 1.70 0.00 25010
+select_simple 18.00 5.08 5.46 0.00 100000
+select_simple_cache 15.00 3.64 5.58 0.00 100000
+select_simple_join 1.00 0.60 0.29 0.00 500
+update_big 22.00 0.00 0.00 0.00 10
+update_of_key 25.00 4.24 1.90 0.00 50000
+update_of_key_big 18.00 0.04 0.03 0.00 501
+update_of_primary_key_many_keys 20.00 0.03 0.01 0.00 256
+update_with_key 116.00 21.90 14.15 0.00 300000
+update_with_key_prefix 36.00 11.11 4.60 0.00 100000
+wisc_benchmark 4.00 1.66 0.73 0.00 114
+TOTALS 4518.00 844.67 325.93 0.00 3227247
diff --git a/sql-bench/Results/alter-table-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/alter-table-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..1d58effc1a5
--- /dev/null
+++ b/sql-bench/Results/alter-table-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,16 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 12:36:21
+
+Testing of ALTER TABLE
+Testing with 1000 columns and 1000 rows in 20 steps
+Insert data into the table
+Time for insert (1000) 0 wallclock secs ( 0.06 usr 0.05 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for alter_table_add (992): 154 wallclock secs ( 0.18 usr 0.06 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for create_index (8): 4 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for drop_index (8): 3 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for alter_table_drop (496): 116 wallclock secs ( 0.07 usr 0.03 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Total time: 277 wallclock secs ( 0.33 usr 0.14 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
diff --git a/sql-bench/Results/big-tables-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/big-tables-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..97f66029696
--- /dev/null
+++ b/sql-bench/Results/big-tables-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,19 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 12:40:58
+
+Testing of some unusual tables
+All tests are done 1000 times with 1000 fields
+
+Testing table with 1000 fields
+Testing select * from table with 1 record
+Time to select_many_fields(1000): 11 wallclock secs ( 4.59 usr 4.21 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing select all_fields from table with 1 record
+Time to select_many_fields(1000): 14 wallclock secs ( 3.79 usr 4.24 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing insert VALUES()
+Time to insert_many_fields(1000): 5 wallclock secs ( 0.29 usr 0.06 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing insert (all_fields) VALUES()
+Time to insert_many_fields(1000): 9 wallclock secs ( 0.03 usr 0.05 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Total time: 39 wallclock secs ( 8.71 usr 8.56 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
diff --git a/sql-bench/Results/connect-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/connect-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..a787d311a54
--- /dev/null
+++ b/sql-bench/Results/connect-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,35 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 12:41:37
+
+Testing the speed of connecting to the server and sending of data
+Connect tests are done 10000 times and other tests 100000 times
+
+Testing connection/disconnect
+Time to connect (10000): 14 wallclock secs ( 8.17 usr 2.02 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Test connect/simple select/disconnect
+Time for connect+select_simple (10000): 16 wallclock secs ( 8.86 usr 2.57 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Test simple select
+Time for select_simple (100000): 18 wallclock secs ( 5.08 usr 5.46 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Test simple select
+Time for select_simple_cache (100000): 15 wallclock secs ( 3.64 usr 5.58 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing connect/select 1 row from table/disconnect
+Time to connect+select_1_row (10000): 17 wallclock secs ( 8.80 usr 2.79 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing select 1 row from table
+Time to select_1_row (100000): 27 wallclock secs ( 5.70 usr 6.78 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time to select_1_row_cache (100000): 22 wallclock secs ( 3.16 usr 5.87 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing select 2 rows from table
+Time to select_2_rows (100000): 30 wallclock secs ( 5.96 usr 7.15 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Test select with aritmetic (+)
+Time for select_column+column (100000): 30 wallclock secs ( 5.07 usr 5.64 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing retrieval of big records (65000 bytes)
+Time to select_big_str (10000): 20 wallclock secs ( 8.04 usr 6.08 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Total time: 209 wallclock secs (62.48 usr 49.95 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
diff --git a/sql-bench/Results/create-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/create-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..c6b2eaf9f23
--- /dev/null
+++ b/sql-bench/Results/create-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,18 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 12:45:06
+
+Testing the speed of creating and droping tables
+Testing with 10000 tables and 10000 loop count
+
+Testing create of tables
+Time for create_MANY_tables (10000): 238 wallclock secs ( 1.84 usr 0.51 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Accessing tables
+Time to select_group_when_MANY_tables (10000): 6 wallclock secs ( 0.90 usr 0.65 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing drop
+Time for drop_table_when_MANY_tables (10000): 10 wallclock secs ( 0.67 usr 0.44 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing create+drop
+Time for create+drop (10000): 15 wallclock secs ( 2.92 usr 0.95 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for create_key+drop (10000): 19 wallclock secs ( 4.55 usr 0.94 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Total time: 288 wallclock secs (10.88 usr 3.48 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
diff --git a/sql-bench/Results/insert-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/insert-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..0cdf5cbede8
--- /dev/null
+++ b/sql-bench/Results/insert-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,106 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 12:49:54
+
+Testing the speed of inserting data into 1 table and do some selects on it.
+The tests are done with a table that has 100000 rows.
+
+Generating random keys
+Creating tables
+Inserting 100000 rows in order
+Inserting 100000 rows in reverse order
+Inserting 100000 rows in random order
+Time for insert (300000): 114 wallclock secs (25.11 usr 13.48 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing insert of duplicates
+Time for insert_duplicates (100000): 30 wallclock secs ( 4.71 usr 5.50 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Retrieving data from the table
+Time for select_big (10:3000000): 31 wallclock secs (17.94 usr 12.42 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_big_key (10:3000000): 31 wallclock secs (18.84 usr 12.61 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_big_key_desc (10:3000000): 32 wallclock secs (19.23 usr 12.70 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_big_key_prefix (10:3000000): 30 wallclock secs (17.36 usr 12.49 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_big_key2 (10:3000000): 30 wallclock secs (17.35 usr 12.38 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_big_key_diff (10:3000000): 36 wallclock secs (17.33 usr 12.44 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_big (10:3000000): 40 wallclock secs (17.31 usr 12.40 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_range (500:125750): 5 wallclock secs ( 0.97 usr 0.55 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_key_prefix (500:125750): 2 wallclock secs ( 0.92 usr 0.56 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for order_by_key2_diff (500:250500): 5 wallclock secs ( 1.67 usr 1.04 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_diff_key (500:1000): 163 wallclock secs ( 0.27 usr 0.04 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_range_prefix (5010:42084): 10 wallclock secs ( 2.63 usr 0.75 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_range_key2 (5010:42084): 10 wallclock secs ( 2.64 usr 0.76 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_key_prefix (200000): 141 wallclock secs (73.88 usr 18.25 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_key (200000): 142 wallclock secs (77.87 usr 17.06 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_key_return_key (200000): 146 wallclock secs (82.66 usr 16.24 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_key2 (200000): 142 wallclock secs (74.50 usr 19.30 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_key2_return_key (200000): 133 wallclock secs (73.16 usr 13.81 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_key2_return_prim (200000): 132 wallclock secs (70.56 usr 13.25 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Test of compares with simple ranges
+Time for select_range_prefix (20000:43500): 8 wallclock secs ( 3.65 usr 0.95 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_range_key2 (20000:43500): 9 wallclock secs ( 3.48 usr 0.96 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_group (111): 95 wallclock secs ( 0.05 usr 0.01 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for min_max_on_key (15000): 10 wallclock secs ( 5.77 usr 1.18 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for min_max (60): 23 wallclock secs ( 0.02 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_on_key (100): 41 wallclock secs ( 0.04 usr 0.01 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count (100): 50 wallclock secs ( 0.04 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_distinct_big (20): 39 wallclock secs ( 0.01 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing update of keys with functions
+Time for update_of_key (50000): 25 wallclock secs ( 4.24 usr 1.90 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for update_of_key_big (501): 18 wallclock secs ( 0.04 usr 0.03 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing update with key
+Time for update_with_key (300000): 116 wallclock secs (21.90 usr 14.15 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for update_with_key_prefix (100000): 36 wallclock secs (11.11 usr 4.60 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing update of all rows
+Time for update_big (10): 22 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing left outer join
+Time for outer_join_on_key (10:10): 40 wallclock secs ( 0.01 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for outer_join (10:10): 67 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for outer_join_found (10:10): 63 wallclock secs ( 0.01 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for outer_join_not_found (500:10): 40 wallclock secs ( 0.01 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing SELECT ... WHERE id in (10 values)
+Time for select_in (500:5000) 0 wallclock secs ( 0.22 usr 0.06 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for select_join_in (500:5000) 1 wallclock secs ( 0.23 usr 0.06 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing SELECT ... WHERE id in (100 values)
+Time for select_in (500:50000) 4 wallclock secs ( 0.56 usr 0.26 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for select_join_in (500:50000) 2 wallclock secs ( 0.57 usr 0.24 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing SELECT ... WHERE id in (1000 values)
+Time for select_in (500:500000) 32 wallclock secs ( 3.96 usr 2.13 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for select_join_in (500:500000) 17 wallclock secs ( 4.02 usr 2.07 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+
+Testing INSERT INTO ... SELECT
+Time for insert_select_1_key (1): 6 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for insert_select_2_keys (1): 8 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for drop table(2): 0 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing delete
+Time for delete_key (10000): 4 wallclock secs ( 0.88 usr 0.55 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for delete_range (12): 9 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Insert into table with 16 keys and with a primary key with 16 parts
+Time for insert_key (100000): 98 wallclock secs (13.49 usr 3.80 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing update of keys
+Time for update_of_primary_key_many_keys (256): 20 wallclock secs ( 0.03 usr 0.01 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Deleting rows from the table
+Time for delete_big_many_keys (128): 47 wallclock secs ( 0.02 usr 0.01 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Deleting everything from table
+Time for delete_all_many_keys (1): 47 wallclock secs ( 0.02 usr 0.01 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Inserting 100000 rows with multiple values
+Time for multiple_value_insert (100000): 7 wallclock secs ( 1.88 usr 0.05 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for drop table(1): 0 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Total time: 2381 wallclock secs (693.26 usr 241.11 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
diff --git a/sql-bench/Results/select-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/select-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..939f130f92e
--- /dev/null
+++ b/sql-bench/Results/select-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,30 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 13:29:36
+
+Testing the speed of selecting on keys that consist of many parts
+The test-table has 10000 rows and the test is done with 500 ranges.
+
+Creating table
+Inserting 10000 rows
+Time to insert (10000): 4 wallclock secs ( 0.81 usr 0.38 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Test if the database has a query cache
+Time for select_cache (10000): 89 wallclock secs ( 3.03 usr 0.74 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for select_cache2 (10000): 91 wallclock secs ( 3.53 usr 0.76 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Testing big selects on the table
+Time for select_big (70:17207): 0 wallclock secs ( 0.14 usr 0.08 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for select_range (410:1057904): 242 wallclock secs ( 8.57 usr 4.60 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for min_max_on_key (70000): 178 wallclock secs (21.67 usr 4.75 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_on_key (50000): 412 wallclock secs (16.70 usr 3.58 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Time for count_group_on_key_parts (1000:100000): 37 wallclock secs ( 1.02 usr 0.48 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Testing count(distinct) on the table
+Time for count_distinct_key_prefix (1000:1000): 28 wallclock secs ( 0.44 usr 0.09 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_distinct (1000:1000): 32 wallclock secs ( 0.44 usr 0.07 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_distinct_2 (1000:1000): 32 wallclock secs ( 0.44 usr 0.08 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_distinct_group_on_key (1000:6000): 38 wallclock secs ( 0.48 usr 0.12 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_distinct_group_on_key_parts (1000:100000): 50 wallclock secs ( 1.15 usr 0.47 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_distinct_group (1000:100000): 50 wallclock secs ( 1.14 usr 0.52 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time for count_distinct_big (100:1000000): 15 wallclock secs ( 7.36 usr 4.25 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Total time: 1298 wallclock secs (66.92 usr 20.96 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
diff --git a/sql-bench/Results/transactions-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/transactions-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..47f81534c1e
--- /dev/null
+++ b/sql-bench/Results/transactions-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,3 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 13:51:14
+
+Test skipped because the database doesn't support transactions
diff --git a/sql-bench/Results/wisconsin-mysql-Linux_2.4.4_SMP_alpha b/sql-bench/Results/wisconsin-mysql-Linux_2.4.4_SMP_alpha
new file mode 100644
index 00000000000..445246a27c7
--- /dev/null
+++ b/sql-bench/Results/wisconsin-mysql-Linux_2.4.4_SMP_alpha
@@ -0,0 +1,14 @@
+Testing server 'MySQL 4.0.5 beta' at 2002-10-23 13:51:14
+
+Wisconsin benchmark test
+
+Time for create_table (3): 0 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Inserting data
+Time to insert (31000): 13 wallclock secs ( 1.99 usr 1.40 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+Time to delete_big (1): 0 wallclock secs ( 0.00 usr 0.00 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Running the actual benchmark
+Time for wisc_benchmark (114): 4 wallclock secs ( 1.66 usr 0.73 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
+
+Total time: 17 wallclock secs ( 3.66 usr 2.13 sys + 0.00 cusr 0.00 csys = 0.00 CPU)
diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh
index 4e7e1c29504..9b999ee7f95 100644
--- a/sql-bench/bench-init.pl.sh
+++ b/sql-bench/bench-init.pl.sh
@@ -39,7 +39,7 @@ require "$pwd/server-cfg" || die "Can't read Configuration file: $!\n";
$|=1; # Output data immediately
$opt_skip_test=$opt_skip_create=$opt_skip_delete=$opt_verbose=$opt_fast_insert=$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=$opt_log=$opt_use_old_results=$opt_help=$opt_odbc=$opt_small_test=$opt_small_tables=$opt_samll_key_tables=$opt_stage=$opt_old_headers=$opt_die_on_errors=$opt_tcpip=$opt_random=0;
-$opt_cmp=$opt_user=$opt_password="";
+$opt_cmp=$opt_user=$opt_password=$opt_connect_options="";
$opt_server="mysql"; $opt_dir="output";
$opt_host="localhost";$opt_database="test";
$opt_machine=""; $opt_suffix="";
@@ -55,11 +55,11 @@ $log_prog_args=join(" ", skip_arguments(\@ARGV,"comments","cmp","server",
"use-old-results","skip-test",
"optimization","hw",
"machine", "dir", "suffix", "log"));
-GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","threads=i","random","old-headers","die-on-errors","create-options=s","hires","tcpip","silent","optimization=s","hw=s","socket=s") || usage();
+GetOptions("skip-test=s","comments=s","cmp=s","server=s","user=s","host=s","database=s","password=s","loop-count=i","row-count=i","skip-create","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","field-count=i","regions=i","groups=i","time-limit=i","log","use-old-results","machine=s","dir=s","suffix=s","help","odbc","small-test","small-tables","small-key-tables","stage=i","threads=i","random","old-headers","die-on-errors","create-options=s","hires","tcpip","silent","optimization=s","hw=s","socket=s","connect-options=s") || usage();
usage() if ($opt_help);
$server=get_server($opt_server,$opt_host,$opt_database,$opt_odbc,
- machine_part(), $opt_socket);
+ machine_part(), $opt_socket, $opt_connect_options);
$limits=merge_limits($server,$opt_cmp);
$date=date();
@estimated=(0.0,0.0,0.0); # For estimated time support
@@ -593,7 +593,11 @@ All benchmarks takes the following options:
--hw='some comments'
Add coments about hardware used for this test.
-
+
+--connect-options='some connect options'
+ Add options, which uses at DBI connect.
+ For example --connect-options=mysql_read_default_file=/etc/my.cnf.
+
EOF
exit(0);
}
diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh
index ea1697fb4c3..f3f00f501ab 100644
--- a/sql-bench/server-cfg.sh
+++ b/sql-bench/server-cfg.sh
@@ -33,10 +33,10 @@
sub get_server
{
- my ($name,$host,$database,$odbc,$machine,$socket)=@_;
+ my ($name,$host,$database,$odbc,$machine,$socket,$connect_options)=@_;
my ($server);
if ($name =~ /mysql/i)
- { $server=new db_MySQL($host, $database, $machine, $socket); }
+ { $server=new db_MySQL($host, $database, $machine, $socket,$connect_options); }
elsif ($name =~ /pg/i)
{ $server= new db_Pg($host,$database); }
elsif ($name =~ /msql/i)
@@ -106,7 +106,7 @@ package db_MySQL;
sub new
{
- my ($type,$host,$database,$machine,$socket)= @_;
+ my ($type,$host,$database,$machine,$socket,$connect_options)= @_;
my $self= {};
my %limits;
bless $self;
@@ -114,6 +114,7 @@ sub new
$self->{'cmp_name'} = "mysql";
$self->{'data_source'} = "DBI:mysql:database=$database;host=$host";
$self->{'data_source'} .= ";mysql_socket=$socket" if($socket);
+ $self->{'data_source'} .= ";$connect_options" if($connect_options);
$self->{'limits'} = \%limits;
$self->{'blob'} = "blob";
$self->{'text'} = "text";
diff --git a/sql-bench/test-create.sh b/sql-bench/test-create.sh
index 2853984e393..1e7d3841bb5 100644
--- a/sql-bench/test-create.sh
+++ b/sql-bench/test-create.sh
@@ -54,7 +54,7 @@ if ($opt_small_test)
}
-print "Testing the speed of creating and droping tables\n";
+print "Testing the speed of creating and dropping tables\n";
print "Testing with $max_tables tables and $opt_loop_count loop count\n\n";
####
diff --git a/sql/field.cc b/sql/field.cc
index 73ef4439bc9..f2324a0a331 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -41,6 +41,11 @@
#include <floatingpoint.h>
#endif
+// Maximum allowed exponent value for converting string to decimal
+#define MAX_EXPONENT 1024
+
+
+
/*****************************************************************************
Instansiate templates and static variables
*****************************************************************************/
@@ -392,7 +397,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
const char *frac_digits_from, *frac_digits_end;
/* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */
char expo_sign_char=0;
- uint exponent=0; // value of the exponent
+ uint exponent=0; // value of the exponent
/*
Pointers used when digits move from the left of the '.' to the
right of the '.' (explained below)
@@ -488,13 +493,17 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
else
expo_sign_char= '+';
/*
- Read digits of the exponent and compute its value
- 'exponent' overflow (e.g. if 1E10000000000000000) is not a problem
- (the value of the field will be overflow anyway, or 0 anyway,
- it does not change anything if the exponent is 2^32 or more
+ Read digits of the exponent and compute its value. We must care about
+ 'exponent' overflow, because as unsigned arithmetic is "modulo", big
+ exponents will become small (e.g. 1e4294967296 will become 1e0, and the
+ field will finally contain 1 instead of its max possible value).
*/
- for (;from!=end && my_isdigit(system_charset_info, (*from)); from++)
+ for (;from!=end && my_isdigit(system_charset_info, *from); from++)
+ {
exponent=10*exponent+(*from-'0');
+ if (exponent>MAX_EXPONENT)
+ break;
+ }
}
/*
@@ -536,6 +545,13 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
int_digits_added_zeros=2 (to make 1234500).
*/
+ /*
+ Below tmp_uint cannot overflow with small enough MAX_EXPONENT setting,
+ as int_digits_added_zeros<=exponent<4G and
+ (int_digits_end-int_digits_from)<=max_allowed_packet<=2G and
+ (frac_digits_from-int_digits_tail_from)<=max_allowed_packet<=2G
+ */
+
if (!expo_sign_char)
tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
else if (expo_sign_char == '-')
@@ -544,7 +560,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
frac_digits_added_zeros=exponent-tmp_uint;
int_digits_end -= tmp_uint;
frac_digits_head_end=int_digits_end+tmp_uint;
- tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
+ tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
}
else // (expo_sign_char=='+')
{
@@ -571,9 +587,9 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
int_digits_added_zeros=0;
}
}
- tmp_uint=(tmp_dec+(uint)(int_digits_end-int_digits_from)
- +(uint)(frac_digits_from-int_digits_tail_from)+
- int_digits_added_zeros);
+ tmp_uint= (tmp_dec+(int_digits_end-int_digits_from)+
+ (uint)(frac_digits_from-int_digits_tail_from)+
+ int_digits_added_zeros);
}
/*
@@ -584,7 +600,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
If the sign is defined and '-', we need one position for it
*/
- if (field_length < tmp_uint + (int) (sign_char == '-'))
+ if (field_length < tmp_uint + (int) (sign_char == '-'))
{
// too big number, change to max or min number
Field_decimal::overflow(sign_char == '-');
@@ -647,69 +663,67 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
*pos--=' '; //fill with blanks
}
- if (tmp_dec) // This field has decimals
- {
- /*
- Write digits of the frac_% parts ;
- Depending on current_thd->count_cutted_fields, we may also want
- to know if some non-zero tail of these parts will
- be truncated (for example, 0.002->0.00 will generate a warning,
- while 0.000->0.00 will not)
- (and 0E1000000000 will not, while 1E-1000000000 will)
- */
+ /*
+ Write digits of the frac_% parts ;
+ Depending on current_thd->count_cutted_fields, we may also want
+ to know if some non-zero tail of these parts will
+ be truncated (for example, 0.002->0.00 will generate a warning,
+ while 0.000->0.00 will not)
+ (and 0E1000000000 will not, while 1E-1000000000 will)
+ */
- pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
+ pos=to+(uint)(field_length-tmp_dec); // Calculate post to '.'
+ right_wall=to+field_length;
+ if (pos != right_wall)
*pos++='.';
- right_wall=to+field_length;
- if (expo_sign_char == '-')
+ if (expo_sign_char == '-')
+ {
+ while (frac_digits_added_zeros-- > 0)
{
- while (frac_digits_added_zeros-- > 0)
+ if (pos == right_wall)
{
- if (pos == right_wall)
- {
- if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
- break; // Go on below to see if we lose non zero digits
- return 0;
- }
- *pos++='0';
+ if (current_thd->count_cuted_fields && !is_cuted_fields_incr)
+ break; // Go on below to see if we lose non zero digits
+ return 0;
}
- while (int_digits_end != frac_digits_head_end)
+ *pos++='0';
+ }
+ while (int_digits_end != frac_digits_head_end)
+ {
+ tmp_char= *int_digits_end++;
+ if (pos == right_wall)
{
- tmp_char= *int_digits_end++;
- if (pos == right_wall)
- {
- if (tmp_char != '0') // Losing a non zero digit ?
- {
- if (!is_cuted_fields_incr)
- current_thd->cuted_fields++;
- return 0;
- }
- continue;
- }
- *pos++= tmp_char;
+ if (tmp_char != '0') // Losing a non zero digit ?
+ {
+ if (!is_cuted_fields_incr)
+ current_thd->cuted_fields++;
+ return 0;
+ }
+ continue;
}
+ *pos++= tmp_char;
}
+ }
- for (;frac_digits_from!=frac_digits_end;)
+ for (;frac_digits_from!=frac_digits_end;)
+ {
+ tmp_char= *frac_digits_from++;
+ if (pos == right_wall)
{
- tmp_char= *frac_digits_from++;
- if (pos == right_wall)
+ if (tmp_char != '0') // Losing a non zero digit ?
{
- if (tmp_char != '0') // Losing a non zero digit ?
- {
- if (!is_cuted_fields_incr)
- current_thd->cuted_fields++;
- return 0;
- }
- continue;
+ if (!is_cuted_fields_incr)
+ current_thd->cuted_fields++;
+ return 0;
}
- *pos++= tmp_char;
+ continue;
}
-
- while (pos != right_wall)
- *pos++='0'; // Fill with zeros at right of '.'
+ *pos++= tmp_char;
}
+
+ while (pos != right_wall)
+ *pos++='0'; // Fill with zeros at right of '.'
return 0;
}
@@ -3930,12 +3944,12 @@ int Field_string::pack_cmp(const char *b, uint length)
}
-uint Field_string::packed_col_length(const char *ptr, uint length)
+uint Field_string::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_string::max_packed_col_length(uint max_length)
@@ -4162,12 +4176,12 @@ int Field_varstring::pack_cmp(const char *b, uint key_length)
(const uchar *)b,b_length);
}
-uint Field_varstring::packed_col_length(const char *ptr, uint length)
+uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_varstring::max_packed_col_length(uint max_length)
@@ -4698,12 +4712,12 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
return to+length;
}
-uint Field_blob::packed_col_length(const char *ptr, uint length)
+uint Field_blob::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
- return uint2korr(ptr)+2;
+ return uint2korr(data_ptr)+2;
else
- return (uint) ((uchar) *ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
uint Field_blob::max_packed_col_length(uint max_length)
@@ -5294,10 +5308,11 @@ Field *make_field(char *ptr, uint32 field_length,
return new Field_datetime(ptr,null_pos,null_bit,
unireg_check, field_name, table, field_charset);
case FIELD_TYPE_NULL:
- default: // Impossible (Wrong version)
return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset);
+ default: // Impossible (Wrong version)
+ break;
}
- return 0; // Impossible (Wrong version)
+ return 0;
}
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 53af60b0370..fab666a1203 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -223,7 +223,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
if (error)
my_error(ER_FILSORT_ABORT,MYF(ME_ERROR+ME_WAITTANG));
else
- statistic_add(filesort_rows, records, &LOCK_status);
+ statistic_add(filesort_rows, (ulong) records, &LOCK_status);
*examined_rows= param.examined_rows;
#ifdef SKIP_DBUG_IN_FILESORT
DBUG_POP(); /* Ok to DBUG */
@@ -724,7 +724,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
org_max_rows=max_rows=param->max_rows;
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
- (int (*) (void *, byte *,byte*))
+ (queue_compare)
(cmp=get_ptr_compare(sort_length)),(void*) &sort_length))
DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 0d92397b616..7daab228093 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -320,7 +320,7 @@ and you are welcome to modify and redistribute it under the GPL license\n");
my_print_help(my_long_options);
}
-static my_bool
+extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument __attribute__((unused)))
{
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 6d5b469a913..679642ca949 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -1931,7 +1931,7 @@ int ha_berkeley::delete_table(const char *name)
double ha_berkeley::scan_time()
{
- return records/3;
+ return rows2double(records/3);
}
ha_rows ha_berkeley::records_in_range(int keynr,
@@ -2206,7 +2206,7 @@ static BDB_SHARE *get_share(const char *table_name, TABLE *table)
if (!(share=(BDB_SHARE*) hash_search(&bdb_open_tables, (byte*) table_name,
length)))
{
- ha_rows *rec_per_key;
+ ulong *rec_per_key;
char *tmp_name;
DB **key_file;
u_int32_t *key_type;
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index 198664d0c06..f2a81d123f1 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -27,7 +27,8 @@
typedef struct st_berkeley_share {
ulonglong auto_ident;
- ha_rows rows, org_rows, *rec_per_key;
+ ha_rows rows, org_rows;
+ ulong *rec_per_key;
THR_LOCK lock;
pthread_mutex_t mutex;
char *table_name;
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index c06421617dd..4a3b9495f6f 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -245,7 +245,7 @@ int ha_heap::create(const char *name, TABLE *table,
{
uint key, parts, mem_per_row= 0;
uint auto_key= 0, auto_key_type= 0;
- ulong max_rows;
+ ha_rows max_rows;
HP_KEYDEF *keydef;
HA_KEYSEG *seg;
char buff[FN_REFLEN];
@@ -310,8 +310,8 @@ int ha_heap::create(const char *name, TABLE *table,
}
}
mem_per_row+= MY_ALIGN(table->reclength + 1, sizeof(char*));
- max_rows = (ulong) (current_thd->variables.max_heap_table_size /
- mem_per_row);
+ max_rows = (ha_rows) (current_thd->variables.max_heap_table_size /
+ mem_per_row);
HP_CREATE_INFO hp_create_info;
hp_create_info.auto_key= auto_key;
hp_create_info.auto_key_type= auto_key_type;
@@ -319,9 +319,9 @@ int ha_heap::create(const char *name, TABLE *table,
create_info->auto_increment_value - 1 : 0);
error= heap_create(fn_format(buff,name,"","",4+2),
table->keys,keydef, table->reclength,
- ((table->max_rows < max_rows && table->max_rows) ?
- table->max_rows : max_rows),
- table->min_rows, &hp_create_info);
+ (ulong) ((table->max_rows < max_rows && table->max_rows) ?
+ table->max_rows : max_rows),
+ (ulong) table->min_rows, &hp_create_info);
my_free((gptr) keydef, MYF(0));
if (file)
info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 9aa63cc1435..7787b543f34 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -40,17 +40,12 @@ InnoDB */
#include "ha_innodb.h"
-/* We must declare this here because we undef SAFE_MUTEX below */
pthread_mutex_t innobase_mutex;
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB
uses unsigned char */
typedef byte mysql_byte;
-#ifdef SAFE_MUTEX
-#undef pthread_mutex_t
-#endif
-
#define INSIDE_HA_INNOBASE_CC
/* Include necessary InnoDB headers */
@@ -97,6 +92,8 @@ are determined in innobase_init below: */
char* innobase_data_home_dir = NULL;
char* innobase_log_group_home_dir = NULL;
char* innobase_log_arch_dir = NULL;
+/* The following has a midleading name: starting from 4.0.5 this also
+affects Windows */
char* innobase_unix_file_flush_method = NULL;
/* Below we have boolean-valued start-up parameters, and their default
@@ -253,6 +250,10 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_TOO_BIG_RECORD) {
return(HA_ERR_TO_BIG_ROW);
+
+ } else if (error == (int) DB_CORRUPTION) {
+
+ return(HA_ERR_CRASHED);
} else {
return(-1); // Unknown error
}
@@ -346,7 +347,8 @@ check_trx_exists(
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
-
+ trx->mysql_query_str = &((*thd).query);
+
thd->transaction.all.innobase_tid = trx;
/* The execution of a single SQL statement is denoted by
@@ -713,9 +715,10 @@ innobase_init(void)
DBUG_RETURN(TRUE);
}
- srv_unix_file_flush_method_str = (innobase_unix_file_flush_method ?
+
+ srv_file_flush_method_str = (innobase_unix_file_flush_method ?
innobase_unix_file_flush_method :
- (char*)"fdatasync");
+ NULL);
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
srv_n_log_files = (ulint) innobase_log_files_in_group;
@@ -725,8 +728,6 @@ innobase_init(void)
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
srv_flush_log_at_trx_commit = (ulint) innobase_flush_log_at_trx_commit;
- srv_use_native_aio = 0;
-
srv_pool_size = (ulint) innobase_buffer_pool_size;
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
@@ -750,6 +751,14 @@ innobase_init(void)
default_charset_info->sort_order, 256);
}
+ /* Since we in this module access directly the fields of a trx
+ struct, and due to different headers and flags it might happen that
+ mutex_t has a different size in this module and in InnoDB
+ modules, we check at run time that the size is the same in
+ these compilation modules. */
+
+ srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
+
err = innobase_start_or_create_for_mysql();
if (err != DB_SUCCESS) {
@@ -1147,15 +1156,15 @@ ha_innobase::open(
ib_table = dict_table_get_and_increment_handle_count(
norm_name, NULL);
if (NULL == ib_table) {
-
- sql_print_error("InnoDB error:\n\
-Cannot find table %s from the internal data dictionary\n\
-of InnoDB though the .frm file for the table exists. Maybe you\n\
-have deleted and recreated InnoDB data files but have forgotten\n\
-to delete the corresponding .frm files of InnoDB tables, or you\n\
-have moved .frm files to another database?\n\
-Look from section 15.1 of http://www.innodb.com/ibman.html\n\
-how you can resolve the problem.\n",
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB error:\n"
+"Cannot find table %s from the internal data dictionary\n"
+"of InnoDB though the .frm file for the table exists. Maybe you\n"
+"have deleted and recreated InnoDB data files but have forgotten\n"
+"to delete the corresponding .frm files of InnoDB tables, or you\n"
+"have moved .frm files to another database?\n"
+"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
+"how you can resolve the problem.\n",
norm_name);
free_share(share);
@@ -1168,7 +1177,10 @@ how you can resolve the problem.\n",
((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = table->reclength;
- primary_key = MAX_KEY;
+ /* Looks like MySQL-3.23 sometimes has primary key number != 0 */
+
+ primary_key = table->primary_key;
+ key_used_on_scan = primary_key;
/* Allocate a buffer for a 'row reference'. A row reference is
a string of bytes of length ref_length which uniquely specifies
@@ -1177,13 +1189,14 @@ how you can resolve the problem.\n",
of length ref_length! */
if (!row_table_got_default_clust_index(ib_table)) {
+ if (primary_key >= MAX_KEY) {
+ fprintf(stderr,
+ "InnoDB: Error: table %s has a primary key in InnoDB\n"
+ "InnoDB: data dictionary, but not in MySQL!\n", name);
+ }
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = FALSE;
-
- primary_key = 0;
- key_used_on_scan = 0;
-
/*
MySQL allocates the buffer for ref. key_info->key_length
includes space for all key columns + one byte for each column
@@ -1192,8 +1205,14 @@ how you can resolve the problem.\n",
based on ref_length.
*/
- ref_length = table->key_info->key_length;
+ ref_length = table->key_info[primary_key].key_length;
} else {
+ if (primary_key != MAX_KEY) {
+ fprintf(stderr,
+ "InnoDB: Error: table %s has no primary key in InnoDB\n"
+ "InnoDB: data dictionary, but has one in MySQL!\n", name);
+ }
+
((row_prebuilt_t*)innobase_prebuilt)
->clust_index_was_generated = TRUE;
@@ -1501,7 +1520,8 @@ ha_innobase::store_key_val_for_row(
are equal
*/
bzero(buff, (ref_length- (uint) (buff - buff_start)));
- DBUG_RETURN(ref_length);
+
+ DBUG_RETURN((uint)(buff - buff_start));
}
/******************************************************************
@@ -1679,6 +1699,7 @@ ha_innobase::write_row(
longlong dummy;
ibool incremented_auto_inc_for_stat = FALSE;
ibool incremented_auto_inc_counter = FALSE;
+ ibool skip_auto_inc_decr;
DBUG_ENTER("ha_innobase::write_row");
@@ -1843,13 +1864,31 @@ ha_innobase::write_row(
if (error != DB_SUCCESS) {
/* If the insert did not succeed we restore the value of
the auto-inc counter we used; note that this behavior was
- introduced only in version 4.0.4 */
+ introduced only in version 4.0.4.
+ NOTE that a REPLACE command handles a duplicate key error
+ itself, and we must not decrement the autoinc counter
+ if we are performing a REPLACE statement.
+ NOTE 2: if there was an error, for example a deadlock,
+ which caused InnoDB to roll back the whole transaction
+ already in the call of row_insert_for_mysql(), we may no
+ longer have the AUTO-INC lock, and cannot decrement
+ the counter here. */
+
+ skip_auto_inc_decr = FALSE;
+
+ if (error == DB_DUPLICATE_KEY) {
+ ut_a(user_thd->query);
+ dict_accept(user_thd->query, "REPLACE",
+ &skip_auto_inc_decr);
+ }
- if (incremented_auto_inc_counter) {
+ if (!skip_auto_inc_decr && incremented_auto_inc_counter
+ && prebuilt->trx->auto_inc_lock) {
dict_table_autoinc_decrement(prebuilt->table);
}
- if (incremented_auto_inc_for_stat) {
+ if (!skip_auto_inc_decr && incremented_auto_inc_for_stat
+ && prebuilt->trx->auto_inc_lock) {
auto_inc_counter_for_this_stat--;
}
}
@@ -2181,8 +2220,16 @@ convert_search_mode_to_innobase(
case HA_READ_AFTER_KEY: return(PAGE_CUR_G);
case HA_READ_BEFORE_KEY: return(PAGE_CUR_L);
case HA_READ_PREFIX: return(PAGE_CUR_GE);
- case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE);
- /* HA_READ_PREFIX_LAST does not yet work in InnoDB! */
+ case HA_READ_PREFIX_LAST:
+ /* ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Warning: Using HA_READ_PREFIX_LAST\n"); */
+ return(PAGE_CUR_LE);
+
+ /* InnoDB does not yet support ..PREFIX_LAST!
+ We have to add a new search flag
+ PAGE_CUR_LE_OR_PREFIX to InnoDB. */
+
/* the above PREFIX flags mean that the last
field in the key value may just be a prefix
of the complete fixed length field */
@@ -2751,7 +2798,11 @@ ha_innobase::position(
that len is always fixed for this table. The following assertion
checks this. */
- ut_a(len == ref_length);
+ if (len != ref_length) {
+ fprintf(stderr,
+ "InnoDB: Error: stored ref len is %lu, but table ref len is %lu\n",
+ (ulint)len, (ulint)ref_length);
+ }
}
@@ -2935,16 +2986,21 @@ ha_innobase::create(
trx->check_unique_secondary = FALSE;
}
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
fn_format(name2, name, "", "",2); // Remove the .frm extension
normalize_table_name(norm_name, name2);
- /* Latch the InnoDB data dictionary exclusive so that no deadlocks
+ /* Latch the InnoDB data dictionary exclusively so that no deadlocks
or lock waits can happen in it during a table create operation.
- (Drop table etc. do this latching in row0mysql.c.) */
+ Drop table etc. do this latching in row0mysql.c. */
- row_mysql_lock_data_dictionary();
+ row_mysql_lock_data_dictionary(trx);
/* Create the table definition in InnoDB */
@@ -2953,7 +3009,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -2983,7 +3039,7 @@ ha_innobase::create(
if (error) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -2998,7 +3054,7 @@ ha_innobase::create(
(uint) primary_key_no))) {
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -3014,7 +3070,7 @@ ha_innobase::create(
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
@@ -3023,24 +3079,27 @@ ha_innobase::create(
}
}
- error = row_table_add_foreign_constraints(trx,
- create_info->create_statement, norm_name);
+ if (current_thd->query != NULL) {
+
+ error = row_table_add_foreign_constraints(trx,
+ current_thd->query, norm_name);
- error = convert_error_code_to_mysql(error, NULL);
+ error = convert_error_code_to_mysql(error, NULL);
- if (error) {
- innobase_commit_low(trx);
+ if (error) {
+ innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
- trx_free_for_mysql(trx);
+ trx_free_for_mysql(trx);
- DBUG_RETURN(error);
+ DBUG_RETURN(error);
+ }
}
innobase_commit_low(trx);
- row_mysql_unlock_data_dictionary();
+ row_mysql_unlock_data_dictionary(trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -3082,6 +3141,12 @@ ha_innobase::delete_table(
DBUG_ENTER("ha_innobase::delete_table");
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
+
trx = trx_allocate_for_mysql();
name_len = strlen(name);
@@ -3095,7 +3160,7 @@ ha_innobase::delete_table(
/* Drop the table in InnoDB */
- error = row_drop_table_for_mysql(norm_name, trx, FALSE);
+ error = row_drop_table_for_mysql(norm_name, trx);
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
@@ -3192,6 +3257,12 @@ ha_innobase::rename_table(
DBUG_ENTER("ha_innobase::rename_table");
+ if (lower_case_table_names) {
+ srv_lower_case_table_names = TRUE;
+ } else {
+ srv_lower_case_table_names = FALSE;
+ }
+
trx = trx_allocate_for_mysql();
name_len1 = strlen(from);
@@ -3318,7 +3389,7 @@ ha_innobase::estimate_number_of_rows(void)
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
dict_index_t* index;
ulonglong estimate;
- ulonglong data_file_length;
+ ulonglong local_data_file_length;
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
@@ -3328,7 +3399,7 @@ ha_innobase::estimate_number_of_rows(void)
index = dict_table_get_first_index_noninline(prebuilt->table);
- data_file_length = ((ulonglong) index->stat_n_leaf_pages)
+ local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
* UNIV_PAGE_SIZE;
/* Calculate a minimum length for a clustered index record and from
@@ -3337,7 +3408,7 @@ ha_innobase::estimate_number_of_rows(void)
by a threshold factor, we must add a safety factor 2 in front
of the formula below. */
- estimate = 2 * data_file_length / dict_index_calc_min_rec_len(index);
+ estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index);
DBUG_RETURN((ha_rows) estimate);
}
@@ -3374,12 +3445,21 @@ ha_innobase::info(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
dict_table_t* ib_table;
dict_index_t* index;
- ulong rec_per_key;
+ ha_rows rec_per_key;
ulong j;
ulong i;
DBUG_ENTER("info");
+ /* If we are forcing recovery at a high level, we will suppress
+ statistics calculation on tables, because that may crash the
+ server if an index is badly corrupted. */
+
+ if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
+
+ return;
+ }
+
/* Warning: since it is not sure that MySQL calls external_lock
before calling this function, the trx field in prebuilt can be
obsolete! */
@@ -3426,7 +3506,7 @@ ha_innobase::info(
rec_per_key = records;
} else {
- rec_per_key = (ulong)(records /
+ rec_per_key = (ha_rows)(records /
index->stat_n_diff_key_vals[j + 1]);
}
@@ -3441,8 +3521,9 @@ ha_innobase::info(
rec_per_key = 1;
}
- table->key_info[i].rec_per_key[j]
- = rec_per_key;
+ table->key_info[i].rec_per_key[j]=
+ rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
+ rec_per_key;
}
index = dict_table_get_next_index_noninline(index);
@@ -3641,7 +3722,6 @@ ha_innobase::reset(void)
return(0);
}
-
/**********************************************************************
When we create a temporary table inside MySQL LOCK TABLES, MySQL will
not call external_lock for the temporary table when it uses it. Instead,
@@ -3663,12 +3743,20 @@ ha_innobase::start_stmt(
innobase_release_stat_resources(trx);
trx_mark_sql_stat_end(trx);
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ && trx->read_view) {
+ /* At low transaction isolation levels we let
+ each consistent read set its own snapshot */
+
+ read_view_close_for_mysql(trx);
+ }
+
auto_inc_counter_for_this_stat = 0;
prebuilt->sql_stat_start = TRUE;
prebuilt->hint_no_need_to_fetch_extra_cols = TRUE;
prebuilt->read_just_key = 0;
- if (prebuilt->select_lock_type == LOCK_NONE) {
+ if (!prebuilt->mysql_has_locked) {
/* This handle is for a temporary table created inside
this same LOCK TABLES; since MySQL does NOT call external_lock
in this case, we must use x-row locks inside InnoDB to be
@@ -3683,6 +3771,24 @@ ha_innobase::start_stmt(
}
/**********************************************************************
+Maps a MySQL trx isolation level code to the InnoDB isolation level code */
+inline
+ulint
+innobase_map_isolation_level(
+/*=========================*/
+ /* out: InnoDB isolation level */
+ enum_tx_isolation iso) /* in: MySQL isolation level code */
+{
+ switch(iso) {
+ case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
+ case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
+ case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
+ case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
+ default: ut_a(0); return(0);
+ }
+}
+
+/**********************************************************************
As MySQL will execute an external lock for every new table it uses when it
starts to process an SQL statement (an exception is when MySQL calls
start_stmt for the handle) we can use this function to store the pointer to
@@ -3703,6 +3809,7 @@ ha_innobase::external_lock(
trx_t* trx;
DBUG_ENTER("ha_innobase::external_lock");
+ DBUG_PRINT("enter",("lock_type: %d", lock_type));
update_thd(thd);
@@ -3727,8 +3834,15 @@ ha_innobase::external_lock(
thd->transaction.all.innodb_active_trans = 1;
trx->n_mysql_tables_in_use++;
+ prebuilt->mysql_has_locked = TRUE;
- if (thd->variables.tx_isolation == ISO_SERIALIZABLE
+ if (thd->variables.tx_isolation != ISO_REPEATABLE_READ) {
+ trx->isolation_level = innobase_map_isolation_level(
+ (enum_tx_isolation)
+ thd->variables.tx_isolation);
+ }
+
+ if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE) {
/* To get serializable execution we let InnoDB
@@ -3744,6 +3858,7 @@ ha_innobase::external_lock(
}
} else {
trx->n_mysql_tables_in_use--;
+ prebuilt->mysql_has_locked = FALSE;
auto_inc_counter_for_this_stat = 0;
if (trx->n_mysql_tables_in_use == 0) {
@@ -3755,6 +3870,15 @@ ha_innobase::external_lock(
innobase_release_stat_resources(trx);
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ && trx->read_view) {
+
+ /* At low transaction isolation levels we let
+ each consistent read set its own snapshot */
+
+ read_view_close_for_mysql(trx);
+ }
+
if (!(thd->options
& (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
@@ -3779,14 +3903,13 @@ innodb_show_status(
char* buf;
DBUG_ENTER("innodb_show_status");
-
+
if (innodb_skip) {
-
- fprintf(stderr,
- "Cannot call SHOW INNODB STATUS because skip-innodb is defined\n");
-
- DBUG_RETURN(-1);
- }
+ my_message(ER_NOT_SUPPORTED_YET,
+ "Cannot call SHOW INNODB STATUS because skip-innodb is defined",
+ MYF(0));
+ DBUG_RETURN(-1);
+ }
/* We let the InnoDB Monitor to output at most 100 kB of text, add
a safety margin of 10 kB for buffer overruns */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 357fb31b5e3..d2639f39c5b 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -96,7 +96,7 @@ class ha_innobase: public handler
ulong index_flags(uint idx) const
{
return (HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER |
- HA_KEY_READ_ONLY | HA_NOT_READ_PREFIX_LAST);
+ HA_KEY_READ_ONLY);
}
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_keys() const { return MAX_KEY; }
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc
index 052e6a4b9ec..6fa54d18aac 100644
--- a/sql/ha_isam.cc
+++ b/sql/ha_isam.cc
@@ -380,7 +380,8 @@ int ha_isam::create(const char *name, register TABLE *form,
}
recinfo_pos->base.type= (int) FIELD_LAST; /* End of fieldinfo */
error=nisam_create(fn_format(buff,name,"","",2+4+16),form->keys,keydef,
- recinfo,form->max_rows,form->min_rows,0,0,0L);
+ recinfo,(ulong) form->max_rows, (ulong) form->min_rows,
+ 0, 0, 0L);
my_free((gptr) recinfo,MYF(0));
DBUG_RETURN(error);
diff --git a/sql/ha_isammrg.cc b/sql/ha_isammrg.cc
index b110ffba2f9..94e394e7665 100644
--- a/sql/ha_isammrg.cc
+++ b/sql/ha_isammrg.cc
@@ -190,13 +190,15 @@ THR_LOCK_DATA **ha_isammrg::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
- MRG_TABLE *table;
+ MRG_TABLE *open_table;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- *(to++)= &table->table->lock;
- if (lock_type != TL_IGNORE && table->table->lock.type == TL_UNLOCK)
- table->table->lock.type=lock_type;
+ *(to++)= &open_table->table->lock;
+ if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
+ open_table->table->lock.type=lock_type;
}
return to;
}
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index c7f0ccf69ee..ae71e362875 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -576,7 +576,6 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
}
if (!optimize ||
- //memcmp(file->state, & share->state.state, sizeof(MI_STATUS_INFO)) ||
((file->state->del || share->state.split != file->state->records) &&
(!(param.testflag & T_QUICK) ||
!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))))
@@ -635,7 +634,12 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
STATE_CRASHED_ON_REPAIR);
file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
- //file->save_state=file->s->state.state;
+ /*
+ the following 'if', thought conceptually wrong,
+ is a useful optimization nevertheless.
+ */
+ if (file->state != &file->s->state.state);
+ file->s->state.state = *file->state;
if (file->s->base.auto_key)
update_auto_increment_key(&param, file, 1);
if (optimize_done)
@@ -914,7 +918,7 @@ void ha_myisam::info(uint flag)
if (table->key_parts)
memcpy((char*) table->key_info[0].rec_per_key,
(char*) info.rec_per_key,
- sizeof(ulong)*table->key_parts);
+ sizeof(table->key_info[0].rec_per_key)*table->key_parts);
raid_type=info.raid_type;
raid_chunks=info.raid_chunks;
raid_chunksize=info.raid_chunksize;
@@ -1014,7 +1018,7 @@ void ha_myisam::update_create_info(HA_CREATE_INFO *create_info)
}
-int ha_myisam::create(const char *name, register TABLE *table,
+int ha_myisam::create(const char *name, register TABLE *table_arg,
HA_CREATE_INFO *info)
{
int error;
@@ -1026,20 +1030,20 @@ int ha_myisam::create(const char *name, register TABLE *table,
MI_KEYDEF *keydef;
MI_COLUMNDEF *recinfo,*recinfo_pos;
HA_KEYSEG *keyseg;
- uint options=table->db_options_in_use;
+ uint options=table_arg->db_options_in_use;
DBUG_ENTER("ha_myisam::create");
type=HA_KEYTYPE_BINARY; // Keep compiler happy
if (!(my_multi_malloc(MYF(MY_WME),
- &recinfo,(table->fields*2+2)*sizeof(MI_COLUMNDEF),
- &keydef, table->keys*sizeof(MI_KEYDEF),
+ &recinfo,(table_arg->fields*2+2)*sizeof(MI_COLUMNDEF),
+ &keydef, table_arg->keys*sizeof(MI_KEYDEF),
&keyseg,
- ((table->key_parts + table->keys) * sizeof(HA_KEYSEG)),
+ ((table_arg->key_parts + table_arg->keys) * sizeof(HA_KEYSEG)),
0)))
DBUG_RETURN(1);
- pos=table->key_info;
- for (i=0; i < table->keys ; i++, pos++)
+ pos=table_arg->key_info;
+ for (i=0; i < table_arg->keys ; i++, pos++)
{
keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
keydef[i].key_alg=pos->algorithm == HA_KEY_ALG_UNDEF ?
@@ -1084,7 +1088,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
{
keydef[i].seg[j].null_bit=field->null_bit;
keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
- (uchar*) table->record[0]);
+ (uchar*) table_arg->record[0]);
}
else
{
@@ -1102,19 +1106,19 @@ int ha_myisam::create(const char *name, register TABLE *table,
keydef[i].seg[j].flag|=HA_BLOB_PART;
/* save number of bytes used to pack length */
keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
- table->blob_ptr_size);
+ table_arg->blob_ptr_size);
}
}
keyseg+=pos->key_parts;
}
recpos=0; recinfo_pos=recinfo;
- while (recpos < (uint) table->reclength)
+ while (recpos < (uint) table_arg->reclength)
{
Field **field,*found=0;
- minpos=table->reclength; length=0;
+ minpos=table_arg->reclength; length=0;
- for (field=table->field ; *field ; field++)
+ for (field=table_arg->field ; *field ; field++)
{
if ((fieldpos=(*field)->offset()) >= recpos &&
fieldpos <= minpos)
@@ -1160,7 +1164,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
{
recinfo_pos->null_bit=found->null_bit;
recinfo_pos->null_pos= (uint) (found->null_ptr-
- (uchar*) table->record[0]);
+ (uchar*) table_arg->record[0]);
}
else
{
@@ -1175,13 +1179,13 @@ int ha_myisam::create(const char *name, register TABLE *table,
}
MI_CREATE_INFO create_info;
bzero((char*) &create_info,sizeof(create_info));
- create_info.max_rows=table->max_rows;
- create_info.reloc_rows=table->min_rows;
+ create_info.max_rows=table_arg->max_rows;
+ create_info.reloc_rows=table_arg->min_rows;
create_info.auto_increment=(info->auto_increment_value ?
info->auto_increment_value -1 :
(ulonglong) 0);
- create_info.data_file_length= ((ulonglong) table->max_rows *
- table->avg_row_length);
+ create_info.data_file_length= ((ulonglong) table_arg->max_rows *
+ table_arg->avg_row_length);
create_info.raid_type=info->raid_type;
create_info.raid_chunks= (info->raid_chunks ? info->raid_chunks :
RAID_DEFAULT_CHUNKS);
@@ -1191,7 +1195,7 @@ int ha_myisam::create(const char *name, register TABLE *table,
create_info.index_file_name=info->index_file_name;
error=mi_create(fn_format(buff,name,"","",2+4),
- table->keys,keydef,
+ table_arg->keys,keydef,
(uint) (recinfo_pos-recinfo), recinfo,
0, (MI_UNIQUEDEF*) 0,
&create_info,
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index c35bf657445..07683dca73e 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -187,6 +187,19 @@ void ha_myisammrg::position(const byte *record)
ha_store_ptr(ref, ref_length, (my_off_t) position);
}
+ha_rows ha_myisammrg::records_in_range(int inx,
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag)
+{
+ return (ha_rows) myrg_records_in_range(file,
+ inx,
+ start_key,start_key_len,
+ start_search_flag,
+ end_key,end_key_len,
+ end_search_flag);
+}
void ha_myisammrg::info(uint flag)
{
@@ -262,13 +275,15 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
- MYRG_TABLE *table;
+ MYRG_TABLE *open_table;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- *(to++)= &table->table->lock;
- if (lock_type != TL_IGNORE && table->table->lock.type == TL_UNLOCK)
- table->table->lock.type=lock_type;
+ *(to++)= &open_table->table->lock;
+ if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
+ open_table->table->lock.type=lock_type;
}
return to;
}
@@ -279,14 +294,16 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
DBUG_ENTER("ha_myisammrg::update_create_info");
if (!(create_info->used_fields & HA_CREATE_USED_UNION))
{
- MYRG_TABLE *table;
+ MYRG_TABLE *open_table;
THD *thd=current_thd;
create_info->merge_list.next= &create_info->merge_list.first;
create_info->merge_list.elements=0;
- for (table=file->open_tables ; table != file->end_table ; table++)
+ for (open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- char *name=table->table->filename;
+ char *name=open_table->table->filename;
char buff[FN_REFLEN];
TABLE_LIST *ptr;
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
@@ -323,7 +340,28 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
sizeof(char*))))
DBUG_RETURN(1);
for (pos=table_names ; tables ; tables=tables->next)
- *pos++= tables->real_name;
+ {
+ char *table_name;
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ {
+ TABLE **tbl=find_temporary_table(current_thd,
+ tables->db, tables->real_name);
+ if (!tbl)
+ {
+ table_name=sql_alloc(1+
+ my_snprintf(buff,FN_REFLEN,"%s/%s/%s",mysql_real_data_home,
+ tables->db, tables->real_name));
+ if (!table_name)
+ DBUG_RETURN(1);
+ strcpy(table_name, buff);
+ }
+ else
+ table_name=(*tbl)->path;
+ }
+ else
+ table_name=tables->real_name;
+ *pos++= table_name;
+ }
*pos=0;
DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16),
(const char **) table_names,
@@ -340,13 +378,15 @@ void ha_myisammrg::append_create_info(String *packet)
packet->append(get_type(&merge_insert_method,file->merge_insert_method-1));
}
packet->append(" UNION=(",8);
- MYRG_TABLE *table,*first;
+ MYRG_TABLE *open_table,*first;
- for (first=table=file->open_tables ; table != file->end_table ; table++)
+ for (first=open_table=file->open_tables ;
+ open_table != file->end_table ;
+ open_table++)
{
- char *name=table->table->filename;
+ char *name= open_table->table->filename;
fn_format(buff,name,"","",3);
- if (table != first)
+ if (open_table != first)
packet->append(',');
packet->append(buff,(uint) strlen(buff));
}
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index b75d5360097..8e33b99e418 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -69,6 +69,11 @@ class ha_myisammrg: public handler
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
void position(const byte *record);
+ ha_rows ha_myisammrg::records_in_range(int inx,
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag);
my_off_t row_position() { return myrg_position(file); }
void info(uint);
int extra(enum ha_extra_function operation);
diff --git a/sql/handler.cc b/sql/handler.cc
index f60c3449075..b2cf86a6abc 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -294,7 +294,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
error=1;
}
else
- transaction_commited= 1;
+ if (!(thd->options & OPTION_BEGIN))
+ transaction_commited= 1;
trans->bdb_tid=0;
}
#endif
diff --git a/sql/handler.h b/sql/handler.h
index fbc27f4729b..6cbd83af282 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -153,7 +153,6 @@ typedef struct st_ha_create_information
CHARSET_INFO *table_charset;
char *comment,*password;
char *data_file_name, *index_file_name;
- char *create_statement;
ulonglong max_rows,min_rows;
ulonglong auto_increment_value;
ulong table_options;
@@ -230,7 +229,7 @@ public:
void change_table_ptr(TABLE *table_arg) { table=table_arg; }
virtual double scan_time()
{ return ulonglong2double(data_file_length) / IO_SIZE + 1; }
- virtual double read_time(ha_rows rows) { return rows; }
+ virtual double read_time(ha_rows rows) { return rows2double(rows); }
virtual bool fast_key_read() { return 0;}
virtual key_map keys_to_use_for_scanning() { return 0; }
virtual bool has_transactions(){ return 0;}
diff --git a/sql/hash_filo.h b/sql/hash_filo.h
index 4d746d9b9bd..f7384cc6e32 100644
--- a/sql/hash_filo.h
+++ b/sql/hash_filo.h
@@ -40,7 +40,7 @@ class hash_filo
{
const uint size, key_offset, key_length;
const hash_get_key get_key;
- void (*free_element)(void*);
+ hash_free_key free_element;
bool init;
hash_filo_element *first_link,*last_link;
@@ -49,7 +49,7 @@ public:
HASH cache;
hash_filo(uint size_arg, uint key_offset_arg , uint key_length_arg,
- hash_get_key get_key_arg,void (*free_element_arg)(void*))
+ hash_get_key get_key_arg, hash_free_key free_element_arg)
:size(size_arg), key_offset(key_offset_arg), key_length(key_length_arg),
get_key(get_key_arg), free_element(free_element_arg),init(0)
{
diff --git a/sql/hostname.cc b/sql/hostname.cc
index 3da752f3b64..609532a67d6 100644
--- a/sql/hostname.cc
+++ b/sql/hostname.cc
@@ -63,7 +63,7 @@ bool hostname_cache_init()
if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset,
sizeof(struct in_addr),NULL,
- (void (*)(void*)) free)))
+ (hash_free_key) free)))
return 1;
hostname_cache->clear();
return 0;
diff --git a/sql/item.h b/sql/item.h
index c67c16c50ad..5eeaa22a2a2 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -89,8 +89,8 @@ public:
virtual CHARSET_INFO *charset() const { return str_value.charset(); };
virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); }
-
virtual bool check_loop(uint id);
+ virtual void top_level_item() {}
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 74eb5734ecf..1065c8cf023 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -27,8 +27,8 @@
/*
Test functions
- These returns 0LL if false and 1LL if true and null if some arg is null
- 'AND' and 'OR' never return null
+ Most of these returns 0LL if false and 1LL if true and
+ NULL if some arg is NULL.
*/
longlong Item_func_not::val_int()
@@ -362,13 +362,19 @@ void Item_func_between::fix_length_and_dec()
*/
if (!args[0] || !args[1] || !args[2])
return;
- cmp_type=args[0]->result_type();
- if (args[0]->binary())
+ cmp_type=item_cmp_type(args[0]->result_type(),
+ item_cmp_type(args[1]->result_type(),
+ args[2]->result_type()));
+ if (args[0]->binary() | args[1]->binary() | args[2]->binary())
string_compare=stringcmp;
else
string_compare=sortcmp;
- // Make a special case of compare with fields to get nicer DATE comparisons
+ /*
+ Make a special case of compare with date/time and longlong fields.
+ They are compared as integers, so for const item this time-consuming
+ conversion can be done only once, not for every single comparison
+ */
if (args[0]->type() == FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
@@ -1141,6 +1147,8 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
#endif
item= *li.ref(); // new current item
}
+ if (abort_on_null)
+ item->top_level_item();
if (item->fix_fields(thd, tables, li.ref()))
return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables();
@@ -1230,28 +1238,41 @@ void Item_cond::print(String *str)
str->append(')');
}
+/*
+ Evalution of AND(expr, expr, expr ...)
+
+ NOTES:
+ abort_if_null is set for AND expressions for which we don't care if the
+ result is NULL or 0. This is set for:
+ - WHERE clause
+ - HAVING clause
+ - IF(expression)
+
+ RETURN VALUES
+ 1 If all expressions are true
+ 0 If all expressions are false or if we find a NULL expression and
+ 'abort_on_null' is set.
+ NULL if all expression are either 1 or NULL
+*/
+
longlong Item_cond_and::val_int()
{
List_iterator_fast<Item> li(list);
Item *item;
+ null_value= 0;
while ((item=li++))
{
if (item->val_int() == 0)
{
- /*
- TODO: In case of NULL, ANSI would require us to continue evaluation
- until we get a FALSE value or run out of values; This would
- require a lot of unnecessary evaluation, which we skip for now
- */
- null_value=item->null_value;
- return 0;
+ if (abort_on_null || !(null_value= item->null_value))
+ return 0; // return FALSE
}
}
- null_value=0;
- return 1;
+ return null_value ? 0 : 1;
}
+
longlong Item_cond_or::val_int()
{
List_iterator_fast<Item> li(list);
@@ -1270,6 +1291,45 @@ longlong Item_cond_or::val_int()
return 0;
}
+/*
+ Create an AND expression from two expressions
+
+ SYNOPSIS
+ and_expressions()
+ a expression or NULL
+ b expression.
+ org_item Don't modify a if a == *org_item
+ If a == NULL, org_item is set to point at b,
+ to ensure that future calls will not modify b.
+
+ NOTES
+ This will not modify item pointed to by org_item or b
+ The idea is that one can call this in a loop and create and
+ 'and' over all items without modifying any of the original items.
+
+ RETURN
+ NULL Error
+ Item
+*/
+
+Item *and_expressions(Item *a, Item *b, Item **org_item)
+{
+ if (!a)
+ return (*org_item= b);
+ if (a == *org_item)
+ {
+ Item_cond *res;
+ if ((res= new Item_cond_and(a, b)))
+ res->used_tables_cache= a->used_tables() | b->used_tables();
+ return res;
+ }
+ if (((Item_cond_and*) a)->add(b))
+ return 0;
+ ((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
+ return a;
+}
+
+
longlong Item_func_isnull::val_int()
{
/*
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 489d54ae786..a9dc6c87f95 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -213,6 +213,11 @@ public:
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
+ bool fix_fields(THD *thd,struct st_table_list *tlist)
+ {
+ args[0]->top_level_item();
+ return Item_func::fix_fields(thd,tlist);
+ }
void fix_length_and_dec();
const char *func_name() const { return "if"; }
};
@@ -286,9 +291,9 @@ public:
virtual void set(uint pos,Item *item)=0;
virtual byte *get_value(Item *item)=0;
void sort()
- {
- qsort(base,used_count,size,compare);
- }
+ {
+ qsort(base,used_count,size,compare);
+ }
int find(Item *item);
};
@@ -557,10 +562,12 @@ class Item_cond :public Item_bool_func
{
protected:
List<Item> list;
+ bool abort_on_null;
public:
- Item_cond() : Item_bool_func() { const_item_cache=0; }
- Item_cond(Item *i1,Item *i2) :Item_bool_func()
- { list.push_back(i1); list.push_back(i2); }
+ /* Item_cond() is only used to create top level items */
+ Item_cond() : Item_bool_func(), abort_on_null(1) { const_item_cache=0; }
+ Item_cond(Item *i1,Item *i2) :Item_bool_func(), abort_on_null(0)
+ { list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); }
bool fix_fields(THD *, struct st_table_list *, Item **ref);
@@ -573,6 +580,7 @@ public:
void split_sum_func(List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
bool check_loop(uint id);
+ void top_level_item() { abort_on_null=1; }
};
@@ -620,6 +628,7 @@ inline Item *and_conds(Item *a,Item *b)
return cond;
}
+Item *and_expressions(Item *a, Item *b, Item **org_item);
/**************************************************************
Spatial relations
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 4c7985cd1bf..75260065be6 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -787,13 +787,14 @@ double Item_func_rand::val()
}
else if (!thd->rand_used)
{
- // no need to send a Rand log event if seed was given eg: RAND(seed),
- // as it will be replicated in the query as such.
-
- // save the seed only the first time RAND() is used in the query
+ /*
+ No need to send a Rand log event if seed was given eg: RAND(seed),
+ as it will be replicated in the query as such.
- // once events are forwarded rather than recreated,
- // the following can be skipped if inside the slave thread
+ Save the seed only the first time RAND() is used in the query
+ Once events are forwarded rather than recreated,
+ the following can be skipped if inside the slave thread
+ */
thd->rand_used=1;
thd->rand_saved_seed1=thd->rand.seed1;
thd->rand_saved_seed2=thd->rand.seed2;
@@ -1606,7 +1607,7 @@ void item_user_lock_release(ULL *ull)
tmp.copy(command, strlen(command), tmp.charset());
tmp.append(ull->key,ull->key_length);
tmp.append("\")");
- Query_log_event qev(current_thd,tmp.ptr(), tmp.length());
+ Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1);
qev.error_code=0; // this query is always safe to run on slave
mysql_bin_log.write(&qev);
}
@@ -2051,13 +2052,13 @@ void Item_func_set_user_var::print(String *str)
user_var_entry *Item_func_get_user_var::get_entry()
{
- if (!entry || ! entry->value)
+ if (!var_entry || ! var_entry->value)
{
null_value=1;
return 0;
}
null_value=0;
- return entry;
+ return var_entry;
}
@@ -2126,8 +2127,8 @@ void Item_func_get_user_var::fix_length_and_dec()
maybe_null=1;
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- if ((entry= get_variable(&thd->user_vars, name, 0)))
- const_var_flag= thd->query_id != entry->update_query_id;
+ if ((var_entry= get_variable(&thd->user_vars, name, 0)))
+ const_var_flag= thd->query_id != var_entry->update_query_id;
}
@@ -2317,18 +2318,18 @@ bool Item_func_match::fix_index()
{
List_iterator_fast<Item> li(fields);
Item_field *item;
- uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, key;
+ uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
uint max_cnt=0, mkeys=0;
- if (this->key == NO_SUCH_KEY)
+ if (key == NO_SUCH_KEY)
return 0;
- for (key=0 ; key<table->keys ; key++)
+ for (keynr=0 ; keynr < table->keys ; keynr++)
{
- if ((table->key_info[key].flags & HA_FULLTEXT) &&
- (table->keys_in_use_for_query & (((key_map)1) << key)))
+ if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
+ (table->keys_in_use_for_query & (((key_map)1) << keynr)))
{
- ft_to_key[fts]=key;
+ ft_to_key[fts]=keynr;
ft_cnt[fts]=0;
fts++;
}
@@ -2339,45 +2340,45 @@ bool Item_func_match::fix_index()
while ((item=(Item_field*)(li++)))
{
- for (key=0 ; key<fts ; key++)
+ for (keynr=0 ; keynr < fts ; keynr++)
{
- KEY *ft_key=&table->key_info[ft_to_key[key]];
+ KEY *ft_key=&table->key_info[ft_to_key[keynr]];
uint key_parts=ft_key->key_parts;
for (uint part=0 ; part < key_parts ; part++)
{
if (item->field->eq(ft_key->key_part[part].field))
- ft_cnt[key]++;
+ ft_cnt[keynr]++;
}
}
}
- for (key=0 ; key<fts ; key++)
+ for (keynr=0 ; keynr < fts ; keynr++)
{
- if (ft_cnt[key] > max_cnt)
+ if (ft_cnt[keynr] > max_cnt)
{
mkeys=0;
- max_cnt=ft_cnt[mkeys]=ft_cnt[key];
- ft_to_key[mkeys]=ft_to_key[key];
+ max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
+ ft_to_key[mkeys]=ft_to_key[keynr];
continue;
}
- if (max_cnt && ft_cnt[key] == max_cnt)
+ if (max_cnt && ft_cnt[keynr] == max_cnt)
{
mkeys++;
- ft_cnt[mkeys]=ft_cnt[key];
- ft_to_key[mkeys]=ft_to_key[key];
+ ft_cnt[mkeys]=ft_cnt[keynr];
+ ft_to_key[mkeys]=ft_to_key[keynr];
continue;
}
}
- for (key=0 ; key<=mkeys ; key++)
+ for (keynr=0 ; keynr <= mkeys ; keynr++)
{
// for now, partial keys won't work. SerG
if (max_cnt < fields.elements ||
- max_cnt < table->key_info[ft_to_key[key]].key_parts)
+ max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
continue;
- this->key=ft_to_key[key];
+ key=ft_to_key[keynr];
return 0;
}
@@ -2385,7 +2386,7 @@ bool Item_func_match::fix_index()
err:
if (mode == FT_BOOL)
{
- this->key=NO_SUCH_KEY;
+ key=NO_SUCH_KEY;
return 0;
}
my_printf_error(ER_FT_MATCHING_KEY_NOT_FOUND,
diff --git a/sql/item_func.h b/sql/item_func.h
index 8996919e284..b659a6d69d2 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -918,7 +918,7 @@ public:
class Item_func_get_user_var :public Item_func
{
LEX_STRING name;
- user_var_entry *entry;
+ user_var_entry *var_entry;
bool const_var_flag;
public:
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index cec83428e24..7c085a1b25a 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -198,15 +198,28 @@ longlong Item_func_second::val_int()
}
-// Returns the week of year in the range of 0 - 53
+/*
+ Returns the week of year.
+
+ The bits in week_format has the following meaning:
+ 0 If not set: USA format: Sunday is first day of week
+ If set: ISO format: Monday is first day of week
+ 1 If not set: Week is in range 0-53
+ If set Week is in range 1-53.
+*/
longlong Item_func_week::val_int()
{
uint year;
+ uint week_format;
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
- return (longlong) calc_week(&ltime, 0, args[1]->val_int() == 0, &year);
+ week_format= (uint) args[1]->val_int();
+ return (longlong) calc_week(&ltime,
+ (week_format & 2) != 0,
+ (week_format & 1) == 0,
+ &year);
}
@@ -216,7 +229,7 @@ longlong Item_func_yearweek::val_int()
TIME ltime;
if (get_arg0_date(&ltime,0))
return 0;
- week=calc_week(&ltime, 1, args[1]->val_int() == 0, &year);
+ week=calc_week(&ltime, 1, (args[1]->val_int() & 1) == 0, &year);
return week+year*100;
}
diff --git a/sql/lex.h b/sql/lex.h
index d4c64d08da4..0d0d60fe204 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -267,6 +267,7 @@ static SYMBOL symbols[] = {
{ "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
+ { "OFFSET", SYM(OFFSET_SYM),0,0},
{ "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0},
diff --git a/sql/lock.cc b/sql/lock.cc
index 3b2444c8e9d..74d1109b203 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -80,7 +80,7 @@ extern HASH open_cache;
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
bool unlock, TABLE **write_locked);
-static int lock_external(TABLE **table,uint count);
+static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
static void print_lock_error(int error);
@@ -116,14 +116,14 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
}
thd->proc_info="System lock";
- if (lock_external(tables,count))
+ if (lock_external(thd, tables, count))
{
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
thd->proc_info=0;
break;
}
- thd->proc_info=0;
+ thd->proc_info="Table lock";
thd->locked=1;
if (thr_multi_lock(sql_lock->locks,sql_lock->lock_count))
{
@@ -142,6 +142,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
thd->locked=0;
break;
}
+ thd->proc_info=0;
/* some table was altered or deleted. reopen tables marked deleted */
mysql_unlock_tables(thd,sql_lock);
@@ -151,6 +152,7 @@ retry:
if (wait_for_tables(thd))
break; // Couldn't open tables
}
+ thd->proc_info=0;
if (thd->killed)
{
my_error(ER_SERVER_SHUTDOWN,MYF(0));
@@ -166,15 +168,15 @@ retry:
}
-static int lock_external(TABLE **tables,uint count)
+static int lock_external(THD *thd, TABLE **tables, uint count)
{
reg1 uint i;
int lock_type,error;
- THD *thd=current_thd;
DBUG_ENTER("lock_external");
for (i=1 ; i <= count ; i++, tables++)
{
+ DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
lock_type=F_WRLCK; /* Lock exclusive */
if ((*tables)->db_stat & HA_READ_ONLY ||
((*tables)->reginfo.lock_type >= TL_READ &&
diff --git a/sql/log.cc b/sql/log.cc
index 286dba3f79b..0e1af8e5dae 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1026,9 +1026,13 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
bool MYSQL_LOG::write(Log_event* event_info)
{
bool error=0;
+ DBUG_ENTER("MYSQL_LOG::write(event)");
if (!inited) // Can't use mutex if not init
- return 0;
+ {
+ DBUG_PRINT("error",("not initied"));
+ DBUG_RETURN(0);
+ }
pthread_mutex_lock(&LOCK_log);
/* In most cases this is only called if 'is_open()' is true */
@@ -1036,7 +1040,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
{
bool should_rotate = 0;
THD *thd=event_info->thd;
- const char* db = event_info->get_db();
+ const char *local_db = event_info->get_db();
#ifdef USING_TRANSACTIONS
IO_CACHE *file = ((event_info->get_cache_stmt()) ?
&thd->transaction.trans_log :
@@ -1046,10 +1050,11 @@ bool MYSQL_LOG::write(Log_event* event_info)
#endif
if ((thd && !(thd->options & OPTION_BIN_LOG) &&
(thd->master_access & SUPER_ACL)) ||
- (db && !db_ok(db, binlog_do_db, binlog_ignore_db)))
+ (local_db && !db_ok(local_db, binlog_do_db, binlog_ignore_db)))
{
VOID(pthread_mutex_unlock(&LOCK_log));
- return 0;
+ DBUG_PRINT("error",("!db_ok"));
+ DBUG_RETURN(0);
}
error=1;
@@ -1087,7 +1092,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
char buf[1024] = "SET CHARACTER SET ";
char* p = strend(buf);
p = strmov(p, thd->variables.convert_set->name);
- Query_log_event e(thd, buf, (ulong)(p - buf));
+ Query_log_event e(thd, buf, (ulong)(p - buf), 0);
e.set_log_pos(this);
if (e.write(file))
goto err;
@@ -1135,7 +1140,7 @@ err:
}
pthread_mutex_unlock(&LOCK_log);
- return error;
+ DBUG_RETURN(error);
}
@@ -1165,6 +1170,7 @@ uint MYSQL_LOG::next_file_id()
bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
{
VOID(pthread_mutex_lock(&LOCK_log));
+ DBUG_ENTER("MYSQL_LOG::write(cache");
if (is_open()) // Should always be true
{
@@ -1223,7 +1229,7 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
signal_update();
}
VOID(pthread_mutex_unlock(&LOCK_log));
- return 0;
+ DBUG_RETURN(0);
err:
if (!write_error)
@@ -1232,7 +1238,7 @@ err:
sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno);
}
VOID(pthread_mutex_unlock(&LOCK_log));
- return 1;
+ DBUG_RETURN(1);
}
@@ -1242,7 +1248,7 @@ err:
*/
bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
- time_t query_start)
+ time_t query_start_arg)
{
bool error=0;
if (is_open())
@@ -1260,7 +1266,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
VOID(pthread_mutex_unlock(&LOCK_log));
return 0;
}
- if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start)
+ if ((specialflag & SPECIAL_LONG_LOG_FORMAT) || query_start_arg)
{
current_time=time(NULL);
if (current_time != last_time)
@@ -1288,13 +1294,13 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
thd->ip ? thd->ip : "") == (uint) -1)
tmp_errno=errno;
}
- if (query_start)
+ if (query_start_arg)
{
/* For slow query log */
if (my_b_printf(&log_file,
"# Query_time: %lu Lock_time: %lu Rows_sent: %lu Rows_examined: %lu\n",
- (ulong) (current_time - query_start),
- (ulong) (thd->time_after_lock - query_start),
+ (ulong) (current_time - query_start_arg),
+ (ulong) (thd->time_after_lock - query_start_arg),
(ulong) thd->sent_row_count,
(ulong) thd->examined_row_count) == (uint) -1)
tmp_errno=errno;
@@ -1321,11 +1327,11 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
}
if (thd->query_start_used)
{
- if (query_start != thd->query_start())
+ if (query_start_arg != thd->query_start())
{
- query_start=thd->query_start();
+ query_start_arg=thd->query_start();
end=strmov(end,",timestamp=");
- end=int10_to_str((long) query_start,end,10);
+ end=int10_to_str((long) query_start_arg,end,10);
}
}
if (end != buff)
diff --git a/sql/log_event.cc b/sql/log_event.cc
index c168c951c8f..3747af22922 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -235,22 +235,25 @@ const char* Log_event::get_type_str()
****************************************************************************/
#ifndef MYSQL_CLIENT
-Log_event::Log_event(THD* thd_arg, uint16 flags_arg)
- :exec_time(0), flags(flags_arg), cached_event_len(0),
- temp_buf(0), thd(thd_arg)
+Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
+ :temp_buf(0), exec_time(0), cached_event_len(0), flags(flags_arg),
+ thd(thd_arg)
{
- if (thd)
- {
- server_id = thd->server_id;
- when = thd->start_time;
- log_pos = thd->log_pos;
- }
- else
- {
- server_id = ::server_id;
- when = time(NULL);
- log_pos =0;
- }
+ server_id= thd->server_id;
+ when= thd->start_time;
+ log_pos= thd->log_pos;
+ cache_stmt= (using_trans &&
+ (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)));
+}
+
+
+Log_event::Log_event()
+ :temp_buf(0), exec_time(0), cached_event_len(0), flags(0), cache_stmt(0),
+ thd(0)
+{
+ server_id= ::server_id;
+ when= time(NULL);
+ log_pos= 0;
}
#endif // !MYSQL_CLIENT
@@ -260,7 +263,7 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg)
****************************************************************************/
Log_event::Log_event(const char* buf, bool old_format)
- :cached_event_len(0), temp_buf(0)
+ :temp_buf(0), cached_event_len(0), cache_stmt(0)
{
when = uint4korr(buf);
server_id = uint4korr(buf + SERVER_ID_OFFSET);
@@ -330,11 +333,11 @@ void Log_event::init_show_field_list(List<Item>* field_list)
Only called by SHOW BINLOG EVENTS
****************************************************************************/
-int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
+int Log_event::net_send(THD* thd_arg, const char* log_name, my_off_t pos)
{
- String* packet = &thd->packet;
- const char* p = strrchr(log_name, FN_LIBCHAR);
- const char* event_type;
+ String* packet = &thd_arg->packet;
+ const char *p= strrchr(log_name, FN_LIBCHAR);
+ const char *event_type;
if (p)
log_name = p + 1;
@@ -346,7 +349,7 @@ int Log_event::net_send(THD* thd, const char* log_name, my_off_t pos)
net_store_data(packet, server_id);
net_store_data(packet, (longlong) log_pos);
pack_info(packet);
- return my_net_write(&thd->net, (char*) packet->ptr(), packet->length());
+ return my_net_write(&thd_arg->net, (char*) packet->ptr(), packet->length());
}
#endif // !MYSQL_CLIENT
@@ -725,12 +728,10 @@ int Query_log_event::write_data(IO_CACHE* file)
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans)
- :Log_event(thd_arg), data_buf(0), query(query_arg), db(thd_arg->db),
- q_len((uint32) query_length),
+ :Log_event(thd_arg, 0, using_trans), data_buf(0), query(query_arg),
+ db(thd_arg->db), q_len((uint32) query_length),
error_code(thd_arg->killed ? ER_SERVER_SHUTDOWN: thd_arg->net.last_errno),
- thread_id(thd_arg->thread_id),
- cache_stmt(using_trans &&
- (thd_arg->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
+ thread_id(thd_arg->thread_id)
{
time_t end_time;
time(&end_time);
@@ -1155,18 +1156,18 @@ int Load_log_event::write_data_body(IO_CACHE* file)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
- const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg,
+Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
+ const char *db_arg, const char *table_name_arg,
+ List<Item> &fields_arg,
enum enum_duplicates handle_dup)
- :Log_event(thd),thread_id(thd->thread_id), num_fields(0),fields(0),
+ :Log_event(thd_arg),thread_id(thd_arg->thread_id), num_fields(0),fields(0),
field_lens(0),field_block_len(0),
table_name(table_name_arg ? table_name_arg : ""),
db(db_arg), fname(ex->file_name)
{
time_t end_time;
time(&end_time);
- exec_time = (ulong) (end_time - thd->start_time);
+ exec_time = (ulong) (end_time - thd_arg->start_time);
/* db can never be a zero pointer in 4.0 */
db_len = (uint32) strlen(db);
table_name_len = (uint32) strlen(table_name);
@@ -1236,11 +1237,11 @@ Load_log_event::Load_log_event(THD* thd, sql_exchange* ex,
constructed event.
****************************************************************************/
-Load_log_event::Load_log_event(const char* buf, int event_len,
- bool old_format):
- Log_event(buf, old_format),num_fields(0),fields(0),
- field_lens(0),field_block_len(0),
- table_name(0),db(0),fname(0)
+Load_log_event::Load_log_event(const char *buf, int event_len,
+ bool old_format)
+ :Log_event(buf, old_format),num_fields(0),fields(0),
+ field_lens(0),field_block_len(0),
+ table_name(0),db(0),fname(0)
{
if (!event_len) // derived class, will call copy_log_event() itself
return;
@@ -1390,14 +1391,14 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
****************************************************************************/
#ifndef MYSQL_CLIENT
-void Load_log_event::set_fields(List<Item> &fields)
+void Load_log_event::set_fields(List<Item> &field_list)
{
uint i;
- const char* field = this->fields;
- for (i = 0; i < num_fields; i++)
+ const char* field = fields;
+ for (i= 0; i < num_fields; i++)
{
- fields.push_back(new Item_field(db, table_name, field));
- field += field_lens[i] + 1;
+ field_list.push_back(new Item_field(db, table_name, field));
+ field+= field_lens[i] + 1;
}
}
#endif // !MYSQL_CLIENT
@@ -1458,8 +1459,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
ex.field_term->length(0);
ex.skip_lines = skip_lines;
- List<Item> fields;
- set_fields(fields);
+ List<Item> field_list;
+ set_fields(field_list);
thd->slave_proxy_id = thd->thread_id;
if (net)
{
@@ -1470,7 +1471,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
*/
thd->net.pkt_nr = net->pkt_nr;
}
- if (mysql_load(thd, &ex, &tables, fields, handle_dup, net != 0,
+ if (mysql_load(thd, &ex, &tables, field_list, handle_dup, net != 0,
TL_WRITE))
thd->query_error = 1;
if (thd->cuted_fields)
@@ -1795,14 +1796,12 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
#ifndef MYSQL_CLIENT
void Rand_log_event::pack_info(String* packet)
{
- char buf1[256], buf[22];
- String tmp(buf1, sizeof(buf1), system_charset_info);
- tmp.length(0);
- tmp.append("randseed1=");
- tmp.append(llstr(seed1, buf));
- tmp.append(",randseed2=");
- tmp.append(llstr(seed2, buf));
- net_store_data(packet, tmp.ptr(), tmp.length());
+ char buf1[256], *pos;
+ pos= strmov(buf1,"rand_seed1=");
+ pos= int10_to_str((long) seed1, pos, 10);
+ pos= strmov(pos, ",rand_seed2=");
+ pos= int10_to_str((long) seed2, pos, 10);
+ net_store_data(packet, buf1, (uint) (pos-buf1));
}
#endif // !MYSQL_CLIENT
@@ -1846,8 +1845,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
print_header(file);
fprintf(file, "\tRand\n");
}
- fprintf(file, "SET RAND SEED1=%s;\n", llstr(seed1, llbuff));
- fprintf(file, "SET RAND SEED2=%s;\n", llstr(seed2, llbuff));
+ fprintf(file, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s;\n",
+ llstr(seed1, llbuff),llstr(seed2, llbuff));
fflush(file);
}
#endif // MYSQL_CLIENT
@@ -1860,8 +1859,8 @@ void Rand_log_event::print(FILE* file, bool short_form, char* last_db)
#ifndef MYSQL_CLIENT
int Rand_log_event::exec_event(struct st_relay_log_info* rli)
{
- thd->rand.seed1 = seed1;
- thd->rand.seed2 = seed2;
+ thd->rand.seed1= (ulong) seed1;
+ thd->rand.seed2= (ulong) seed2;
rli->inc_pending(get_event_len());
return 0;
}
@@ -1907,8 +1906,8 @@ void Slave_log_event::pack_info(String* packet)
****************************************************************************/
#ifndef MYSQL_CLIENT
Slave_log_event::Slave_log_event(THD* thd_arg,
- struct st_relay_log_info* rli):
- Log_event(thd_arg),mem_pool(0),master_host(0)
+ struct st_relay_log_info* rli)
+ :Log_event(thd_arg, 0, 0), mem_pool(0), master_host(0)
{
DBUG_ENTER("Slave_log_event");
if (!rli->inited) // QQ When can this happen ?
@@ -2120,11 +2119,13 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Create_file_log_event::Create_file_log_event(THD* thd_arg, sql_exchange* ex,
- const char* db_arg, const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup,
- char* block_arg, uint block_len_arg)
- :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup),
+Create_file_log_event::
+Create_file_log_event(THD* thd_arg, sql_exchange* ex,
+ const char* db_arg, const char* table_name_arg,
+ List<Item>& fields_arg, enum enum_duplicates handle_dup,
+ char* block_arg, uint block_len_arg, bool using_trans)
+ :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup,
+ using_trans),
fake_base(0),block(block_arg),block_len(block_len_arg),
file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
{
@@ -2327,9 +2328,10 @@ err:
****************************************************************************/
#ifndef MYSQL_CLIENT
Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
- uint block_len_arg)
- :Log_event(thd_arg), block(block_arg),block_len(block_len_arg),
- file_id(thd_arg->file_id)
+ uint block_len_arg,
+ bool using_trans)
+ :Log_event(thd_arg,0, using_trans), block(block_arg),
+ block_len(block_len_arg), file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2447,8 +2449,8 @@ err:
****************************************************************************/
#ifndef MYSQL_CLIENT
-Delete_file_log_event::Delete_file_log_event(THD* thd_arg)
- :Log_event(thd_arg),file_id(thd_arg->file_id)
+Delete_file_log_event::Delete_file_log_event(THD *thd_arg, bool using_trans)
+ :Log_event(thd_arg, 0, using_trans),file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2545,8 +2547,8 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
-Execute_load_log_event::Execute_load_log_event(THD* thd_arg)
- :Log_event(thd_arg),file_id(thd_arg->file_id)
+Execute_load_log_event::Execute_load_log_event(THD *thd_arg, bool using_trans)
+ :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id)
{
}
#endif // !MYSQL_CLIENT
@@ -2556,8 +2558,8 @@ Execute_load_log_event::Execute_load_log_event(THD* thd_arg)
Execute_load_log_event ctor
****************************************************************************/
-Execute_load_log_event::Execute_load_log_event(const char* buf,int len)
- :Log_event(buf, 0),file_id(0)
+Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
+ :Log_event(buf, 0), file_id(0)
{
if ((uint)len < EXEC_LOAD_EVENT_OVERHEAD)
return;
diff --git a/sql/log_event.h b/sql/log_event.h
index bf04c480729..20a134ab3cc 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -247,18 +247,19 @@ struct st_relay_log_info;
class Log_event
{
public:
+ my_off_t log_pos;
+ char *temp_buf;
time_t when;
ulong exec_time;
uint32 server_id;
- my_off_t log_pos;
+ uint cached_event_len;
uint16 flags;
- int cached_event_len;
- char* temp_buf;
-
+ bool cache_stmt;
#ifndef MYSQL_CLIENT
THD* thd;
- Log_event(THD* thd_arg, uint16 flags_arg = 0);
+ Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt);
+ Log_event();
// if mutex is 0, the read will proceed without mutex
static Log_event* read_log_event(IO_CACHE* file,
pthread_mutex_t* log_lock,
@@ -301,7 +302,7 @@ public:
{ return 0; }
virtual Log_event_type get_type_code() = 0;
virtual bool is_valid() = 0;
- virtual bool get_cache_stmt() { return 0; }
+ inline bool get_cache_stmt() { return cache_stmt; }
Log_event(const char* buf, bool old_format);
virtual ~Log_event() { free_temp_buf();}
void register_temp_buf(char* buf) { temp_buf = buf; }
@@ -350,14 +351,12 @@ public:
uint16 error_code;
ulong thread_id;
#ifndef MYSQL_CLIENT
- bool cache_stmt;
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
- bool using_trans=0);
+ bool using_trans);
const char* get_db() { return db; }
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
- bool get_cache_stmt() { return cache_stmt; }
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@@ -445,14 +444,15 @@ public:
const char* fname;
uint32 skip_lines;
sql_ex_info sql_ex;
-
+
#ifndef MYSQL_CLIENT
String field_lens_buf;
String fields_buf;
Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
const char* table_name_arg,
- List<Item>& fields_arg, enum enum_duplicates handle_dup);
+ List<Item>& fields_arg, enum enum_duplicates handle_dup,
+ bool using_trans);
void set_fields(List<Item> &fields_arg);
void pack_info(String* packet);
const char* get_db() { return db; }
@@ -468,8 +468,10 @@ public:
Load_log_event(const char* buf, int event_len, bool old_format);
~Load_log_event()
{}
- Log_event_type get_type_code() { return sql_ex.new_format() ?
- NEW_LOAD_EVENT: LOAD_EVENT; }
+ Log_event_type get_type_code()
+ {
+ return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
+ }
int write_data_header(IO_CACHE* file);
int write_data_body(IO_CACHE* file);
bool is_valid() { return table_name != 0; }
@@ -500,7 +502,7 @@ public:
char server_version[ST_SERVER_VER_LEN];
#ifndef MYSQL_CLIENT
- Start_log_event() :Log_event((THD*)0),binlog_version(BINLOG_VERSION)
+ Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION)
{
created = (uint32) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
@@ -538,7 +540,7 @@ public:
#ifndef MYSQL_CLIENT
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
- :Log_event(thd_arg),val(val_arg),type(type_arg)
+ :Log_event(),val(val_arg),type(type_arg)
{}
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
@@ -570,7 +572,7 @@ class Rand_log_event: public Log_event
#ifndef MYSQL_CLIENT
Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg)
- :Log_event(thd_arg),seed1(seed1_arg),seed2(seed2_arg)
+ :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
{}
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
@@ -596,7 +598,7 @@ class Stop_log_event: public Log_event
{
public:
#ifndef MYSQL_CLIENT
- Stop_log_event() :Log_event((THD*)0)
+ Stop_log_event() :Log_event()
{}
int exec_event(struct st_relay_log_info* rli);
#else
@@ -628,8 +630,9 @@ public:
bool alloced;
#ifndef MYSQL_CLIENT
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
- uint ident_len_arg = 0,ulonglong pos_arg = 4)
- : Log_event(thd_arg), new_log_ident(new_log_ident_arg),
+ uint ident_len_arg = 0,
+ ulonglong pos_arg = LOG_EVENT_OFFSET)
+ :Log_event(thd_arg,0,0), new_log_ident(new_log_ident_arg),
pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
(uint) strlen(new_log_ident_arg)), alloced(0)
{}
@@ -678,7 +681,8 @@ public:
const char* table_name_arg,
List<Item>& fields_arg,
enum enum_duplicates handle_dup,
- char* block_arg, uint block_len_arg);
+ char* block_arg, uint block_len_arg,
+ bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
@@ -728,7 +732,7 @@ public:
#ifndef MYSQL_CLIENT
Append_block_log_event(THD* thd, char* block_arg,
- uint block_len_arg);
+ uint block_len_arg, bool using_trans);
int exec_event(struct st_relay_log_info* rli);
void pack_info(String* packet);
#else
@@ -754,7 +758,7 @@ public:
uint file_id;
#ifndef MYSQL_CLIENT
- Delete_file_log_event(THD* thd);
+ Delete_file_log_event(THD* thd, bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
@@ -780,7 +784,7 @@ public:
uint file_id;
#ifndef MYSQL_CLIENT
- Execute_load_log_event(THD* thd);
+ Execute_load_log_event(THD* thd, bool using_trans);
void pack_info(String* packet);
int exec_event(struct st_relay_log_info* rli);
#else
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index aa84a52eb0b..0f20587ec24 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -295,11 +295,11 @@ static int mc_sock_connect(my_socket s, const struct sockaddr *name,
FD_SET(s, &sfds);
tv.tv_sec = (long) to;
tv.tv_usec = 0;
-#ifdef HPUX
+#ifdef HPUX10
res = select(s+1, NULL, (int*) &sfds, NULL, &tv);
#else
res = select(s+1, NULL, &sfds, NULL, &tv);
-#endif
+#endif /* HPUX10 */
if (res <= 0) /* Never became writable */
return(-1);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 392333a4971..4317ea05041 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -85,6 +85,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
*/
#define MIN_FILE_LENGTH_TO_USE_ROW_CACHE (16L*1024*1024)
#define MIN_ROWS_TO_USE_TABLE_CACHE 100
+#define MIN_ROWS_TO_USE_BULK_INSERT 100
/*
The following is used to decide if MySQL should use table scanning
@@ -326,9 +327,8 @@ void mysql_init_multi_delete(LEX *lex);
void init_max_user_conn(void);
void init_update_queries(void);
void free_max_user_conn(void);
-pthread_handler_decl(handle_one_connection,arg);
-pthread_handler_decl(handle_bootstrap,arg);
-sig_handler end_thread_signal(int sig);
+extern "C" pthread_handler_decl(handle_one_connection,arg);
+extern "C" pthread_handler_decl(handle_bootstrap,arg);
void end_thread(THD *thd,bool put_in_cache);
void flush_thread_cache();
void mysql_execute_command(THD *thd);
@@ -441,14 +441,12 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
ORDER *order, ha_rows limit,
- enum enum_duplicates handle_duplicates,
- thr_lock_type lock_type);
+ enum enum_duplicates handle_duplicates);
int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
- List<List_item> &values, enum_duplicates flag,
- thr_lock_type lock_type);
+ List<List_item> &values, enum_duplicates flag);
void kill_delayed_threads(void);
int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, ORDER *order,
- ha_rows rows, thr_lock_type lock_type, ulong options);
+ ha_rows rows, ulong options);
int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
@@ -543,6 +541,7 @@ bool add_field_to_list(char *field_name, enum enum_field_types type,
char *change, TYPELIB *interval,CHARSET_INFO *cs);
void store_position_for_column(const char *name);
bool add_to_list(SQL_LIST &list,Item *group,bool asc=0);
+void set_lock_for_tables(thr_lock_type lock_type);
void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b);
bool add_proc_to_list(Item *item);
@@ -609,7 +608,7 @@ int write_record(TABLE *table,COPY_INFO *info);
extern ulong volatile manager_status;
extern bool volatile manager_thread_in_use, mqh_used;
extern pthread_t manager_thread;
-pthread_handler_decl(handle_manager, arg);
+extern "C" pthread_handler_decl(handle_manager, arg);
/* sql_test.cc */
#ifndef DBUG_OFF
@@ -637,6 +636,8 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
const char *index_file_name,
enum_log_type type, bool read_append = 0,
bool no_auto_events = 0);
+/* mysqld.cc */
+void clear_error_message(THD *thd);
/*
External variables
@@ -762,7 +763,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list);
/* old unireg functions */
void unireg_init(ulong options);
-void unireg_end(int signal);
+void unireg_end(void);
int rea_create_table(THD *thd, my_string file_name,HA_CREATE_INFO *create_info,
List<create_field> &create_field,
uint key_count,KEY *key_info);
@@ -791,7 +792,7 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
-void unireg_abort(int exit_code);
+extern "C" void unireg_abort(int exit_code);
void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select,
int use_record_cache, bool print_errors);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 755998bb8ba..ebda24b404a 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -279,7 +279,7 @@ static char* pidfile_name_ptr= pidfile_name;
static pthread_t select_thread;
static my_bool opt_noacl=0, opt_bootstrap=0, opt_myisam_log=0;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
-my_bool opt_safe_show_db=0, lower_case_table_names, opt_old_rpl_compat;
+my_bool lower_case_table_names, opt_old_rpl_compat;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
my_bool opt_log_slave_updates= 0;
@@ -349,7 +349,7 @@ volatile ulong cached_thread_count=0;
my_string master_user = (char*) "test", master_password = 0, master_host=0,
master_info_file = (char*) "master.info",
relay_log_info_file = (char*) "relay-log.info",
- master_ssl_key=0, master_ssl_cert=0;
+ master_ssl_key=0, master_ssl_cert=0, master_ssl_capath=0, master_ssl_cipher=0;
my_string report_user = 0, report_password = 0, report_host=0;
const char *localhost=LOCAL_HOST;
@@ -458,23 +458,23 @@ pthread_cond_t eventShutdown;
#endif
static void start_signal_handler(void);
-static void *signal_hand(void *arg);
+extern "C" pthread_handler_decl(signal_hand, arg);
static void set_options(void);
static void get_options(int argc,char **argv);
static char *get_relative_path(const char *path);
static void fix_paths(void);
-static pthread_handler_decl(handle_connections_sockets,arg);
-static pthread_handler_decl(kill_server_thread,arg);
+extern "C" pthread_handler_decl(handle_connections_sockets,arg);
+extern "C" pthread_handler_decl(kill_server_thread,arg);
static int bootstrap(FILE *file);
static void close_server_sock();
static bool read_init_file(char *file_name);
#ifdef __NT__
-static pthread_handler_decl(handle_connections_namedpipes,arg);
+extern "C" pthread_handler_decl(handle_connections_namedpipes,arg);
#endif
#ifdef HAVE_SMEM
static pthread_handler_decl(handle_connections_shared_memory,arg);
#endif
-extern pthread_handler_decl(handle_slave,arg);
+extern "C" pthread_handler_decl(handle_slave,arg);
#ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit);
#endif
@@ -781,14 +781,14 @@ static void __cdecl kill_server(int sig_ptr)
if (sig != MYSQL_KILL_SIGNAL && sig != 0)
unireg_abort(1); /* purecov: inspected */
else
- unireg_end(0);
+ unireg_end();
pthread_exit(0); /* purecov: deadcode */
RETURN_FROM_KILL_SERVER;
}
#ifdef USE_ONE_SIGNAL_HAND
-static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
{
SHUTDOWN_THD;
my_thread_init(); // Initialize new thread
@@ -803,7 +803,7 @@ static pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
#define sigset signal
#endif
-static sig_handler print_signal_warning(int sig)
+extern "C" sig_handler print_signal_warning(int sig)
{
if (!DBUG_IN_USE)
{
@@ -820,16 +820,33 @@ static sig_handler print_signal_warning(int sig)
#endif
}
+/*
+ cleanup all memory and end program nicely
+
+ SYNOPSIS
+ unireg_end()
+
+ NOTES
+ This function never returns.
-void unireg_end(int signal_number __attribute__((unused)))
+ If SIGNALS_DONT_BREAK_READ is defined, this function is called
+ by the main thread. To get MySQL to shut down nicely in this case
+ (Mac OS X) we have to call exit() instead if pthread_exit().
+*/
+
+void unireg_end(void)
{
clean_up();
my_thread_end();
+#ifdef SIGNALS_DONT_BREAK_READ
+ exit(0);
+#else
pthread_exit(0); // Exit is in main thread
+#endif
}
-void unireg_abort(int exit_code)
+extern "C" void unireg_abort(int exit_code)
{
DBUG_ENTER("unireg_abort");
if (exit_code)
@@ -875,6 +892,9 @@ void clean_up(bool print_message)
bitmap_free(&temp_pool);
free_max_user_conn();
end_slave_list();
+#ifdef USE_REGEX
+ regex_end();
+#endif
#if !defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
if (!opt_bootstrap)
@@ -1176,7 +1196,7 @@ void close_connection(NET *net,uint errcode,bool lock)
/* Called when a thread is aborted */
/* ARGSUSED */
-sig_handler end_thread_signal(int sig __attribute__((unused)))
+extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
{
THD *thd=current_thd;
DBUG_ENTER("end_thread_signal");
@@ -1267,7 +1287,7 @@ void flush_thread_cache()
*/
#ifdef THREAD_SPECIFIC_SIGPIPE
-static sig_handler abort_thread(int sig __attribute__((unused)))
+extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
{
THD *thd=current_thd;
DBUG_ENTER("abort_thread");
@@ -1341,7 +1361,7 @@ static void start_signal_handler(void)
#define UNSAFE_DEFAULT_LINUX_THREADS 200
#endif
-static sig_handler handle_segfault(int sig)
+extern "C" sig_handler handle_segfault(int sig)
{
THD *thd=current_thd;
/*
@@ -1418,7 +1438,11 @@ information that should help you find out what is causing the crash.\n");
#endif /* HAVE_STACKTRACE */
if (test_flags & TEST_CORE_ON_SIGNAL)
+ {
+ fprintf(stderr, "Writing a core file\n");
+ fflush(stderr);
write_core(sig);
+ }
exit(1);
}
@@ -1526,7 +1550,7 @@ static void start_signal_handler(void)
/* This threads handles all signals and alarms */
/* ARGSUSED */
-static void *signal_hand(void *arg __attribute__((unused)))
+extern "C" void *signal_hand(void *arg __attribute__((unused)))
{
sigset_t set;
int sig;
@@ -1654,8 +1678,8 @@ static void *signal_hand(void *arg __attribute__((unused)))
/* ARGSUSED */
-static int my_message_sql(uint error, const char *str,
- myf MyFlags __attribute__((unused)))
+extern "C" int my_message_sql(uint error, const char *str,
+ myf MyFlags __attribute__((unused)))
{
THD *thd;
DBUG_ENTER("my_message_sql");
@@ -1675,6 +1699,17 @@ static int my_message_sql(uint error, const char *str,
DBUG_RETURN(0);
}
+
+/*
+ Forget last error message (if we got one)
+*/
+
+void clear_error_message(THD *thd)
+{
+ thd->net.last_error[0]= 0;
+}
+
+
#ifdef __WIN__
struct utsname
@@ -1690,7 +1725,7 @@ int uname(struct utsname *a)
#ifdef __WIN__
-pthread_handler_decl(handle_shutdown,arg)
+extern "C" pthread_handler_decl(handle_shutdown,arg)
{
MSG msg;
SHUTDOWN_THD;
@@ -1718,7 +1753,7 @@ int __stdcall handle_kill(ulong ctrl_type)
#endif
#ifdef OS2
-pthread_handler_decl(handle_shutdown,arg)
+extern "C" pthread_handler_decl(handle_shutdown,arg)
{
SHUTDOWN_THD;
my_thread_init();
@@ -1902,8 +1937,6 @@ int main(int argc, char **argv)
if (!ssl_acceptor_fd)
opt_use_ssl = 0;
}
- if (des_key_file)
- load_des_key_file(des_key_file);
#endif /* HAVE_OPENSSL */
#ifdef HAVE_LIBWRAP
@@ -1976,6 +2009,10 @@ int main(int argc, char **argv)
reset_floating_point_exceptions();
init_thr_lock();
init_slave_list();
+#ifdef HAVE_OPENSSL
+ if (des_key_file)
+ load_des_key_file(des_key_file);
+#endif /* HAVE_OPENSSL */
/* Setup log files */
if (opt_log)
@@ -2002,6 +2039,8 @@ int main(int argc, char **argv)
if (ha_init())
{
sql_print_error("Can't init databases");
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
ha_key_cache();
@@ -2037,10 +2076,12 @@ int main(int argc, char **argv)
pthread_key_create(&THR_MALLOC,NULL))
{
sql_print_error("Can't create thread-keys");
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
start_signal_handler(); // Creates pidfile
- if (acl_init(opt_noacl))
+ if (acl_init((THD*) 0, opt_noacl))
{
abort_loop=1;
select_thread_in_use=0;
@@ -2049,10 +2090,12 @@ int main(int argc, char **argv)
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
#endif
+ if (unix_sock != INVALID_SOCKET)
+ unlink(mysql_unix_port);
exit(1);
}
if (!opt_noacl)
- (void) grant_init();
+ (void) grant_init((THD*) 0);
init_max_user_conn();
init_update_queries();
@@ -2521,7 +2564,7 @@ inline void kill_broken_server()
/* Handle new connections and spawn new process to handle them */
-pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
{
my_socket sock,new_sock;
uint error_count=0;
@@ -2557,7 +2600,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
while (!abort_loop)
{
readFDs=clientFDs;
-#ifdef HPUX
+#ifdef HPUX10
if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0)
continue;
#else
@@ -2571,7 +2614,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
MAYBE_BROKEN_SYSCALL
continue;
}
-#endif /* HPUX */
+#endif /* HPUX10 */
if (abort_loop)
{
MAYBE_BROKEN_SYSCALL;
@@ -2728,7 +2771,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
#ifdef __NT__
-pthread_handler_decl(handle_connections_namedpipes,arg)
+extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
{
HANDLE hConnectedPipe;
BOOL fConnected;
@@ -3053,8 +3096,9 @@ enum options {
OPT_MASTER_PASSWORD, OPT_MASTER_PORT,
OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
OPT_MASTER_RETRY_COUNT,
- OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
- OPT_MASTER_SSL_CERT,
+ OPT_MASTER_SSL, OPT_MASTER_SSL_KEY,
+ OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH,
+ OPT_MASTER_SSL_CIPHER,
OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB,
@@ -3371,6 +3415,14 @@ struct my_option my_long_options[] =
"Master SSL certificate file name. Only applies if you have enabled master-ssl.",
(gptr*) &master_ssl_cert, (gptr*) &master_ssl_cert, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
+ {"master-ssl-capath", OPT_MASTER_SSL_CAPATH,
+ "Master SSL CA path. Only applies if you have enabled master-ssl.",
+ (gptr*) &master_ssl_capath, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER,
+ "Master SSL cipher. Only applies if you have enabled master-ssl.",
+ (gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
+ 0, 0, 0, 0, 0, 0},
{"myisam-recover", OPT_MYISAM_RECOVER,
"Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP or FORCE.",
(gptr*) &myisam_recover_options_str, (gptr*) &myisam_recover_options_str, 0,
@@ -3460,7 +3512,7 @@ struct my_option my_long_options[] =
(gptr*) &report_port, (gptr*) &report_port, 0, GET_UINT, REQUIRED_ARG,
MYSQL_PORT, 0, 0, 0, 0, 0},
{"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented",
- (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_UINT,
+ (gptr*) &rpl_recovery_rank, (gptr*) &rpl_recovery_rank, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"relay-log", OPT_RELAY_LOG, "Undocumented",
(gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
@@ -3473,8 +3525,7 @@ struct my_option my_long_options[] =
#ifndef TO_BE_DELETED
{"safe-show-database", OPT_SAFE_SHOW_DB,
"Deprecated option; One should use GRANT SHOW DATABASES instead...",
- (gptr*) &opt_safe_show_db, (gptr*) &opt_safe_show_db, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"safe-user-create", OPT_SAFE_USER_CREATE,
"Don't allow new user creation by the user who has no write privileges to the mysql.user table",
@@ -4029,6 +4080,7 @@ struct show_var_st status_vars[]= {
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
+ {"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG},
{"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
{"Qcache_free_memory", (char*) &query_cache.free_memory,
SHOW_LONG_CONST},
@@ -4149,7 +4201,7 @@ static void set_options(void)
/* Set default values for some variables */
global_system_variables.table_type=DB_TYPE_MYISAM;
- global_system_variables.tx_isolation=ISO_READ_COMMITTED;
+ global_system_variables.tx_isolation=ISO_REPEATABLE_READ;
global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
max_system_variables.select_limit= (ulong) HA_POS_ERROR;
global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
@@ -4176,7 +4228,7 @@ static void set_options(void)
}
-static my_bool
+extern "C" my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
@@ -4621,7 +4673,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
}
global_system_variables.tx_isolation= ((opt_sql_mode & MODE_SERIALIZABLE) ?
ISO_SERIALIZABLE :
- ISO_READ_COMMITTED);
+ ISO_REPEATABLE_READ);
break;
}
case OPT_MASTER_PASSWORD:
@@ -4719,9 +4771,17 @@ fn_format_relative_to_data_home(my_string to, const char *name,
static void fix_paths(void)
{
- char buff[FN_REFLEN];
- (void) fn_format(mysql_home,mysql_home,"","",16); // Remove symlinks
+ char buff[FN_REFLEN],*pos;
convert_dirname(mysql_home,mysql_home,NullS);
+ /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
+ my_realpath(mysql_home,mysql_home,MYF(0));
+ /* Ensure that mysql_home ends in FN_LIBCHAR */
+ pos=strend(mysql_home);
+ if (pos[-1] != FN_LIBCHAR)
+ {
+ pos[0]= FN_LIBCHAR;
+ pos[1]= 0;
+ }
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
convert_dirname(language,language,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index 2d0eae125d6..b917c91ce15 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -568,31 +568,3 @@ BOOL NTService::is_super_user()
FreeSid(psidAdministrators);
return ret_value;
}
-/* ------------------------------------------------------------------------
- -------------------------------------------------------------------------- */
-BOOL NTService::IsService(LPCSTR ServiceName)
-{
- BOOL ret_value=FALSE;
- SC_HANDLE service, scm;
-
- if (scm = OpenSCManager(0, 0,SC_MANAGER_ENUMERATE_SERVICE))
- {
- if ((service = OpenService(scm,ServiceName, SERVICE_ALL_ACCESS )))
- {
- ret_value=TRUE;
- CloseServiceHandle(service);
- }
- CloseServiceHandle(scm);
- }
- return ret_value;
-}
-/* ------------------------------------------------------------------------
- -------------------------------------------------------------------------- */
-BOOL NTService::got_service_option(char **argv, char *service_option)
-{
- char *option;
- for (option= argv[1]; *option; option++)
- if (!strcmp(option, service_option))
- return TRUE;
- return FALSE;
-}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 13c2f6333b1..b6f81ab07eb 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2463,9 +2463,9 @@ int QUICK_SELECT::get_next()
if (range->flag & NO_MIN_RANGE) // Read first record
{
- int error;
- if ((error=file->index_first(record)))
- DBUG_RETURN(error); // Empty table
+ int local_error;
+ if ((local_error=file->index_first(record)))
+ DBUG_RETURN(local_error); // Empty table
if (cmp_next(range) == 0)
DBUG_RETURN(0);
range=0; // No matching records; go to next range
@@ -2499,13 +2499,13 @@ int QUICK_SELECT::get_next()
/* compare if found key is over max-value */
/* Returns 0 if key <= range->max_key */
-int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
+int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
{
- if (range->flag & NO_MAX_RANGE)
- return (0); /* key can't be to large */
+ if (range_arg->flag & NO_MAX_RANGE)
+ return 0; /* key can't be to large */
KEY_PART *key_part=key_parts;
- for (char *key=range->max_key, *end=key+range->max_length;
+ for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
key < end;
key+= key_part++->part_length)
{
@@ -2526,7 +2526,7 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range)
if (cmp > 0)
return 1;
}
- return (range->flag & NEAR_MAX) ? 1 : 0; // Exact match
+ return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match
}
@@ -2610,9 +2610,9 @@ int QUICK_SELECT_DESC::get_next()
if (range->flag & NO_MAX_RANGE) // Read last record
{
- int error;
- if ((error=file->index_last(record)))
- DBUG_RETURN(error); // Empty table
+ int local_error;
+ if ((local_error=file->index_last(record)))
+ DBUG_RETURN(local_error); // Empty table
if (cmp_prev(range) == 0)
DBUG_RETURN(0);
range=0; // No matching records; go to next range
@@ -2666,16 +2666,18 @@ int QUICK_SELECT_DESC::get_next()
}
}
+
/*
- * Returns 0 if found key is inside range (found key >= range->min_key).
- */
-int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range)
+ Returns 0 if found key is inside range (found key >= range->min_key).
+*/
+
+int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
{
- if (range->flag & NO_MIN_RANGE)
- return (0); /* key can't be to small */
+ if (range_arg->flag & NO_MIN_RANGE)
+ return 0; /* key can't be to small */
KEY_PART *key_part = key_parts;
- for (char *key = range->min_key, *end = key + range->min_length;
+ for (char *key = range_arg->min_key, *end = key + range_arg->min_length;
key < end;
key += key_part++->part_length)
{
@@ -2699,42 +2701,45 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range)
if (cmp < 0)
return 1;
}
- return (range->flag & NEAR_MIN) ? 1 : 0; // Exact match
+ return (range_arg->flag & NEAR_MIN) ? 1 : 0; // Exact match
}
+
/*
* True if this range will require using HA_READ_AFTER_KEY
See comment in get_next() about this
*/
-bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range)
+bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg)
{
- return ((range->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
- !(range->flag & EQ_RANGE) ||
- head->key_info[index].key_length != range->max_length) ? 1 : 0;
+ return ((range_arg->flag & (NO_MAX_RANGE | NEAR_MAX)) ||
+ !(range_arg->flag & EQ_RANGE) ||
+ head->key_info[index].key_length != range_arg->max_length) ? 1 : 0;
}
+
/* True if we are reading over a key that may have a NULL value */
-bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range,
+bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
uint used_key_parts)
{
uint offset,end;
KEY_PART *key_part = key_parts,
*key_part_end= key_part+used_key_parts;
- for (offset= 0, end = min(range->min_length, range->max_length) ;
+ for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ;
offset < end && key_part != key_part_end ;
offset += key_part++->part_length)
{
uint null_length=test(key_part->null_bit);
- if (!memcmp((char*) range->min_key+offset, (char*) range->max_key+offset,
+ if (!memcmp((char*) range_arg->min_key+offset,
+ (char*) range_arg->max_key+offset,
key_part->part_length + null_length))
{
offset+=null_length;
continue;
}
- if (null_length && range->min_key[offset])
+ if (null_length && range_arg->min_key[offset])
return 1; // min_key is null and max_key isn't
// Range doesn't cover NULL. This is ok if there is no more null parts
break;
@@ -2747,7 +2752,7 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range,
*/
if (key_part != key_part_end && key_part->null_bit)
{
- if (offset >= range->min_length || range->min_key[offset])
+ if (offset >= range_arg->min_length || range_arg->min_key[offset])
return 1; // Could be null
key_part++;
}
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 38365dbb546..1477d46e756 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -37,6 +37,19 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
bool recalc_const_item=0;
table_map removed_tables=0;
Item *item;
+ COND *org_conds= conds;
+
+ /* Add all ON conditions to WHERE condition */
+ for (TABLE_LIST *tl=tables; tl ; tl= tl->next)
+ {
+ if (tl->on_expr)
+ conds= and_expressions(conds, tl->on_expr, &org_conds);
+ }
+
+ /*
+ Iterate through item is select part and replace COUNT(), MIN() and MAX()
+ with constants (if possible)
+ */
while ((item= it++))
{
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 4295a16c547..785a253b1ac 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -188,14 +188,15 @@ err2:
return 1;
}
-static uint32* slave_list_key(SLAVE_INFO* si, uint* len,
- my_bool not_used __attribute__((unused)))
+extern "C" uint32
+*slave_list_key(SLAVE_INFO* si, uint* len,
+ my_bool not_used __attribute__((unused)))
{
*len = 4;
return &si->server_id;
}
-static void slave_info_free(void *s)
+extern "C" void slave_info_free(void *s)
{
my_free((gptr) s, MYF(MY_WME));
}
@@ -203,7 +204,7 @@ static void slave_info_free(void *s)
void init_slave_list()
{
hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0,
- (hash_get_key) slave_list_key, slave_info_free, 0);
+ (hash_get_key) slave_list_key, (hash_free_key) slave_info_free, 0);
pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST);
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 141320cc3f6..599c4af06cc 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -202,8 +202,6 @@ sys_var_thd_enum sys_query_cache_type("query_cache_type",
&SV::query_cache_type,
&query_cache_type_typelib);
#endif /* HAVE_QUERY_CACHE */
-sys_var_bool_ptr sys_safe_show_db("safe_show_database",
- &opt_safe_show_db);
sys_var_long_ptr sys_server_id("server_id",&server_id);
sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
&opt_slave_compressed_protocol);
@@ -299,6 +297,8 @@ static sys_var_readonly sys_warning_count("warning_count",
/* alias for last_insert_id() to be compatible with Sybase */
static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter");
+static sys_var_rand_seed1 sys_rand_seed1("rand_seed1");
+static sys_var_rand_seed2 sys_rand_seed2("rand_seed2");
/*
@@ -370,10 +370,11 @@ sys_var *sys_variables[]=
&sys_query_cache_type,
#endif /* HAVE_QUERY_CACHE */
&sys_quote_show_create,
+ &sys_rand_seed1,
+ &sys_rand_seed2,
&sys_read_buff_size,
&sys_read_rnd_buff_size,
&sys_rpl_recovery_rank,
- &sys_safe_show_db,
&sys_safe_updates,
&sys_select_limit,
&sys_server_id,
@@ -448,7 +449,7 @@ struct show_var_st init_vars[]= {
{"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
{"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
{"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG },
- {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_LONG},
+ {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_INT},
{"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL},
{"innodb_flush_method", (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR},
{"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
@@ -519,7 +520,6 @@ struct show_var_st init_vars[]= {
{sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS},
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */
- {sys_safe_show_db.name, (char*) &sys_safe_show_db, SHOW_SYS},
#ifdef HAVE_SMEM
{"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL},
{"shared_memory_base_name", (char*) &shared_memory_base_name, SHOW_CHAR_PTR},
@@ -530,7 +530,9 @@ struct show_var_st init_vars[]= {
{"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL},
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
{sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS},
+#ifdef HAVE_SYS_UN_H
{"socket", (char*) &mysql_unix_port, SHOW_CHAR_PTR},
+#endif
{sys_sort_buffer.name, (char*) &sys_sort_buffer, SHOW_SYS},
{"sql_mode", (char*) &opt_sql_mode, SHOW_LONG},
{"table_cache", (char*) &table_cache_size, SHOW_LONG},
@@ -1073,6 +1075,19 @@ bool sys_var_slave_skip_counter::update(THD *thd, set_var *var)
}
+bool sys_var_rand_seed1::update(THD *thd, set_var *var)
+{
+ thd->rand.seed1= (ulong) var->value->val_int();
+ return 0;
+}
+
+bool sys_var_rand_seed2::update(THD *thd, set_var *var)
+{
+ thd->rand.seed2= (ulong) var->value->val_int();
+ return 0;
+}
+
+
/*
Functions to update thd->options bits
*/
diff --git a/sql/set_var.h b/sql/set_var.h
index 62fa977eb06..de1e27e0da8 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -337,6 +337,23 @@ public:
};
+class sys_var_rand_seed1 :public sys_var
+{
+public:
+ sys_var_rand_seed1(const char *name_arg) :sys_var(name_arg) {}
+ bool update(THD *thd, set_var *var);
+ bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+};
+
+class sys_var_rand_seed2 :public sys_var
+{
+public:
+ sys_var_rand_seed2(const char *name_arg) :sys_var(name_arg) {}
+ bool update(THD *thd, set_var *var);
+ bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+};
+
+
class sys_var_thd_conv_charset :public sys_var_thd
{
public:
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 0eef4ae9cad..1b1f90abfb3 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -188,7 +188,7 @@
"Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno",
"Kl-Bíè '%-.64s' v tabulce '%-.64s' neexistuje",
"Nemohu otev-Bøít tabulku",
-"Handler tabulky nepodporuje check/repair",
+"Handler tabulky nepodporuje %s",
"Proveden-Bí tohoto pøíkazu není v transakci dovoleno",
"Chyba %d p-Bøi COMMIT",
"Chyba %d p-Bøi ROLLBACK",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index c2e0ddb064f..65eb190b48b 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -182,7 +182,7 @@
"Du bruger sikker opdaterings modus ('safe update mode') og du forsøgte at opdatere en tabel uden en WHERE klausul, der gør brug af et KEY felt",
"Nøglen '%-.64s' eksisterer ikke i tabellen '%-.64s'",
"Kan ikke åbne tabellen",
-"Denne tabeltype understøtter ikke CHECK/REPAIR",
+"Denne tabeltype understøtter ikke %s",
"Du må ikke bruge denne kommando i en transaktion",
"Modtog fejl %d mens kommandoen COMMIT blev udført",
"Modtog fejl %d mens kommandoen ROLLBACK blev udført",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 7a3f7b787b2..965221dd83f 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -190,7 +190,7 @@
"U gebruikt 'safe update mode' en u probeerde een tabel te updaten zonder een WHERE met een KEY kolom",
"Zoeksleutel '%-.64s' bestaat niet in tabel '%-.64s'",
"Kan tabel niet openen",
-"De 'handler' voor de tabel ondersteund geen check/repair",
+"De 'handler' voor de tabel ondersteund geen %s",
"Het is u niet toegestaan dit commando uit te voeren binnen een transactie",
"Kreeg fout %d tijdens COMMIT",
"Kreeg fout %d tijdens ROLLBACK",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index e746b461a6d..7472fe14365 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index ee20b9890c4..3f2745a8809 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -184,7 +184,7 @@
"Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita",
"Võti '%-.64s' ei eksisteeri tabelis '%-.64s'",
"Ei suuda avada tabelit",
-"Antud tabelitüüp ei toeta CHECK/REPAIR käske",
+"Antud tabelitüüp ei toeta %s käske",
"Seda käsku ei saa kasutada transaktsiooni sees",
"Viga %d käsu COMMIT täitmisel",
"Viga %d käsu ROLLBACK täitmisel",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 89b82b3851b..f1df0c0c2f2 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -179,7 +179,7 @@
"Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index",
"L'index '%-.64s' n'existe pas sur la table '%-.64s'",
"Impossible d'ouvrir la table",
-"Ce type de table ne supporte pas les check/repair",
+"Ce type de table ne supporte pas les %s",
"Vous n'êtes pas autorisé à exécute cette commande dans une transaction",
"Erreur %d lors du COMMIT",
"Erreur %d lors du ROLLBACK",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 3b354ee3298..bd51de5a257 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -182,7 +182,7 @@
"Unter Verwendung des Sicheren Updatemodes wurde versucht eine Tabelle zu updaten ohne eine KEY-Spalte in der WHERE-Klausel",
"Schlüssel '%-.64s' existiert nicht in der Tabelle '%-.64s'",
"Kann Tabelle nicht öffnen",
-"Der Tabellen-Handler für diese Tabelle unterstützt kein check/repair",
+"Der Tabellen-Handler für diese Tabelle unterstützt kein %s",
"Keine Berechtigung dieses Kommando in einer Transaktion auszuführen",
"Fehler %d wärend COMMIT",
"Fehler %d wärend ROLLBACK",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 38ce4217888..915b4e9f64b 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index f2fd63765d9..aa8567dac87 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -181,7 +181,7 @@
"On a biztonsagos update modot hasznalja, es WHERE that uses a KEY column",
"A '%-.64s' kulcs nem letezik a '%-.64s' tablaban",
"Nem tudom megnyitni a tablat",
-"A tabla kezeloje (handler) nem tamogatja az ellenorzest/helyreallitast",
+"A tabla kezeloje (handler) nem tamogatja az %s",
"Az On szamara nem engedelyezett a parancs vegrehajtasa a tranzakcioban",
"%d hiba a COMMIT vegrehajtasa soran",
"%d hiba a ROLLBACK vegrehajtasa soran",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 2b24a123e25..20430757590 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -179,7 +179,7 @@
"In modalita` 'safe update' si e` cercato di aggiornare una tabella senza clausola WHERE su una chiave",
"La chiave '%-.64s' non esiste nella tabella '%-.64s'",
"Impossibile aprire la tabella",
-"Il gestore per la tabella non supporta il controllo/riparazione",
+"Il gestore per la tabella non supporta il %s",
"Non puoi eseguire questo comando in una transazione",
"Rilevato l'errore %d durante il COMMIT",
"Rilevato l'errore %d durante il ROLLBACK",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index 7b428cae703..2f3c61c1fe1 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 8fbc33bf690..277e53895c3 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -179,7 +179,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 1c3cf11e10c..4c3a12d6557 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 1db0068685c..46bf84c409e 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -181,7 +181,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index bda25b01065..e4d9832725d 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -183,7 +183,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 947f935fd33..1c5adc96560 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -179,7 +179,7 @@
"Você está usando modo de atualização seguro e tentou atualizar uma tabela sem uma cláusula WHERE que use uma coluna chave",
"Chave '%-.64s' não existe na tabela '%-.64s'",
"Não pode abrir a tabela",
-"O manipulador de tabela não suporta checagem/reparação (check/repair)",
+"O manipulador de tabela não suporta %s",
"Não lhe é permitido executar este comando em uma transação",
"Obteve erro %d durante COMMIT",
"Obteve erro %d durante ROLLBACK",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 71baf4ca098..313af2e5f14 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -183,7 +183,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 03ea8b74ce5..3b636aacae7 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -182,7 +182,7 @@
"MySQL ÒÁÂÏÔÁÅÔ × ÒÅÖÉÍÅ ÚÁÝÉÔÙ ÏÔ ÄÕÒÁËÏ× (safe_mode) - ÎÅ ÍÏÇÕ UPDATE ÂÅÚ WHERE Ó ËÁËÉÍ-ÎÅÂÕÄØ KEY",
"éÎÄÅËÓ '%-.64s' ÎÅ ÎÁÊÄÅÎ × ÔÁÂÌÉÃÅ '%-.64s'",
"îÅ ÍÏÇÕ ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ",
-"äÁÎÎÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ check/repair",
+"äÁÎÎÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ËÏÍÁÎÄÕ %s",
"üÔÁ ËÏÍÁÎÄÁ ×ÎÕÔÒÉ ÔÒÁÎÚÁËÃÉÉ ÚÁÐÒÅÝÅÎÁ",
"ïÛÉÂËÁ %d ×Ï ×ÒÅÍÑ COMMIT",
"ïÛÉÂËÁ %d ×Ï ×ÒÅÍÑ ROLLBACK",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 36f5e421561..9f610a84bd9 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -187,7 +187,7 @@
"You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column",
"Key '%-.64s' doesn't exist in table '%-.64s'",
"Can't open table",
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
"You are not allowed to execute this command in a transaction",
"Got error %d during COMMIT",
"Got error %d during ROLLBACK",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 5a087d6fa17..ab4e3e93a25 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -180,7 +180,7 @@
"Tu estás usando modo de actualización segura y tentado actualizar una tabla sin un WHERE que usa una KEY columna",
"Clave '%-.64s' no existe en la tabla '%-.64s'",
"No puedo abrir tabla",
-"El manipulador de la tabla no permite soporte para check/repair",
+"El manipulador de la tabla no permite soporte para %s",
"No tienes el permiso para ejecutar este comando en una transición",
"Obtenido error %d durante COMMIT",
"Obtenido error %d durante ROLLBACK",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 42f2e72ec45..3d91522bf0f 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -179,7 +179,7 @@
"Du använder 'säker uppdaterings mod' och försökte uppdatera en table utan en WHERE sats som använder sig av en nyckel",
"Nyckel '%-.64s' finns inte in tabell '%-.64s'",
"Kan inte öppna tabellen",
-"Tabellhanteraren för denna tabell kan inte göra check/repair",
+"Tabellhanteraren för denna tabell kan inte göra %s",
"Du får inte utföra detta kommando i en transaktion",
"Fick fel %d vid COMMIT",
"Fick fel %d vid ROLLBACK",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index f41041de2bb..d16a8e678d1 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -184,7 +184,7 @@
"÷É Õ ÒÅÖÉͦ ÂÅÚÐÅÞÎÏÇÏ ÏÎÏ×ÌÅÎÎÑ ÔÁ ÎÁÍÁÇÁ¤ÔÅÓØ ÏÎÏ×ÉÔÉ ÔÁÂÌÉÃÀ ÂÅÚ ÏÐÅÒÁÔÏÒÁ WHERE, ÝÏ ×ÉËÏÒÉÓÔÏ×Õ¤ KEY ÓÔÏ×ÂÅÃØ",
"ëÌÀÞ '%-.64s' ÎÅ ¦ÓÎÕ¤ × ÔÁÂÌÉæ '%-.64s'",
"îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÔÁÂÌÉÃÀ",
-"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ ÐÅÒÅצÒËÕ/צÄÎÏ×ÌÅÎÎÑ",
+"÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ %s",
"÷ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÎÕ×ÁÔÉ ÃÀ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËæ§",
"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ COMMIT",
"ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ ROLLBACK",
diff --git a/sql/slave.cc b/sql/slave.cc
index a9c1b15a982..f8acc592afa 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -608,7 +608,7 @@ void init_table_rule_hash(HASH* h, bool* h_inited)
{
hash_init(h, system_charset_info,TABLE_RULE_HASH_SIZE,0,0,
(hash_get_key) get_table_key,
- (void (*)(void*)) free_table_ent, 0);
+ (hash_free_key) free_table_ent, 0);
*h_inited = 1;
}
@@ -1637,7 +1637,7 @@ bool flush_master_info(MASTER_INFO* mi)
DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos));
my_b_seek(file, 0L);
- my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n",
+ my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user,
mi->password, mi->port, mi->connect_retry
@@ -1945,7 +1945,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error)
"Slave: query '%s' partially completed on the master \
and was aborted. There is a chance that your master is inconsistent at this \
point. If you are sure that your master is ok, run this query manually on the\
- slave and then restart the slave with SET SQL_SLAVE_SKIP_COUNTER=1;\
+ slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;\
SLAVE START;", thd->query);
rli->last_slave_errno = expected_error;
sql_print_error("%s",rli->last_slave_error);
@@ -2025,11 +2025,10 @@ This may also be a network problem, or just a bug in the master or slave code.\
}
/*****************************************************************************
-
Slave I/O Thread entry point
-
*****************************************************************************/
-pthread_handler_decl(handle_slave_io,arg)
+
+extern "C" pthread_handler_decl(handle_slave_io,arg)
{
THD *thd; // needs to be first for thread_stack
MYSQL *mysql;
@@ -2298,11 +2297,10 @@ err:
}
/*****************************************************************************
-
Slave SQL Thread entry point
-
*****************************************************************************/
-pthread_handler_decl(handle_slave_sql,arg)
+
+extern "C" pthread_handler_decl(handle_slave_sql,arg)
{
THD *thd; /* needs to be first for thread_stack */
char llbuff[22],llbuff1[22];
@@ -2478,7 +2476,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
in the loop
*/
{
- Append_block_log_event aev(thd,0,0);
+ Append_block_log_event aev(thd,0,0,0);
for (;;)
{
@@ -2491,7 +2489,7 @@ static int process_io_create_file(MASTER_INFO* mi, Create_file_log_event* cev)
if (unlikely(!num_bytes)) /* eof */
{
net_write_command(net, 0, "", 0, "", 0);/* 3.23 master wants it */
- Execute_load_log_event xev(thd);
+ Execute_load_log_event xev(thd,0);
xev.log_pos = mi->master_log_pos;
if (unlikely(mi->rli.relay_log.append(&xev)))
{
diff --git a/sql/slave.h b/sql/slave.h
index 74c89f9d755..2c750e415bc 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -436,8 +436,8 @@ int init_relay_log_pos(RELAY_LOG_INFO* rli,const char* log,ulonglong pos,
int purge_relay_logs(RELAY_LOG_INFO* rli, THD *thd, bool just_reset,
const char** errmsg);
-pthread_handler_decl(handle_slave_io,arg);
-pthread_handler_decl(handle_slave_sql,arg);
+extern "C" pthread_handler_decl(handle_slave_io,arg);
+extern "C" pthread_handler_decl(handle_slave_sql,arg);
extern bool volatile abort_loop;
extern MASTER_INFO main_mi, *active_mi; /* active_mi for multi-master */
extern volatile int active_mi_in_use;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 5f8cf42c2bf..8ccd7dbde68 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -119,6 +119,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
SYNOPSIS
acl_init()
+ thd Thread handler
dont_read_acl_tables Set to 1 if run with --skip-grant
RETURN VALUES
@@ -127,9 +128,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
*/
-my_bool acl_init(bool dont_read_acl_tables)
+my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
{
- THD *thd, *org_thd;
+ THD *thd;
TABLE_LIST tables[3];
TABLE *table;
READ_RECORD read_record_info;
@@ -140,14 +141,13 @@ my_bool acl_init(bool dont_read_acl_tables)
if (!acl_cache)
acl_cache=new hash_filo(ACL_CACHE_SIZE,0,0,
(hash_get_key) acl_entry_get_key,
- (void (*)(void*)) free);
+ (hash_free_key) free);
if (dont_read_acl_tables)
DBUG_RETURN(0); /* purecov: tested */
/*
To be able to run this from boot, we allocate a temporary THD
*/
- org_thd=current_thd; // Save for restore
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */
thd->store_globals();
@@ -339,6 +339,11 @@ end:
delete thd;
if (org_thd)
org_thd->store_globals(); /* purecov: inspected */
+ else
+ {
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ }
DBUG_RETURN(return_val);
}
@@ -385,7 +390,7 @@ void acl_reload(THD *thd)
delete_dynamic(&acl_wild_hosts);
hash_free(&acl_check_hosts);
- if (acl_init(0))
+ if (acl_init(thd, 0))
{ // Error. Revert to old list
acl_free(); /* purecov: inspected */
acl_hosts=old_acl_hosts;
@@ -1089,7 +1094,7 @@ bool change_password(THD *thd, const char *host, const char *user,
acl_user->host.hostname ? acl_user->host.hostname : "",
new_password));
mysql_update_log.write(thd, buff, query_length);
- Query_log_event qinfo(thd, buff, query_length);
+ Query_log_event qinfo(thd, buff, query_length, 0);
mysql_bin_log.write(&qinfo);
DBUG_RETURN(0);
}
@@ -1352,8 +1357,13 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
strlen(thd->lex.x509_subject), system_charset_info);
break;
case SSL_TYPE_NOT_SPECIFIED:
- case SSL_TYPE_NONE: // Impossible
- break; // Nothing to do
+ break;
+ case SSL_TYPE_NONE:
+ table->field[24]->store("",0);
+ table->field[25]->store("",0);
+ table->field[26]->store("",0);
+ table->field[27]->store("",0);
+ break;
}
USER_RESOURCES mqh = thd->lex.mqh;
@@ -2275,9 +2285,9 @@ void grant_free(void)
/* Init grant array if possible */
-my_bool grant_init(void)
+my_bool grant_init(THD *org_thd)
{
- THD *thd, *org_thd;
+ THD *thd;
TABLE_LIST tables[2];
MYSQL_LOCK *lock;
my_bool return_val= 1;
@@ -2294,7 +2304,6 @@ my_bool grant_init(void)
if (!initialized)
DBUG_RETURN(0); /* purecov: tested */
- org_thd=current_thd;
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: deadcode */
thd->store_globals();
@@ -2352,13 +2361,18 @@ end:
delete thd;
if (org_thd)
org_thd->store_globals();
+ else
+ {
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+ }
DBUG_RETURN(return_val);
}
/* Reload grant array if possible */
-void grant_reload(void)
+void grant_reload(THD *thd)
{
HASH old_hash_tables;bool old_grant_option;
MEM_ROOT old_mem;
@@ -2372,7 +2386,7 @@ void grant_reload(void)
old_grant_option = grant_option;
old_mem = memex;
- if (grant_init())
+ if (grant_init(thd))
{ // Error. Revert to old hash
grant_free(); /* purecov: deadcode */
hash_tables=old_hash_tables; /* purecov: deadcode */
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 326a55ddd0c..6925b6b406c 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -81,7 +81,7 @@
/* prototypes */
-my_bool acl_init(bool dont_read_acl_tables);
+my_bool acl_init(THD *thd, bool dont_read_acl_tables);
void acl_reload(THD *thd);
void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip, const char *bin_ip,
@@ -98,9 +98,9 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
List <LEX_COLUMN> &column_list, ulong rights,
bool revoke);
-my_bool grant_init(void);
+my_bool grant_init(THD *thd);
void grant_free(void);
-void grant_reload(void);
+void grant_reload(THD *thd);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command=0, bool dont_print_error=0);
bool check_grant_column (THD *thd,TABLE *table, const char *name, uint length,
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 5c735ab35d5..f98eb0e0b26 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -677,7 +677,7 @@ bool analyse::end_of_records()
case FIELD_TYPE_DECIMAL:
ans.append("DECIMAL", 7);
// if item is FIELD_ITEM, it _must_be_ Field_num in this case
- if (((Field_num*) (*f)->item)->zerofill)
+ if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill)
ans.append(" ZEROFILL");
break;
default:
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index fd6c2c48020..59310fb00de 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -39,8 +39,8 @@ static key_map get_key_map_from_key_list(TABLE *table,
List<String> *index_list);
-static byte *cache_key(const byte *record,uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *table_cache_key(const byte *record,uint *length,
+ my_bool not_used __attribute__((unused)))
{
TABLE *entry=(TABLE*) record;
*length=entry->key_length;
@@ -50,8 +50,8 @@ static byte *cache_key(const byte *record,uint *length,
void table_cache_init(void)
{
VOID(hash_init(&open_cache,system_charset_info,
- table_cache_size+16,0,0,cache_key,
- (void (*)(void*)) free_cache_entry,0));
+ table_cache_size+16,0,0,table_cache_key,
+ (hash_free_key) free_cache_entry,0));
mysql_rm_tmp_tables();
}
@@ -536,14 +536,14 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
if (!found)
if_wait_for_refresh=0; // Nothing to wait for
}
+ if (!tables)
+ kill_delayed_threads();
if (if_wait_for_refresh)
{
/*
If there is any table that has a lower refresh_version, wait until
this is closed (or this thread is killed) before returning
*/
- if (!tables)
- kill_delayed_threads();
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
thd->proc_info="Flushing tables";
@@ -699,26 +699,20 @@ void close_temporary_tables(THD *thd)
{
TABLE *table,*next;
char *query, *end;
- const uint init_query_buf_size = 11; // "drop table "
uint query_buf_size;
bool found_user_tables = 0;
+ if (!thd->temporary_tables)
+ return;
+
LINT_INIT(end);
- query_buf_size = init_query_buf_size;
+ query_buf_size= 50; // Enough for DROP ... TABLE
for (table=thd->temporary_tables ; table ; table=table->next)
- {
query_buf_size += table->key_length;
- }
-
- if (query_buf_size == init_query_buf_size)
- return; // no tables to close
if ((query = alloc_root(&thd->mem_root, query_buf_size)))
- {
- memcpy(query, "drop table ", init_query_buf_size);
- end = query + init_query_buf_size;
- }
+ end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE ");
for (table=thd->temporary_tables ; table ; table=next)
{
@@ -727,12 +721,14 @@ void close_temporary_tables(THD *thd)
// skip temporary tables not created directly by the user
if (table->real_name[0] != '#')
{
- end = strxmov(end,table->table_cache_key,".",
- table->real_name,",", NullS);
- // here we assume table_cache_key always starts
- // with \0 terminated db name
+ /*
+ Here we assume table_cache_key always starts
+ with \0 terminated db name
+ */
found_user_tables = 1;
}
+ end = strxmov(end,table->table_cache_key,".",
+ table->real_name,",", NullS);
}
next=table->next;
close_temporary(table);
@@ -740,7 +736,7 @@ void close_temporary_tables(THD *thd)
if (query && found_user_tables && mysql_bin_log.is_open())
{
/* The -1 is to remove last ',' */
- Query_log_event qinfo(thd, query, (ulong)(end-query)-1);
+ Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0);
qinfo.error_code=0;
mysql_bin_log.write(&qinfo);
}
@@ -1435,7 +1431,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
int error;
DBUG_ENTER("open_unireg_entry");
- (void) sprintf(path,"%s/%s/%s",mysql_data_home,db,name);
+ strxmov(path, mysql_data_home, "/", db, "/", name, NullS);
if (openfrm(path,alias,
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX |
HA_TRY_READ_ONLY),
@@ -1564,6 +1560,61 @@ int open_tables(THD *thd,TABLE_LIST *start)
}
+/*
+ Check that lock is ok for tables; Call start stmt if ok
+
+ SYNOPSIS
+ check_lock_and_start_stmt()
+ thd Thread handle
+ table_list Table to check
+ lock_type Lock used for table
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
+ thr_lock_type lock_type)
+{
+ int error;
+ DBUG_ENTER("check_lock_and_start_stmt");
+
+ if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
+ (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
+ {
+ my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
+ ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
+ MYF(0),table->table_name);
+ DBUG_RETURN(1);
+ }
+ if ((error=table->file->start_stmt(thd)))
+ {
+ table->file->print_error(error,MYF(0));
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Open and lock one table
+
+ SYNOPSIS
+ open_ltable()
+ thd Thread handler
+ table_list Table to open is first table in this list
+ lock_type Lock to use for open
+
+ RETURN VALUES
+ table Opened table
+ 0 Error
+
+ If ok, the following are also set:
+ table_list->lock_type lock_type
+ table_list->table table
+*/
+
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
{
TABLE *table;
@@ -1576,8 +1627,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
&refresh)) && refresh) ;
if (table)
{
- int error;
-
#if defined( __WIN__) || defined(OS2)
/* Win32 can't drop a file that is open */
if (lock_type == TL_WRITE_ALLOW_READ)
@@ -1585,39 +1634,29 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
lock_type= TL_WRITE;
}
#endif /* __WIN__ || OS2 */
-
- table_list->table=table;
+ table_list->lock_type= lock_type;
+ table_list->table= table;
table->grant= table_list->grant;
if (thd->locked_tables)
{
- thd->proc_info=0;
- if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
- (int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
- {
- my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
- ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
- MYF(0),table_list->alias);
- table=0;
- }
- else if ((error=table->file->start_stmt(thd)))
- {
- table->file->print_error(error,MYF(0));
- table=0;
- }
- thd->proc_info=0;
- DBUG_RETURN(table);
+ if (check_lock_and_start_stmt(thd, table, lock_type))
+ table= 0;
+ }
+ else
+ {
+ if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
+ if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
+ table= 0;
}
- if ((table->reginfo.lock_type=lock_type) != TL_UNLOCK)
- if (!(thd->lock=mysql_lock_tables(thd,&table_list->table,1)))
- DBUG_RETURN(0);
}
thd->proc_info=0;
DBUG_RETURN(table);
}
+
/*
-** Open all tables in list and locks them for read.
-** The lock will automaticly be freed by the close_thread_tables
+ Open all tables in list and locks them for read.
+ The lock will automaticly be freed by close_thread_tables()
*/
int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
@@ -1627,10 +1666,27 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
return 0;
}
+
+/*
+ Lock all tables in list
+
+ SYNOPSIS
+ lock_tables()
+ thd Thread handler
+ tables Tables to lock
+
+ RETURN VALUES
+ 0 ok
+ -1 Error
+*/
+
int lock_tables(THD *thd,TABLE_LIST *tables)
{
TABLE_LIST *table;
- if (tables && !thd->locked_tables)
+ if (!tables)
+ return 0;
+
+ if (!thd->locked_tables)
{
uint count=0;
for (table = tables ; table ; table=table->next)
@@ -1647,10 +1703,9 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
{
for (table = tables ; table ; table=table->next)
{
- int error;
- if ((error=table->table->file->start_stmt(thd)))
+ if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
{
- table->table->file->print_error(error,MYF(0));
+ ha_rollback_stmt(thd);
return -1;
}
}
@@ -1658,10 +1713,11 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
return 0;
}
+
/*
-** Open a single table without table caching and don't set it in open_list
-** Used by alter_table to open a temporary table and when creating
-** a temporary table with CREATE TEMPORARY ...
+ Open a single table without table caching and don't set it in open_list
+ Used by alter_table to open a temporary table and when creating
+ a temporary table with CREATE TEMPORARY ...
*/
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
@@ -1670,11 +1726,13 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
TABLE *tmp_table;
DBUG_ENTER("open_temporary_table");
- // the extra size in my_malloc() is for table_cache_key
- // 4 bytes for master thread id if we are in the slave
- // 1 byte to terminate db
- // 1 byte to terminate table_name
- // total of 6 extra bytes in my_malloc in addition to table/db stuff
+ /*
+ The extra size in my_malloc() is for table_cache_key
+ 4 bytes for master thread id if we are in the slave
+ 1 byte to terminate db
+ 1 byte to terminate table_name
+ total of 6 extra bytes in my_malloc in addition to table/db stuff
+ */
if (!(tmp_table=(TABLE*) my_malloc(sizeof(*tmp_table)+(uint) strlen(db)+
(uint) strlen(table_name)+6,
MYF(MY_WME))))
@@ -2071,6 +2129,7 @@ bool setup_tables(TABLE_LIST *tables)
DBUG_RETURN(1);
table->keys_in_use_for_query &= ~map;
}
+ table->used_keys &= table->keys_in_use_for_query;
if (table_list->shared)
{
/* Clear query_id that may have been set by previous select */
@@ -2202,6 +2261,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
Item_cond_and *cond_and=new Item_cond_and();
if (!cond_and) // If not out of memory
DBUG_RETURN(1);
+ cond_and->top_level_item();
uint i,j;
for (i=0 ; i < t1->fields ; i++)
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 2f236da2aa3..ef584f4364e 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -473,33 +473,6 @@ byte *query_cache_table_get_key(const byte *record, uint *length,
Query_cache_query methods
*****************************************************************************/
-void Query_cache_query::init_n_lock()
-{
- DBUG_ENTER("Query_cache_query::init_n_lock");
- res=0; wri = 0; len = 0;
- 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))));
- DBUG_VOID_RETURN;
-}
-
-
-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))));
- /*
- The following call is not needed on system where one can destroy an
- active semaphore
- */
- this->unlock_writing();
- rwlock_destroy(&lock);
- DBUG_VOID_RETURN;
-}
-
-
/*
Following methods work for block read/write locking only in this
particular case and in interaction with structure_guard_mutex.
@@ -551,6 +524,34 @@ inline void Query_cache_query::unlock_reading()
RW_UNLOCK(&lock);
}
+
+void Query_cache_query::init_n_lock()
+{
+ DBUG_ENTER("Query_cache_query::init_n_lock");
+ res=0; wri = 0; len = 0;
+ 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))));
+ DBUG_VOID_RETURN;
+}
+
+
+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))));
+ /*
+ The following call is not needed on system where one can destroy an
+ active semaphore
+ */
+ this->unlock_writing();
+ rwlock_destroy(&lock);
+ DBUG_VOID_RETURN;
+}
+
+
extern "C"
{
byte *query_cache_query_get_key(const byte *record, uint *length,
@@ -714,19 +715,19 @@ void query_cache_invalidate_by_MyISAM_filename(const char *filename)
Query_cache methods
*****************************************************************************/
-Query_cache::Query_cache(ulong query_cache_limit,
- ulong min_allocation_unit,
- ulong min_result_data_size,
- uint def_query_hash_size ,
- uint def_table_hash_size)
+Query_cache::Query_cache(ulong query_cache_limit_arg,
+ ulong min_allocation_unit_arg,
+ ulong min_result_data_size_arg,
+ uint def_query_hash_size_arg,
+ uint def_table_hash_size_arg)
:query_cache_size(0),
- query_cache_limit(query_cache_limit),
+ query_cache_limit(query_cache_limit_arg),
queries_in_cache(0), hits(0), inserts(0), refused(0),
- total_blocks(0),
- min_allocation_unit(ALIGN_SIZE(min_allocation_unit)),
- min_result_data_size(ALIGN_SIZE(min_result_data_size)),
- def_query_hash_size(ALIGN_SIZE(def_query_hash_size)),
- def_table_hash_size(ALIGN_SIZE(def_table_hash_size)),
+ total_blocks(0), lowmem_prunes(0),
+ min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)),
+ min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
+ def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
+ def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
initialized(0)
{
ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) +
@@ -751,13 +752,13 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
{
- TABLE_COUNTER_TYPE tables;
+ TABLE_COUNTER_TYPE local_tables;
ulong tot_length;
DBUG_ENTER("Query_cache::store_query");
if (query_cache_size == 0)
DBUG_VOID_RETURN;
- if ((tables = is_cacheable(thd, thd->query_length,
+ if ((local_tables = is_cacheable(thd, thd->query_length,
thd->query, &thd->lex, tables_used)))
{
NET *net = &thd->net;
@@ -803,7 +804,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
Query_cache_block *query_block;
query_block= write_block_data(tot_length, (gptr) thd->query,
ALIGN_SIZE(sizeof(Query_cache_query)),
- Query_cache_block::QUERY, tables, 1);
+ Query_cache_block::QUERY, local_tables, 1);
if (query_block != 0)
{
DBUG_PRINT("qcache", ("query block 0x%lx allocated, %lu",
@@ -820,7 +821,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
STRUCT_UNLOCK(&structure_guard_mutex);
goto end;
}
- if (!register_all_tables(query_block, tables_used, tables))
+ if (!register_all_tables(query_block, tables_used, local_tables))
{
refused++;
DBUG_PRINT("warning", ("tables list including failed"));
@@ -1527,6 +1528,7 @@ my_bool Query_cache::free_old_query()
if (query_block != 0)
{
free_query(query_block);
+ lowmem_prunes++;
DBUG_RETURN(0);
}
}
@@ -1796,7 +1798,7 @@ inline ulong Query_cache::get_min_append_result_data_size()
my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
ulong data_len,
Query_cache_block *query_block,
- my_bool first_block)
+ my_bool first_block_arg)
{
ulong all_headers_len = (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_result)));
@@ -1806,7 +1808,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
DBUG_PRINT("qcache", ("data_len %lu, all_headers_len %lu",
data_len, all_headers_len));
- ulong min_size = (first_block ?
+ ulong min_size = (first_block_arg ?
get_min_first_result_data_size():
get_min_append_result_data_size());
*result_block = allocate_block(max(min_size, align_len),
@@ -1833,7 +1835,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block,
Query_cache_block *next_block;
if ((success = allocate_data_chain(&next_block,
len - new_block->length,
- query_block, first_block)))
+ query_block, first_block_arg)))
double_linked_list_join(new_block, next_block);
}
if (success)
@@ -1902,14 +1904,23 @@ void Query_cache::invalidate_table(Query_cache_block *table_block)
}
}
+/*
+ Store all used tables
+
+ SYNOPSIS
+ register_all_tables()
+ block Store tables in this block
+ tables_used List if used tables
+ tables_arg Not used ?
+*/
my_bool Query_cache::register_all_tables(Query_cache_block *block,
TABLE_LIST *tables_used,
- TABLE_COUNTER_TYPE tables)
+ TABLE_COUNTER_TYPE tables_arg)
{
TABLE_COUNTER_TYPE n;
DBUG_PRINT("qcache", ("register tables block 0x%lx, n %d, header %x",
- (ulong) block, (int) tables,
+ (ulong) block, (int) tables_arg,
(int) ALIGN_SIZE(sizeof(Query_cache_block))));
Query_cache_block_table *block_table = block->table(0);
@@ -2201,28 +2212,28 @@ void Query_cache::split_block(Query_cache_block *block, ulong len)
Query_cache_block *
-Query_cache::join_free_blocks(Query_cache_block *first_block,
+Query_cache::join_free_blocks(Query_cache_block *first_block_arg,
Query_cache_block *block_in_list)
{
Query_cache_block *second_block;
DBUG_ENTER("Query_cache::join_free_blocks");
DBUG_PRINT("qcache",
("join first 0x%lx, pnext 0x%lx, in list 0x%lx",
- (ulong) first_block, (ulong) first_block->pnext,
+ (ulong) first_block_arg, (ulong) first_block_arg->pnext,
(ulong) block_in_list));
exclude_from_free_memory_list(block_in_list);
- second_block = first_block->pnext;
+ second_block = first_block_arg->pnext;
// May be was not free block
second_block->used=0;
second_block->destroy();
total_blocks--;
- first_block->length += second_block->length;
- first_block->pnext = second_block->pnext;
- second_block->pnext->pprev = first_block;
+ first_block_arg->length += second_block->length;
+ first_block_arg->pnext = second_block->pnext;
+ second_block->pnext->pprev = first_block_arg;
- DBUG_RETURN(first_block);
+ DBUG_RETURN(first_block_arg);
}
@@ -2439,7 +2450,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
char *query,
LEX *lex, TABLE_LIST *tables_used)
{
- TABLE_COUNTER_TYPE tables = 0;
+ TABLE_COUNTER_TYPE table_count = 0;
DBUG_ENTER("Query_cache::is_cacheable");
if (lex->sql_command == SQLCOM_SELECT &&
@@ -2456,7 +2467,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
for (; tables_used; tables_used= tables_used->next)
{
- tables++;
+ table_count++;
DBUG_PRINT("qcache", ("table %s, db %s, type %u",
tables_used->real_name,
tables_used->db, tables_used->table->db_type));
@@ -2480,7 +2491,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
{
ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
MYRG_INFO *file = handler->myrg_info();
- tables+= (file->end_table - file->open_tables);
+ table_count+= (file->end_table - file->open_tables);
}
}
@@ -2490,8 +2501,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
DBUG_PRINT("qcache", ("not in autocommin mode"));
DBUG_RETURN(0);
}
- DBUG_PRINT("qcache", ("select is using %d tables", tables));
- DBUG_RETURN(tables);
+ DBUG_PRINT("qcache", ("select is using %d tables", table_count));
+ DBUG_RETURN(table_count);
}
DBUG_PRINT("qcache",
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index f19e6630da5..b15df28f54b 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -178,7 +178,7 @@ extern "C"
my_bool not_used);
}
void query_cache_insert(NET *thd, const char *packet, ulong length);
-void query_cache_invalidate_by_MyISAM_filename(const char* filename);
+extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename);
struct Query_cache_memory_bin
@@ -219,7 +219,7 @@ public:
ulong query_cache_size, query_cache_limit;
/* statistics */
ulong free_memory, queries_in_cache, hits, inserts, refused,
- free_memory_blocks, total_blocks;
+ free_memory_blocks, total_blocks, lowmem_prunes;
protected:
/*
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b7cca50ffb5..e3ee0fb9f72 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -59,14 +59,14 @@ template class List_iterator<Alter_column>;
** User variables
****************************************************************************/
-static byte* get_var_key(user_var_entry *entry, uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *get_var_key(user_var_entry *entry, uint *length,
+ my_bool not_used __attribute__((unused)))
{
*length=(uint) entry->name.length;
return (byte*) entry->name.str;
}
-static void free_var(user_var_entry *entry)
+extern "C" void free_user_var(user_var_entry *entry)
{
char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
if (entry->value && entry->value != pos)
@@ -88,9 +88,6 @@ THD::THD():user_time(0), fatal_error(0),
host_or_ip="unknown ip";
locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password=
query_start_used=safe_to_cache_query=prepare_command=0;
- pthread_mutex_lock(&LOCK_global_system_variables);
- variables= global_system_variables;
- pthread_mutex_unlock(&LOCK_global_system_variables);
db_length=query_length=col_access=0;
query_error=0;
next_insert_id=last_insert_id=0;
@@ -133,19 +130,12 @@ THD::THD():user_time(0), fatal_error(0),
server_id = ::server_id;
slave_net = 0;
log_pos = 0;
- server_status= SERVER_STATUS_AUTOCOMMIT;
- update_lock_default= (variables.low_priority_updates ?
- TL_WRITE_LOW_PRIORITY :
- TL_WRITE);
- options= thd_startup_options;
- sql_mode=(uint) opt_sql_mode;
- open_options=ha_open_options;
- session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
command=COM_CONNECT;
set_query_id=1;
db_access=NO_ACCESS;
version=refresh_version; // For boot
+ init();
/* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root));
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
@@ -157,7 +147,7 @@ THD::THD():user_time(0), fatal_error(0),
user_connect=(USER_CONN *)0;
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key,
- (void (*)(void*)) free_var,0);
+ (hash_free_key) free_user_var,0);
/* Prepared statements */
last_prepared_stmt= 0;
@@ -190,6 +180,48 @@ THD::THD():user_time(0), fatal_error(0),
}
}
+
+/*
+ Init common variables that has to be reset on start and on change_user
+*/
+
+void THD::init(void)
+{
+ server_status= SERVER_STATUS_AUTOCOMMIT;
+ update_lock_default= (variables.low_priority_updates ?
+ TL_WRITE_LOW_PRIORITY :
+ TL_WRITE);
+ options= thd_startup_options;
+ sql_mode=(uint) opt_sql_mode;
+ open_options=ha_open_options;
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ variables= global_system_variables;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
+}
+
+/*
+ Do what's needed when one invokes change user
+
+ SYNOPSIS
+ change_user()
+
+ IMPLEMENTATION
+ Reset all resources that are connection specific
+*/
+
+
+void THD::change_user(void)
+{
+ cleanup();
+ cleanup_done=0;
+ init();
+ hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
+ (hash_get_key) get_var_key,
+ (hash_free_key) free_user_var,0);
+}
+
+
/* Do operations that may take a long time */
void THD::cleanup(void)
@@ -207,17 +239,21 @@ void THD::cleanup(void)
close_thread_tables(this);
}
close_temporary_tables(this);
-#ifdef USING_TRANSACTIONS
- if (opt_using_transactions)
+ hash_free(&user_vars);
+ if (global_read_lock)
+ unlock_global_read_lock(this);
+ if (ull)
{
- close_cached_file(&transaction.trans_log);
- ha_close_connection(this);
+ pthread_mutex_lock(&LOCK_user_locks);
+ item_user_lock_release(ull);
+ pthread_mutex_unlock(&LOCK_user_locks);
+ ull= 0;
}
-#endif
cleanup_done=1;
DBUG_VOID_RETURN;
}
+
THD::~THD()
{
THD_CHECK_SENTRY(this);
@@ -234,15 +270,13 @@ THD::~THD()
}
if (!cleanup_done)
cleanup();
- if (global_read_lock)
- unlock_global_read_lock(this);
- if (ull)
+#ifdef USING_TRANSACTIONS
+ if (opt_using_transactions)
{
- pthread_mutex_lock(&LOCK_user_locks);
- item_user_lock_release(ull);
- pthread_mutex_unlock(&LOCK_user_locks);
+ close_cached_file(&transaction.trans_log);
+ ha_close_connection(this);
}
- hash_free(&user_vars);
+#endif
DBUG_PRINT("info", ("freeing host"));
if (host != localhost) // If not pointer to constant
@@ -338,20 +372,21 @@ void THD::add_changed_table(TABLE *table)
DBUG_VOID_RETURN;
}
+
void THD::add_changed_table(const char *key, long key_length)
{
DBUG_ENTER("THD::add_changed_table(key)");
- CHANGED_TABLE_LIST** prev = &transaction.changed_tables;
- CHANGED_TABLE_LIST* curr = transaction.changed_tables;
+ CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables;
+ CHANGED_TABLE_LIST *curr = transaction.changed_tables;
- for (; curr; prev = &(curr->next), curr = curr->next)
+ for (; curr; prev_changed = &(curr->next), curr = curr->next)
{
int cmp = (long)curr->key_length - (long)key_length;
if (cmp < 0)
{
- list_include(prev, curr, changed_table_dup(key, key_length));
+ list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
- ("key_length %u %u", key_length, (*prev)->key_length));
+ ("key_length %u %u", key_length, (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -359,10 +394,10 @@ void THD::add_changed_table(const char *key, long key_length)
cmp = memcmp(curr->key, key, curr->key_length);
if (cmp < 0)
{
- list_include(prev, curr, changed_table_dup(key, key_length));
+ list_include(prev_changed, curr, changed_table_dup(key, key_length));
DBUG_PRINT("info",
("key_length %u %u", key_length,
- (*prev)->key_length));
+ (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
@@ -372,9 +407,9 @@ void THD::add_changed_table(const char *key, long key_length)
}
}
}
- *prev = changed_table_dup(key, key_length);
+ *prev_changed = changed_table_dup(key, key_length);
DBUG_PRINT("info", ("key_length %u %u", key_length,
- (*prev)->key_length));
+ (*prev_changed)->key_length));
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 9a7ee4556e8..acdf2471ba8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -488,6 +488,7 @@ public:
uint total_warn_count, old_total_warn_count;
ulong query_id, warn_id, version, options, thread_id, col_access;
ulong current_stmt_id;
+ ulong rand_saved_seed1, rand_saved_seed2;
long dbug_thread_id;
pthread_t real_id;
uint current_tablenr,tmp_table,cond_count;
@@ -504,7 +505,6 @@ public:
bool set_query_id,locked,count_cuted_fields,some_tables_deleted;
bool no_errors, allow_sum_func, password, fatal_error;
bool query_start_used,last_insert_id_used,insert_id_used,rand_used;
- ulonglong rand_saved_seed1, rand_saved_seed2;
bool system_thread,in_lock_tables,global_read_lock;
bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query;
@@ -534,6 +534,8 @@ public:
THD();
~THD();
+ void init(void);
+ void change_user(void);
void cleanup(void);
bool store_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE
@@ -932,11 +934,9 @@ public:
ha_rows deleted;
uint num_of_tables;
int error;
- thr_lock_type lock_option;
- bool do_delete, not_trans_safe;
+ bool do_delete, transactional_tables, log_delayed, normal_tables;
public:
- multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
- uint num_of_tables);
+ multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
@@ -956,7 +956,6 @@ public:
ha_rows updated, found;
List<Item> fields;
List <Item> **fields_by_tables;
- thr_lock_type lock_option;
enum enum_duplicates dupl;
uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
int error;
@@ -964,7 +963,7 @@ public:
public:
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
enum enum_duplicates handle_duplicates,
- thr_lock_type lock_option_arg, uint num);
+ uint num);
~multi_update();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list,
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index b80e25c9f40..cefad6a0805 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -220,7 +220,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
if (!thd->query) // Only in replication
{
query= path;
- query_length= (uint) (strxmov(path,"create database ", db, NullS) -
+ query_length= (uint) (strxmov(path,"create database `", db, "`", NullS) -
path);
}
else
@@ -231,7 +231,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
mysql_update_log.write(thd, query, query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, query, query_length);
+ Query_log_event qinfo(thd, query, query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -346,22 +346,25 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
query_cache_invalidate1(db);
if (!silent)
{
+ const char *query;
+ ulong query_length;
if (!thd->query)
{
- thd->query = path;
- thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
- path);
+ /* The client used the old obsolete mysql_drop_db() call */
+ query= path;
+ query_length = (uint) (strxmov(path,"drop database `", db, "`",
+ NullS)- path);
}
- mysql_update_log.write(thd, thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
+ else
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
- mysql_bin_log.write(&qinfo);
+ query=thd->query;
+ query_length=thd->query_length;
}
- if (thd->query == path)
+ mysql_update_log.write(thd, query, query_length);
+ if (mysql_bin_log.is_open())
{
- thd->query = 0; // just in case
- thd->query_length = 0;
+ Query_log_event qinfo(thd, query, query_length, 0);
+ mysql_bin_log.write(&qinfo);
}
send_ok(thd,(ulong) deleted);
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 811cc7c5f5e..cc60ebfb58d 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -28,20 +28,18 @@
#include "sql_select.h"
int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
- ha_rows limit, thr_lock_type lock_type, ulong options)
+ ha_rows limit, ulong options)
{
int error;
TABLE *table;
SQL_SELECT *select=0;
READ_RECORD info;
bool using_limit=limit != HA_POS_ERROR;
- bool using_transactions, safe_update, const_cond;
+ bool using_transactions, log_delayed, safe_update, const_cond;
ha_rows deleted;
DBUG_ENTER("mysql_delete");
- if (!table_list->db)
- table_list->db=thd->db;
- if (!(table = open_ltable(thd,table_list, lock_type)))
+ if (!(table = open_ltable(thd, table_list, table_list->lock_type)))
DBUG_RETURN(-1);
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
@@ -162,23 +160,34 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
(void) table->file->extra(HA_EXTRA_NORMAL);
cleanup:
- using_transactions=table->file->has_transactions();
- if (deleted && (error <= 0 || !using_transactions))
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if (deleted && (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd,thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions && ha_autocommit_or_rollback(thd,error >= 0))
- error=1;
- if (deleted)
+ if (transactional_table)
+ {
+ if (ha_autocommit_or_rollback(thd,error >= 0))
+ error=1;
+ }
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if (deleted &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -205,19 +214,17 @@ cleanup:
#define MEM_STRIP_BUF_SIZE current_thd->variables.sortbuff_size
-int refposcmp2(void* arg, const void *a,const void *b)
+extern "C" int refposcmp2(void* arg, const void *a,const void *b)
{
return memcmp(a,b, *(int*) arg);
}
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
- thr_lock_type lock_option_arg,
uint num_of_tables_arg)
: delete_tables (dt), thd(thd_arg), deleted(0),
- num_of_tables(num_of_tables_arg), error(0), lock_option(lock_option_arg),
- do_delete(false)
+ num_of_tables(num_of_tables_arg), error(0),
+ do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
{
- not_trans_safe=false;
tempfiles = (Unique **) sql_calloc(sizeof(Unique *) * (num_of_tables-1));
}
@@ -268,8 +275,12 @@ multi_delete::initialize_tables(JOIN *join)
/* Don't use KEYREAD optimization on this table */
tbl->no_keyread=1;
walk=walk->next;
- if (!not_trans_safe && !tbl->file->has_transactions())
- not_trans_safe=true;
+ if (tbl->file->has_transactions())
+ log_delayed= transactional_tables= 1;
+ else if (tbl->tmp_table != NO_TMP_TABLE)
+ log_delayed= 1;
+ else
+ normal_tables= 1;
}
}
walk= delete_tables;
@@ -375,7 +386,7 @@ void multi_delete::send_error(uint errcode,const char *err)
In all other cases do attempt deletes ...
*/
if ((table_being_deleted->table->file->has_transactions() &&
- table_being_deleted == delete_tables) || !not_trans_safe)
+ table_being_deleted == delete_tables) || !normal_tables)
ha_rollback_stmt(thd);
else if (do_delete)
{
@@ -394,7 +405,7 @@ void multi_delete::send_error(uint errcode,const char *err)
int multi_delete::do_deletes(bool from_send_error)
{
- int error = 0, counter = 0;
+ int local_error= 0, counter= 0;
if (from_send_error)
{
@@ -415,27 +426,26 @@ int multi_delete::do_deletes(bool from_send_error)
TABLE *table = table_being_deleted->table;
if (tempfiles[counter]->get(table))
{
- error=1;
+ local_error=1;
break;
}
READ_RECORD info;
init_read_record(&info,thd,table,NULL,0,0);
- while (!(error=info.read_record(&info)) &&
- (!thd->killed || from_send_error || not_trans_safe))
+ while (!(local_error=info.read_record(&info)) && !thd->killed)
{
- if ((error=table->file->delete_row(table->record[0])))
+ if ((local_error=table->file->delete_row(table->record[0])))
{
- table->file->print_error(error,MYF(0));
+ table->file->print_error(local_error,MYF(0));
break;
}
deleted++;
}
end_read_record(&info);
- if (error == -1) // End of file
- error = 0;
+ if (local_error == -1) // End of file
+ local_error = 0;
}
- return error;
+ return local_error;
}
@@ -451,15 +461,11 @@ bool multi_delete::send_eof()
thd->proc_info="deleting from reference tables";
/* Does deletes for the last n - 1 tables, returns 0 if ok */
- int error = do_deletes(0); // returns 0 if success
+ int local_error= do_deletes(0); // returns 0 if success
/* reset used flags */
thd->proc_info="end";
- if (error)
- {
- ::send_error(thd);
- return 1;
- }
+
/*
Write the SQL statement to the binlog if we deleted
@@ -467,24 +473,25 @@ bool multi_delete::send_eof()
was a non-transaction-safe table involved, since
modifications in it cannot be rolled back.
*/
- if (deleted || not_trans_safe)
+ if (deleted)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
- if (mysql_bin_log.write(&qinfo) &&
- !not_trans_safe)
- error=1; // Log write failed: roll back the SQL statement
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && !normal_tables)
+ local_error=1; // Log write failed: roll back the SQL statement
}
/* Commit or rollback the current SQL statement */
- VOID(ha_autocommit_or_rollback(thd,error > 0));
- }
- if (deleted)
- {
+ VOID(ha_autocommit_or_rollback(thd,local_error > 0));
+
query_cache_invalidate3(thd, delete_tables, 1);
}
- ::send_ok(thd,deleted);
+ if (local_error)
+ ::send_error(thd);
+ else
+ ::send_ok(thd, deleted);
return 0;
}
@@ -557,8 +564,9 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
if (!ha_supports_generate(table_type))
{
/* Probably InnoDB table */
- DBUG_RETURN(mysql_delete(thd,table_list, (COND*) 0, (ORDER*) 0,
- HA_POS_ERROR, TL_WRITE, 0));
+ table_list->lock_type= TL_WRITE;
+ DBUG_RETURN(mysql_delete(thd, table_list, (COND*) 0, (ORDER*) 0,
+ HA_POS_ERROR, 0));
}
if (lock_and_wait_for_table_name(thd, table_list))
DBUG_RETURN(-1);
@@ -570,6 +578,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
*fn_ext(path)=0; // Remove the .frm extension
error= ha_create_table(path,&create_info,1) ? -1 : 0;
query_cache_invalidate3(thd, table_list, 0);
+
end:
if (!dont_send_ok)
{
@@ -578,7 +587,8 @@ end:
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ thd->tmp_table);
mysql_bin_log.write(&qinfo);
}
send_ok(thd); // This should return record count
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 0a1b4435fff..6cb146afb33 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -25,7 +25,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup,
char *query, uint query_length, bool log_on);
static void end_delayed_insert(THD *thd);
-static pthread_handler_decl(handle_delayed_insert,arg);
+extern "C" pthread_handler_decl(handle_delayed_insert,arg);
static void unlink_blobs(register TABLE *table);
/* Define to force use of my_malloc() if the allocated memory block is big */
@@ -98,13 +98,12 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
- List<List_item> &values_list,enum_duplicates duplic,
- thr_lock_type lock_type)
+ List<List_item> &values_list,enum_duplicates duplic)
{
int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
!(thd->master_access & SUPER_ACL));
- bool using_transactions, bulk_insert=0;
+ bool transactional_table, log_delayed, bulk_insert=0;
uint value_count;
uint save_time_stamp;
ulong counter = 1;
@@ -114,6 +113,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
List_iterator_fast<List_item> its(values_list);
List_item *values;
char *query=thd->query;
+ thr_lock_type lock_type = table_list->lock_type;
DBUG_ENTER("mysql_insert");
/*
@@ -194,14 +194,19 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->proc_info="update";
if (duplic == DUP_IGNORE || duplic == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- if ((bulk_insert= (values_list.elements > 1 &&
+ if ((bulk_insert= (values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT &&
lock_type != TL_WRITE_DELAYED &&
!(specialflag & SPECIAL_SAFE_MODE))))
{
table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
- thd->variables.read_buff_size);
- table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
- thd->variables.bulk_insert_buff_size);
+ min(thd->variables.read_buff_size,
+ table->avg_row_length*values_list.elements));
+ if (thd->variables.bulk_insert_buff_size)
+ table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
+ min(thd->variables.bulk_insert_buff_size,
+ (table->total_key_length +
+ table->keys * TREE_ELEMENT_EXTRA_SIZE)*
+ values_list.elements));
table->bulk_insert= 1;
}
@@ -266,10 +271,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
info.copied=values_list.elements;
end_delayed_insert(thd);
}
- if (info.copied || info.deleted)
- {
- query_cache_invalidate3(thd, table_list, 1);
- }
+ query_cache_invalidate3(thd, table_list, 1);
}
else
{
@@ -297,23 +299,33 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
thd->insert_id(id); // For update log
else if (table->next_number_field)
id=table->next_number_field->val_int(); // Return auto_increment value
- using_transactions=table->file->has_transactions();
- if ((info.copied || info.deleted) && (error <= 0 || !using_transactions))
+
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if ((info.copied || info.deleted) && (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions)
+ if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
- if (info.copied || info.deleted)
+
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if ((info.copied || info.deleted) &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -913,7 +925,7 @@ void kill_delayed_threads(void)
* Create a new delayed insert thread
*/
-static pthread_handler_decl(handle_delayed_insert,arg)
+extern "C" pthread_handler_decl(handle_delayed_insert,arg)
{
delayed_insert *di=(delayed_insert*) arg;
THD *thd= &di->thd;
@@ -1197,7 +1209,7 @@ bool delayed_insert::handle_inserts(void)
mysql_update_log.write(&thd,row->query, row->query_length);
if (using_bin_log)
{
- Query_log_event qinfo(&thd, row->query, row->query_length);
+ Query_log_event qinfo(&thd, row->query, row->query_length,0);
mysql_bin_log.write(&qinfo);
}
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 6bafef8a469..9f8e3200246 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -436,9 +436,9 @@ typedef struct st_lex
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
uint param_count;
- bool drop_primary, drop_if_exists, local_file, olap;
+ bool drop_primary, drop_if_exists, drop_temporary, local_file;
bool in_comment, ignore_space, verbose, simple_alter;
- bool derived_tables, describe;
+ bool derived_tables, describe, olap;
uint slave_thd_opt;
CHARSET_INFO *charset;
char *help_arg;
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 52d1f3adf48..00450a3b86c 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -90,7 +90,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
bool is_fifo=0;
LOAD_FILE_INFO lf_info;
char * db = table_list->db ? table_list->db : thd->db;
- bool using_transactions;
+ bool transactional_table, log_delayed;
DBUG_ENTER("mysql_load");
#ifdef EMBEDDED_LIBRARY
@@ -105,6 +105,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
if (!(table = open_ltable(thd,table_list,lock_type)))
DBUG_RETURN(-1);
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+
if (!fields.elements)
{
Field **field;
@@ -224,6 +227,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
lf_info.handle_dup = handle_duplicates;
lf_info.wrote_create_file = 0;
lf_info.last_pos_in_file = HA_POS_ERROR;
+ lf_info.log_delayed= log_delayed;
read_info.set_io_cache_arg((void*) &lf_info);
}
restore_record(table,2);
@@ -275,16 +279,16 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
free_blobs(table); /* if pack_blob was used */
table->copy_blobs=0;
thd->count_cuted_fields=0; /* Don`t calc cuted fields */
- using_transactions = table->file->has_transactions();
+
if (error)
{
- if (using_transactions)
+ if (transactional_table)
ha_autocommit_or_rollback(thd,error);
if (!opt_old_rpl_compat && mysql_bin_log.is_open())
{
if (lf_info.wrote_create_file)
{
- Delete_file_log_event d(thd);
+ Delete_file_log_event d(thd, log_delayed);
mysql_bin_log.write(&d);
}
}
@@ -297,27 +301,30 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (!thd->slave_thread)
mysql_update_log.write(thd,thd->query,thd->query_length);
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
if (mysql_bin_log.is_open())
{
- if (opt_old_rpl_compat && !read_file_from_client)
+ if (opt_old_rpl_compat)
{
- Load_log_event qinfo(thd, ex, db, table->table_name, fields,
- handle_duplicates);
- mysql_bin_log.write(&qinfo);
+ if (!read_file_from_client)
+ {
+ Load_log_event qinfo(thd, ex, db, table->table_name, fields,
+ handle_duplicates, log_delayed);
+ mysql_bin_log.write(&qinfo);
+ }
}
- if (!opt_old_rpl_compat)
+ else
{
read_info.end_io_cache(); // make sure last block gets logged
if (lf_info.wrote_create_file)
{
- Execute_load_log_event e(thd);
+ Execute_load_log_event e(thd, log_delayed);
mysql_bin_log.write(&e);
}
}
}
- if (using_transactions)
+ if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
DBUG_RETURN(error);
}
diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc
index 13cac83fc3f..0af6a80d4c2 100644
--- a/sql/sql_manager.cc
+++ b/sql/sql_manager.cc
@@ -32,7 +32,7 @@ pthread_t manager_thread;
pthread_mutex_t LOCK_manager;
pthread_cond_t COND_manager;
-pthread_handler_decl(handle_manager,arg __attribute__((unused)))
+extern "C" pthread_handler_decl(handle_manager,arg __attribute__((unused)))
{
int error = 0;
ulong status;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index aebccf7a39e..4816a0539f3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -98,7 +98,17 @@ static void init_signals(void)
}
#endif
-inline bool end_active_trans(THD *thd)
+static void unlock_locked_tables(THD *thd)
+{
+ if (thd->locked_tables)
+ {
+ thd->lock=thd->locked_tables;
+ thd->locked_tables=0; // Will be automaticly closed
+ close_thread_tables(thd); // Free tables
+ }
+}
+
+static bool end_active_trans(THD *thd)
{
int error=0;
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
@@ -257,14 +267,14 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
started with corresponding variable that is greater then 0.
*/
-static byte* get_key_conn(user_conn *buff, uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte *get_key_conn(user_conn *buff, uint *length,
+ my_bool not_used __attribute__((unused)))
{
*length=buff->len;
return (byte*) buff->user;
}
-static void free_user(struct user_conn *uc)
+extern "C" void free_user(struct user_conn *uc)
{
my_free((char*) uc,MYF(0));
}
@@ -273,7 +283,7 @@ void init_max_user_conn(void)
{
(void) hash_init(&hash_user_connections,system_charset_info,max_connections,
0,0,
- (hash_get_key) get_key_conn, (void (*)(void*)) free_user,
+ (hash_get_key) get_key_conn, (hash_free_key) free_user,
0);
}
@@ -552,7 +562,13 @@ check_connections(THD *thd)
{
/* Do the SSL layering. */
DBUG_PRINT("info", ("IO layer change in progress..."));
- sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout);
+ if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout))
+ {
+ DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
+ pkt_len));
+ inc_host_errors(&thd->remote.sin_addr);
+ return(ER_HANDSHAKE_ERROR);
+ }
DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len=my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE)
@@ -690,7 +706,7 @@ pthread_handler_decl(handle_one_connection,arg)
(net->last_errno ? ER(net->last_errno) :
ER(ER_UNKNOWN_ERROR)));
send_error(thd,net->last_errno,NullS);
- thread_safe_increment(aborted_threads,&LOCK_status);
+ statistic_increment(aborted_threads,&LOCK_status);
}
end_thread:
@@ -711,7 +727,7 @@ end_thread:
Used when creating the initial grant tables
*/
-pthread_handler_decl(handle_bootstrap,arg)
+extern "C" pthread_handler_decl(handle_bootstrap,arg)
{
THD *thd=(THD*) arg;
FILE *file=bootstrap_file;
@@ -903,7 +919,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->lex.select_lex.options=0; // We store status here
switch (command) {
case COM_INIT_DB:
- thread_safe_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_CHANGE_DB],&LOCK_status);
if (!mysql_change_db(thd,packet))
mysql_log.write(thd,command,"%s",thd->db);
break;
@@ -915,7 +931,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_TABLE_DUMP:
{
- thread_safe_increment(com_other, &LOCK_status);
+ statistic_increment(com_other, &LOCK_status);
slow_command = TRUE;
uint db_len = *(uchar*)packet;
uint tbl_len = *(uchar*)(packet + db_len + 1);
@@ -932,7 +948,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_CHANGE_USER:
{
- thread_safe_increment(com_other,&LOCK_status);
+ thd->change_user();
+ clear_error_message(thd); // If errors from rollback
+
+ statistic_increment(com_other,&LOCK_status);
char *user= (char*) packet;
char *passwd= strend(user)+1;
char *db= strend(passwd)+1;
@@ -1005,7 +1024,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
char *fields;
TABLE_LIST table_list;
- thread_safe_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_SHOW_FIELDS],&LOCK_status);
bzero((char*) &table_list,sizeof(table_list));
if (!(table_list.db=thd->db))
{
@@ -1040,7 +1059,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_CREATE_DB: // QQ: To be removed
{
- thread_safe_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status);
char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
@@ -1058,7 +1077,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_DROP_DB: // QQ: To be removed
{
- thread_safe_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_DROP_DB],&LOCK_status);
char *db=thd->strdup(packet);
// null test to handle EOM
if (!db || !strip_sp(db) || check_db_name(db))
@@ -1079,7 +1098,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_BINLOG_DUMP:
{
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
slow_command = TRUE;
if (check_global_access(thd, REPL_SLAVE_ACL))
break;
@@ -1103,7 +1122,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_REFRESH:
{
- thread_safe_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_FLUSH],&LOCK_status);
ulong options= (ulong) (uchar) packet[0];
if (check_global_access(thd,RELOAD_ACL))
break;
@@ -1115,7 +1134,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_SHUTDOWN:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd,SHUTDOWN_ACL))
break; /* purecov: inspected */
DBUG_PRINT("quit",("Got shutdown command"));
@@ -1138,7 +1157,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_STATISTICS:
{
mysql_log.write(thd,command,NullS);
- thread_safe_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_SHOW_STATUS],&LOCK_status);
char buff[200];
ulong uptime = (ulong) (thd->start_time - start_time);
sprintf((char*) buff,
@@ -1157,11 +1176,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
case COM_PING:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
send_ok(thd); // Tell client we are alive
break;
case COM_PROCESS_INFO:
- thread_safe_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_SHOW_PROCESSLIST],&LOCK_status);
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
mysql_log.write(thd,command,NullS);
@@ -1170,13 +1189,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
case COM_PROCESS_KILL:
{
- thread_safe_increment(com_stat[SQLCOM_KILL],&LOCK_status);
+ statistic_increment(com_stat[SQLCOM_KILL],&LOCK_status);
ulong id=(ulong) uint4korr(packet);
kill_one_thread(thd,id);
break;
}
case COM_DEBUG:
- thread_safe_increment(com_other,&LOCK_status);
+ statistic_increment(com_other,&LOCK_status);
if (check_global_access(thd, SUPER_ACL))
break; /* purecov: inspected */
mysql_print_status(thd);
@@ -1355,7 +1374,7 @@ mysql_execute_command(THD *thd)
!tables_ok(thd,tables)))
DBUG_VOID_RETURN;
- thread_safe_increment(com_stat[lex->sql_command],&LOCK_status);
+ statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
case SQLCOM_SELECT:
{
@@ -1413,6 +1432,8 @@ mysql_execute_command(THD *thd)
Normal select:
Change lock if we are using SELECT HIGH PRIORITY,
FOR UPDATE or IN SHARE MODE
+
+ TODO: Delete the following loop when locks is set by sql_yacc
*/
TABLE_LIST *table;
for (table = tables ; table ; table=table->next)
@@ -1642,6 +1663,7 @@ mysql_execute_command(THD *thd)
TABLE_LIST *table;
if (check_table_access(thd, SELECT_ACL, tables->next))
goto error; // Error message is given
+ /* TODO: Delete the following loop when locks is set by sql_yacc */
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
@@ -1711,7 +1733,7 @@ mysql_execute_command(THD *thd)
#else
{
ulong priv=0;
- if (lex->name && strlen(lex->name) > NAME_LEN)
+ if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
{
net_printf(thd,ER_WRONG_TABLE_NAME,lex->name);
res=0;
@@ -1885,18 +1907,13 @@ mysql_execute_command(THD *thd)
}
if (select_lex->table_list.elements == 1)
{
- res = mysql_update(thd,tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- (ORDER *) select_lex->order_list.first,
- select_lex->select_limit,
- lex->duplicates,
- lex->lock_option);
-
-#ifdef DELETE_ITEMS
- delete select_lex->where;
-#endif
+ res= mysql_update(thd,tables,
+ select_lex->item_list,
+ lex->value_list,
+ select_lex->where,
+ (ORDER *) select_lex->order_list.first,
+ select_lex->select_limit,
+ lex->duplicates);
}
else
{
@@ -1906,11 +1923,8 @@ mysql_execute_command(THD *thd)
const char *msg=0;
lex->sql_command=SQLCOM_MULTI_UPDATE;
- for (auxi=(TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
- {
+ for (auxi= (TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
table_count++;
- auxi->lock_type=TL_WRITE;
- }
if (select_lex->order_list.elements)
msg="ORDER BY";
@@ -1932,8 +1946,7 @@ mysql_execute_command(THD *thd)
!setup_fields(thd,tables,lex->value_list,0,0,0) &&
!thd->fatal_error &&
(result=new multi_update(thd,tables,select_lex->item_list,
- lex->duplicates, lex->lock_option,
- table_count)))
+ lex->duplicates, table_count)))
{
List <Item> total_list;
List_iterator <Item> field_list(select_lex->item_list);
@@ -1964,8 +1977,7 @@ mysql_execute_command(THD *thd)
if (grant_option && check_grant(thd,INSERT_ACL,tables))
goto error;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- lex->duplicates,
- lex->lock_option);
+ lex->duplicates);
break;
case SQLCOM_REPLACE:
if (check_access(thd,INSERT_ACL | DELETE_ACL,
@@ -1976,8 +1988,7 @@ mysql_execute_command(THD *thd)
goto error;
res = mysql_insert(thd,tables,lex->field_list,lex->many_values,
- DUP_REPLACE,
- lex->lock_option);
+ DUP_REPLACE);
break;
case SQLCOM_REPLACE_SELECT:
case SQLCOM_INSERT_SELECT:
@@ -2012,8 +2023,8 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_INSERT_TABLE_USED,tables->real_name);
DBUG_VOID_RETURN;
}
- tables->lock_type=TL_WRITE; // update first table
{
+ /* TODO: Delete the following loop when locks is set by sql_yacc */
TABLE_LIST *table;
for (table = tables->next ; table ; table=table->next)
table->lock_type= lex->lock_option;
@@ -2056,8 +2067,7 @@ mysql_execute_command(THD *thd)
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
res = mysql_delete(thd,tables, select_lex->where,
(ORDER*) select_lex->order_list.first,
- select_lex->select_limit, lex->lock_option,
- select_lex->options);
+ select_lex->select_limit, select_lex->options);
break;
}
case SQLCOM_DELETE_MULTI:
@@ -2093,7 +2103,7 @@ mysql_execute_command(THD *thd)
net_printf(thd,ER_NONUNIQ_TABLE,auxi->real_name);
goto error;
}
- auxi->lock_type=walk->lock_type=TL_WRITE;
+ walk->lock_type= auxi->lock_type;
auxi->table_list= walk; // Remember corresponding table
}
if (add_item_to_list(new Item_null()))
@@ -2108,7 +2118,6 @@ mysql_execute_command(THD *thd)
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
auxi->table= auxi->table_list->table;
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
- lex->lock_option,
table_count)))
{
res= mysql_select(thd,tables,select_lex->item_list,
@@ -2314,11 +2323,7 @@ mysql_execute_command(THD *thd)
send_ok(thd);
break;
case SQLCOM_UNLOCK_TABLES:
- if (thd->locked_tables)
- {
- thd->lock=thd->locked_tables;
- thd->locked_tables=0; // Will be automaticly closed
- }
+ unlock_locked_tables(thd);
if (thd->options & OPTION_TABLE_LOCK)
{
end_active_trans(thd);
@@ -2329,12 +2334,7 @@ mysql_execute_command(THD *thd)
send_ok(thd);
break;
case SQLCOM_LOCK_TABLES:
- if (thd->locked_tables)
- {
- thd->lock=thd->locked_tables;
- thd->locked_tables=0; // Will be automaticly closed
- close_thread_tables(thd);
- }
+ unlock_locked_tables(thd);
if (check_db_used(thd,tables) || end_active_trans(thd))
goto error;
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, tables))
@@ -2484,7 +2484,7 @@ mysql_execute_command(THD *thd)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
}
@@ -2504,7 +2504,7 @@ mysql_execute_command(THD *thd)
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
if (mqh_used && lex->sql_command == SQLCOM_GRANT)
@@ -2874,7 +2874,7 @@ mysql_init_query(THD *thd)
thd->total_warn_count=0; // Warnings for this query
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
thd->sent_row_count= thd->examined_row_count= 0;
- thd->fatal_error= thd->rand_used=0;
+ thd->fatal_error= thd->rand_used= 0;
thd->safe_to_cache_query= 1;
thd->possible_loops= 0;
DBUG_VOID_RETURN;
@@ -3476,14 +3476,50 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table,
}
+/*
+ Set lock for all tables in current select level
+
+ SYNOPSIS:
+ set_lock_for_tables()
+ lock_type Lock to set for tables
+
+ NOTE:
+ If lock is a write lock, then tables->updating is set 1
+ This is to get tables_ok to know that the table is updated by the
+ query
+*/
+
+void set_lock_for_tables(thr_lock_type lock_type)
+{
+ THD *thd=current_thd;
+ bool for_update= lock_type >= TL_READ_NO_INSERT;
+ DBUG_ENTER("set_lock_for_tables");
+ DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
+ for_update));
+
+ for (TABLE_LIST *tables= (TABLE_LIST*) thd->lex.select->table_list.first ;
+ tables ;
+ tables=tables->next)
+ {
+ tables->lock_type= lock_type;
+ tables->updating= for_update;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
void add_join_on(TABLE_LIST *b,Item *expr)
{
- if (!b->on_expr)
- b->on_expr=expr;
- else
+ if (expr)
{
- // This only happens if you have both a right and left join
- b->on_expr=new Item_cond_and(b->on_expr,expr);
+ if (!b->on_expr)
+ b->on_expr=expr;
+ else
+ {
+ // This only happens if you have both a right and left join
+ b->on_expr=new Item_cond_and(b->on_expr,expr);
+ }
+ b->on_expr->top_level_item();
}
}
@@ -3511,7 +3547,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
if (options & REFRESH_GRANT)
{
acl_reload(thd);
- grant_reload();
+ grant_reload(thd);
if (mqh_used)
reset_mqh(thd,(LEX_USER *) NULL,true);
}
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index a9ab1776e19..5b0ec2ec843 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -94,7 +94,7 @@ end:
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 93545d10268..23951cec29f 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -941,7 +941,7 @@ int show_binlog_events(THD* thd)
if (mysql_bin_log.is_open())
{
LEX_MASTER_INFO *lex_mi = &thd->lex.mi;
- uint event_count, limit_start, limit_end;
+ ha_rows event_count, limit_start, limit_end;
my_off_t pos = lex_mi->pos;
char search_file_name[FN_REFLEN], *name;
const char *log_file_name = lex_mi->log_file_name;
@@ -1133,7 +1133,8 @@ int log_loaded_block(IO_CACHE* file)
lf_info->last_pos_in_file = file->pos_in_file;
if (lf_info->wrote_create_file)
{
- Append_block_log_event a(lf_info->thd, buffer, block_len);
+ Append_block_log_event a(lf_info->thd, buffer, block_len,
+ lf_info->log_delayed);
mysql_bin_log.write(&a);
}
else
@@ -1141,7 +1142,7 @@ int log_loaded_block(IO_CACHE* file)
Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
lf_info->table_name, *lf_info->fields,
lf_info->handle_dup, buffer,
- block_len);
+ block_len, lf_info->log_delayed);
mysql_bin_log.write(&c);
lf_info->wrote_create_file = 1;
DBUG_SYNC_POINT("debug_lock.created_file_event",10);
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 197fd03ec7c..15435382b08 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -43,13 +43,13 @@ int check_binlog_magic(IO_CACHE* log, const char** errmsg);
typedef struct st_load_file_info
{
THD* thd;
+ my_off_t last_pos_in_file;
sql_exchange* ex;
List <Item> *fields;
enum enum_duplicates handle_dup;
char* db;
char* table_name;
- bool wrote_create_file;
- my_off_t last_pos_in_file;
+ bool wrote_create_file, log_delayed;
} LOAD_FILE_INFO;
int log_loaded_block(IO_CACHE* file);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 05551980309..20b000392df 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -367,6 +367,7 @@ JOIN::optimize()
{
conds->fix_fields(thd, tables_list, &conds);
conds->change_ref_to_fields(thd, tables_list);
+ conds->top_level_item();
having= 0;
}
}
@@ -960,6 +961,7 @@ JOIN::exec()
sort_table_cond)))
DBUG_VOID_RETURN;
table->select_cond=table->select->cond;
+ table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select->cond,
"select and having"););
having_list= make_cond_for_table(having_list, ~ (table_map) 0,
@@ -1432,7 +1434,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
select->quick=0;
if (records != HA_POS_ERROR)
{
- s->found_records=records;
+ s->records=s->found_records=records;
s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
}
}
@@ -1965,7 +1967,7 @@ static void
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
double read_time)
{
- ulong rec;
+ ha_rows rec;
double tmp;
THD *thd= join->thd;
@@ -2158,7 +2160,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
records
This gives the formula:
records= (x * (b-a) + a*c-b)/(c-1)
-
+
b = records matched by whole key
a = records matched by first key part (10% of all records?)
c = number of key parts in key
@@ -2227,7 +2229,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{ // Check full join
if (s->on_expr)
{
- tmp=s->found_records; // Can't use read cache
+ tmp=rows2double(s->found_records); // Can't use read cache
}
else
{
@@ -2246,11 +2248,11 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
will ensure that this will be used
*/
best=tmp;
- records=s->found_records;
+ records= rows2double(s->found_records);
best_key=0;
}
}
- join->positions[idx].records_read=(double) records;
+ join->positions[idx].records_read= records;
join->positions[idx].key=best_key;
join->positions[idx].table= s;
if (!best_key && idx == join->const_tables &&
@@ -2587,7 +2589,7 @@ bool
store_val_in_field(Field *field,Item *item)
{
THD *thd=current_thd;
- ulong cuted_fields=thd->cuted_fields;
+ ha_rows cuted_fields=thd->cuted_fields;
thd->count_cuted_fields=1;
(void) item->save_in_field(field);
thd->count_cuted_fields=0;
@@ -2675,7 +2677,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
use_quick_range=1;
tab->use_quick=1;
tab->ref.key_parts=0; // Don't use ref key.
- join->best_positions[i].records_read=tab->quick->records;
+ join->best_positions[i].records_read= rows2double(tab->quick->records);
}
COND *tmp=make_cond_for_table(cond,used_tables,current_map);
@@ -3948,7 +3950,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*blob_field= 0; // End marker
/* If result table is small; use a heap */
- if (blob_count || using_unique_constraint || group_null_items ||
+ if (blob_count || using_unique_constraint ||
(select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
OPTION_BIG_TABLES)
{
@@ -5547,6 +5549,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
else
{
+ if (end_of_records)
+ DBUG_RETURN(0);
join->first_record=1;
VOID(test_if_group_changed(join->group_fields));
}
@@ -5616,6 +5620,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
{
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
+ /* Create new top level AND item */
Item_cond_and *new_cond=new Item_cond_and;
if (!new_cond)
return (COND*) 0; // OOM /* purecov: inspected */
@@ -5653,6 +5658,7 @@ make_cond_for_table(COND *cond,table_map tables,table_map used_table)
new_cond->argument_list()->push_back(fix);
}
new_cond->used_tables_cache=((Item_cond_or*) cond)->used_tables_cache;
+ new_cond->top_level_item();
return new_cond;
}
}
@@ -6004,6 +6010,7 @@ static bool fix_having(JOIN *join, Item **having)
sort_table_cond)))
return 1;
table->select_cond=table->select->cond;
+ table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select_cond,
"select and having"););
*having=make_cond_for_table(*having,~ (table_map) 0,~used_tables);
@@ -7432,56 +7439,32 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
{
if (tab->use_quick == 2)
{
- sprintf(buff_ptr,"range checked for each record (index map: %u)",
+ sprintf(buff_ptr,"; Range checked for each record (index map: %u)",
tab->keys);
buff_ptr=strend(buff_ptr);
}
else
- buff_ptr=strmov(buff_ptr,"where used");
+ buff_ptr=strmov(buff_ptr,"; Using where");
}
if (key_read)
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using index");
- }
+ buff_ptr= strmov(buff_ptr,"; Using index");
if (table->reginfo.not_exists_optimize)
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Not exists");
- }
+ buff_ptr= strmov(buff_ptr,"; Not exists");
if (need_tmp_table)
{
need_tmp_table=0;
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using temporary");
+ buff_ptr= strmov(buff_ptr,"; Using temporary");
}
if (need_order)
{
need_order=0;
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Using filesort");
+ buff_ptr= strmov(buff_ptr,"; Using filesort");
}
if (distinct & test_all_bits(used_tables,thd->used_tables))
- {
- if (buff != buff_ptr)
- {
- buff_ptr[0]=';' ; buff_ptr[1]=' '; buff_ptr+=2;
- }
- buff_ptr=strmov(buff_ptr,"Distinct");
- }
- item_list.push_back(new Item_string(buff,(uint) (buff_ptr - buff),
+ buff_ptr= strmov(buff_ptr,"; Distinct");
+ if (buff_ptr == buff)
+ buff_ptr+= 2; // Skip inital "; "
+ item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2,
default_charset_info));
// For next iteration
used_tables|=table->map;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c039f84dc77..ebf5b210d6c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -889,7 +889,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
field_list.push_back(item=new Item_empty_string("Collation",1));
item->maybe_null=1;
- field_list.push_back(item=new Item_int("Cardinality",0,11));
+ field_list.push_back(item=new Item_int("Cardinality",0,21));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Sub_part",0,3));
item->maybe_null=1;
@@ -930,8 +930,8 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
KEY *key=table->key_info+i;
if (key->rec_per_key[j])
{
- ulong records=(table->file->records / key->rec_per_key[j]);
- end=int10_to_str((long) records, buff, 10);
+ ha_rows records=(table->file->records / key->rec_per_key[j]);
+ end=longlong10_to_str((longlong) records, buff, 10);
net_store_data(packet,convert,buff,(uint) (end-buff));
}
else
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index abb4cf8d3f9..00077bda39f 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -110,6 +110,17 @@ int mysql_rm_table_part2_with_lock(THD *thd,
return error;
}
+/*
+ TODO:
+ When logging to the binary log, we should log
+ tmp_tables and transactional tables as separate statements if we
+ are in a transaction; This is needed to get these tables into the
+ cached binary log that is only written on COMMIT.
+
+ The current code only writes DROP statements that only uses temporary
+ tables to the cache binary log. This should be ok on most cases, but
+ not all.
+*/
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool dont_log_query)
@@ -119,7 +130,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
String wrong_tables;
db_type table_type;
int error;
- bool some_tables_deleted=0;
+ bool some_tables_deleted=0, tmp_table_deleted=0;
DBUG_ENTER("mysql_rm_table_part2");
for (table=tables ; table ; table=table->next)
@@ -127,7 +138,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char *db=table->db ? table->db : thd->db;
if (!close_temporary_table(thd, db, table->real_name))
{
- some_tables_deleted=1; // Log query
+ tmp_table_deleted=1;
continue; // removed temporary table
}
@@ -143,8 +154,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
DBUG_RETURN(-1);
/* remove form file and isam files */
- (void) sprintf(path,"%s/%s/%s%s",mysql_data_home,db,table->real_name,
- reg_ext);
+ strxmov(path, mysql_data_home, "/", db, "/", table->real_name, reg_ext,
+ NullS);
(void) unpack_filename(path,path);
error=0;
@@ -177,7 +188,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
wrong_tables.append(String(table->real_name,default_charset_info));
}
}
- if (some_tables_deleted)
+ if (some_tables_deleted || tmp_table_deleted)
{
query_cache_invalidate3(thd, tables, 0);
if (!dont_log_query)
@@ -185,7 +196,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ tmp_table_deleted && !some_tables_deleted);
mysql_bin_log.write(&qinfo);
}
}
@@ -271,7 +283,8 @@ static int sort_keys(KEY *a, KEY *b)
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
- tmp_table Set to 1 if this is a temporary table
+ tmp_table Set to 1 if this is an internal temporary table
+ (From ALTER TABLE)
no_log Don't log the query to binary log.
DESCRIPTION
@@ -784,7 +797,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
thd->proc_info="creating table";
- create_info->create_statement = thd->query;
create_info->table_options=db_options;
if (rea_create_table(thd, path, create_info, fields, key_count,
key_info_buffer))
@@ -792,16 +804,6 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
/* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */
goto end;
}
- if (!tmp_table && !no_log)
- {
- // Must be written before unlock
- mysql_update_log.write(thd,thd->query, thd->query_length);
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length);
- mysql_bin_log.write(&qinfo);
- }
- }
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
/* Open table and put in temporary table list */
@@ -811,6 +813,18 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
goto end;
}
}
+ if (!tmp_table && !no_log)
+ {
+ // Must be written before unlock
+ mysql_update_log.write(thd,thd->query, thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ test(create_info->options &
+ HA_LEX_CREATE_TMP_TABLE));
+ mysql_bin_log.write(&qinfo);
+ }
+ }
error=0;
end:
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -1255,8 +1269,13 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
switch (result_code) {
case HA_ADMIN_NOT_IMPLEMENTED:
- net_store_data(packet, "error");
- net_store_data(packet, ER(ER_CHECK_NOT_IMPLEMENTED));
+ {
+ char buf[ERRMSGSIZE+20];
+ my_snprintf(buf, ERRMSGSIZE,
+ ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
+ net_store_data(packet, "error");
+ net_store_data(packet, buf);
+ }
break;
case HA_ADMIN_OK:
@@ -1511,7 +1530,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
@@ -1887,7 +1906,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
goto end_temporary;
@@ -2016,7 +2035,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
VOID(pthread_cond_broadcast(&COND_refresh));
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index f45eca0b65f..35e33caf572 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -98,8 +98,8 @@ static void init_syms(udf_func *tmp)
}
}
-static byte* get_hash_key(const byte *buff,uint *length,
- my_bool not_used __attribute__((unused)))
+extern "C" byte* get_hash_key(const byte *buff,uint *length,
+ my_bool not_used __attribute__((unused)))
{
udf_func *udf=(udf_func*) buff;
*length=(uint) udf->name_length;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index be69935a49c..73343ab1a50 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -50,11 +50,10 @@ int mysql_update(THD *thd,
COND *conds,
ORDER *order,
ha_rows limit,
- enum enum_duplicates handle_duplicates,
- thr_lock_type lock_type)
+ enum enum_duplicates handle_duplicates)
{
- bool using_limit=limit != HA_POS_ERROR;
- bool used_key_is_modified, using_transactions;
+ bool using_limit=limit != HA_POS_ERROR, safe_update= thd->options & OPTION_SAFE_UPDATES;
+ bool used_key_is_modified, transactional_table, log_delayed;
int error=0;
uint save_time_stamp, used_index, want_privilege;
ulong query_id=thd->query_id, timestamp_query_id;
@@ -66,7 +65,7 @@ int mysql_update(THD *thd,
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
- if (!(table = open_ltable(thd,table_list,lock_type)))
+ if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
DBUG_RETURN(-1); /* purecov: inspected */
save_time_stamp=table->time_stamp;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -117,9 +116,7 @@ int mysql_update(THD *thd,
table->used_keys=0;
select=make_select(table,0,0,conds,&error);
if (error ||
- (select && select->check_quick(test(thd->options & OPTION_SAFE_UPDATES),
- limit)) ||
- !limit)
+ (select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
table->time_stamp=save_time_stamp; // Restore timestamp pointer
@@ -134,7 +131,7 @@ int mysql_update(THD *thd,
if (!table->quick_keys)
{
thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
- if ((thd->options & OPTION_SAFE_UPDATES) && limit == HA_POS_ERROR)
+ if (safe_update && !using_limit)
{
delete select;
table->time_stamp=save_time_stamp;
@@ -301,23 +298,34 @@ int mysql_update(THD *thd,
thd->proc_info="end";
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
table->time_stamp=save_time_stamp; // Restore auto timestamp pointer
- using_transactions=table->file->has_transactions();
- if (updated && (error <= 0 || !using_transactions))
+ transactional_table= table->file->has_transactions();
+ log_delayed= (transactional_table || table->tmp_table);
+ if (updated && (error <= 0 || !transactional_table))
{
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
- using_transactions);
- if (mysql_bin_log.write(&qinfo) && using_transactions)
- error=1;
+ log_delayed);
+ if (mysql_bin_log.write(&qinfo) && transactional_table)
+ error=1; // Rollback update
}
- if (!using_transactions)
+ if (!log_delayed)
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
}
- if (using_transactions && ha_autocommit_or_rollback(thd, error >= 0))
- error=1;
- if (updated)
+ if (transactional_table)
+ {
+ if (ha_autocommit_or_rollback(thd, error >= 0))
+ error=1;
+ }
+ /*
+ Only invalidate the query cache if something changed or if we
+ didn't commit the transacion (query cache is automaticly
+ invalidated on commit)
+ */
+ if (updated &&
+ (!transactional_table ||
+ thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
query_cache_invalidate3(thd, table_list, 1);
}
@@ -349,10 +357,12 @@ int mysql_update(THD *thd,
Update multiple tables from join
***************************************************************************/
-multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
- enum enum_duplicates handle_duplicates, thr_lock_type lock_option_arg, uint num)
- : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs), lock_option(lock_option_arg),
- dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0) , error(0), do_update(false)
+multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
+ enum enum_duplicates handle_duplicates,
+ uint num)
+ : update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs),
+ dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0),
+ error(0), do_update(false)
{
save_time_stamps = (uint *) sql_calloc (sizeof(uint) * num_of_tables);
tmp_tables = (TABLE **)NULL;
@@ -695,7 +705,7 @@ void multi_update::send_error(uint errcode,const char *err)
int multi_update::do_updates (bool from_send_error)
{
- int error = 0, counter = 0;
+ int local_error= 0, counter= 0;
if (from_send_error)
{
@@ -720,7 +730,7 @@ int multi_update::do_updates (bool from_send_error)
TABLE *tmp_table=tmp_tables[counter];
if (tmp_table->file->extra(HA_EXTRA_NO_CACHE))
{
- error=1;
+ local_error=1;
break;
}
List<Item> list;
@@ -736,35 +746,36 @@ int multi_update::do_updates (bool from_send_error)
tmp_table->used_keys&=field->part_of_key;
}
tmp_table->used_fields=tmp_table->fields;
- error=0; list.pop(); // we get position some other way ...
- error = tmp_table->file->rnd_init(1);
- if (error)
- return error;
- while (!(error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
+ local_error=0;
+ list.pop(); // we get position some other way ...
+ local_error = tmp_table->file->rnd_init(1);
+ if (local_error)
+ return local_error;
+ while (!(local_error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
(!thd->killed || from_send_error || not_trans_safe))
{
found++;
- error= table->file->rnd_pos(table->record[0],
- (byte*) (*(tmp_table->field))->ptr);
- if (error)
- return error;
+ local_error= table->file->rnd_pos(table->record[0],
+ (byte*) (*(tmp_table->field))->ptr);
+ if (local_error)
+ return local_error;
table->status|= STATUS_UPDATED;
store_record(table,1);
- error= fill_record(*fields_by_tables[counter + 1],list) ||
- /* compare_record(table, query_id) || */
- table->file->update_row(table->record[1],table->record[0]);
- if (error)
+ local_error= (fill_record(*fields_by_tables[counter + 1],list) ||
+ /* compare_record(table, query_id) || */
+ table->file->update_row(table->record[1],table->record[0]));
+ if (local_error)
{
- table->file->print_error(error,MYF(0));
+ table->file->print_error(local_error,MYF(0));
break;
}
else
updated++;
}
- if (error == HA_ERR_END_OF_FILE)
- error = 0;
+ if (local_error == HA_ERR_END_OF_FILE)
+ local_error = 0;
}
- return error;
+ return local_error;
}
@@ -775,18 +786,18 @@ bool multi_update::send_eof()
thd->proc_info="updating the reference tables";
/* Does updates for the last n - 1 tables, returns 0 if ok */
- int error = (num_updated) ? do_updates(false) : 0; /* do_updates returns 0 if success */
+ int local_error = (num_updated) ? do_updates(false) : 0;
/* reset used flags */
#ifndef NOT_USED
update_tables->table->no_keyread=0;
#endif
- if (error == -1)
- error = 0;
- thd->proc_info="end";
- //TODO error should be sent at the query processing end
- if (error)
- send_error(error,"An error occured in multi-table update");
+ if (local_error == -1)
+ local_error= 0;
+ thd->proc_info= "end";
+ // TODO: Error should be sent at the query processing end
+ if (local_error)
+ send_error(local_error, "An error occured in multi-table update");
/*
Write the SQL statement to the binlog if we updated
@@ -798,7 +809,7 @@ bool multi_update::send_eof()
if (updated || not_trans_safe)
{
mysql_update_log.write(thd,thd->query,thd->query_length);
- Query_log_event qinfo(thd, thd->query, thd->query_length);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
/*
mysql_bin_log is not open if binlogging or replication
@@ -807,14 +818,14 @@ bool multi_update::send_eof()
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
!not_trans_safe)
- error=1; /* Log write failed: roll back the SQL statement */
+ local_error=1; /* Log write failed: roll back the SQL statement */
/* Commit or rollback the current SQL statement */
- VOID(ha_autocommit_or_rollback(thd,error > 0));
+ VOID(ha_autocommit_or_rollback(thd, local_error > 0));
}
else
- error=0; // this can happen only if it is end of file error
- if (!error) // if the above log write did not fail ...
+ local_error= 0; // this can happen only if it is end of file error
+ if (!local_error) // if the above log write did not fail ...
{
char buff[80];
sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 04aeddfc384..a994a2539f7 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -69,6 +69,7 @@ inline Item *or_or_concat(Item* A, Item* B)
enum Item_cast cast_type;
enum Item_udftype udf_type;
CHARSET_INFO *charset;
+ thr_lock_type lock_type;
interval_type interval;
}
@@ -177,7 +178,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CHARSET
%token CHECKSUM_SYM
%token CHECK_SYM
-%token CIPHER
%token COMMITTED_SYM
%token COLLATE_SYM
%token COLUMNS
@@ -234,7 +234,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token IN_SYM
%token ISOLATION
%token ISAM_SYM
-%token ISSUER
%token JOIN_SYM
%token KEYS
%token KEY_SYM
@@ -254,7 +253,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MASTER_USER_SYM
%token MASTER_LOG_FILE_SYM
%token MASTER_LOG_POS_SYM
-%token MASTER_LOG_SEQ_SYM
%token MASTER_PASSWORD_SYM
%token MASTER_PORT_SYM
%token MASTER_CONNECT_RETRY_SYM
@@ -275,10 +273,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token NEW_SYM
%token NCHAR_SYM
%token NOT
-%token NO_FOREIGN_KEY_CHECKS
%token NO_SYM
%token NULL_SYM
%token NUM
+%token OFFSET_SYM
%token ON
%token OPEN_SYM
%token OPTION
@@ -305,7 +303,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token REAL_NUM
%token REFERENCES
%token REGEXP
-%token RELAXED_UNIQUE_CHECKS
%token RELOAD
%token RENAME
%token REPEATABLE_SYM
@@ -557,7 +554,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
type int_type real_type order_dir opt_field_spec lock_option
udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_var_type opt_var_ident_type
- delete_option opt_with_if_not_exists
+ delete_option opt_temporary
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@@ -565,6 +562,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <ulonglong_number>
ulonglong_num
+%type <lock_type>
+ replace_lock_option opt_low_priority insert_lock_option load_data_lock
+
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
@@ -636,17 +636,18 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
field_opt_list opt_binary table_lock_list table_lock varchar
ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use
opt_delete_options opt_delete_option
- opt_outer table_list table_name opt_option opt_place opt_low_priority
+ opt_outer table_list table_name opt_option opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges opt_table user_list grant_option
grant_privilege grant_privilege_list
- flush_options flush_option insert_lock_option replace_lock_option
+ flush_options flush_option
equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
- single_multi table_wild_list table_wild_one opt_wild union union_list
- precision union_option opt_on_delete_item subselect_start opt_and
+ single_multi table_wild_list table_wild_one opt_wild
+ union opt_union union_list union_option
+ precision opt_on_delete_item subselect_start opt_and
subselect_end select_var_list select_var_list_init help opt_len
END_OF_INPUT
@@ -730,7 +731,7 @@ change:
{
LEX *lex = Lex;
lex->sql_command = SQLCOM_CHANGE_MASTER;
- memset(&lex->mi, 0, sizeof(lex->mi));
+ bzero((char*) &lex->mi, sizeof(lex->mi));
} master_defs;
master_defs:
@@ -887,10 +888,6 @@ opt_if_not_exists:
/* empty */ { $$= 0; }
| IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
-opt_with_if_not_exists:
- /* empty */ { $$= 0; }
- | WITH IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
-
opt_create_table_options:
/* empty */
| create_table_options;
@@ -1461,20 +1458,24 @@ opt_to:
| EQ {}
| AS {};
+/*
+ The first two deprecate the last two--delete the last two for 4.1 release
+*/
+
slave:
START_SYM SLAVE slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_START;
- lex->type = 0;
- }
- |
- STOP_SYM SLAVE slave_thread_opts
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_SLAVE_STOP;
- lex->type = 0;
- };
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_START;
+ lex->type = 0;
+ }
+ | STOP_SYM SLAVE slave_thread_opts
+ {
+ LEX *lex=Lex;
+ lex->sql_command = SQLCOM_SLAVE_STOP;
+ lex->type = 0;
+ }
+ ;
slave_thread_opts:
slave_thread_opt
@@ -2490,15 +2491,24 @@ opt_table_alias:
where_clause:
/* empty */ { Select->select_lex()->where= 0; }
- | WHERE expr { Select->select_lex()->where= $2; };
+ | WHERE expr
+ {
+ Select->select_lex()->where= $2;
+ if ($2)
+ $2->top_level_item();
+ }
+ ;
having_clause:
/* empty */
| HAVING { Select->select_lex()->create_refs= 1; } expr
- {
- SELECT_LEX *sel= Select->select_lex();
- sel->having= $3; sel->create_refs=0;
- };
+ {
+ SELECT_LEX *sel= Select->select_lex();
+ sel->having= $3; sel->create_refs=0;
+ if ($3)
+ $3->top_level_item();
+ }
+ ;
opt_escape:
ESCAPE_SYM TEXT_STRING { $$= $2.str; }
@@ -2563,11 +2573,6 @@ order_clause:
ORDER_SYM BY
{
LEX *lex=Lex;
- if (lex->sql_command == SQLCOM_MULTI_UPDATE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "UPDATE", "ORDER BY");
- YYABORT;
- }
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
lex->current_select->select_lex()->olap !=
UNSPECIFIED_OLAP_TYPE)
@@ -2593,7 +2598,7 @@ order_dir:
limit_clause:
/* empty */ {}
- | LIMIT ULONG_NUM
+ | LIMIT
{
LEX *lex= Lex;
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
@@ -2604,35 +2609,36 @@ limit_clause:
"LIMIT");
YYABORT;
}
+ }
+ limit_options
+ ;
+
+limit_options:
+ ULONG_NUM
+ {
+ SELECT_LEX_NODE *sel= Select;
+ sel->select_limit= $1;
+ sel->offset_limit= 0L;
+ }
+ | ULONG_NUM ',' ULONG_NUM
+ {
SELECT_LEX_NODE *sel= Select;
- sel->select_limit= $2;
- sel->offset_limit= 0L;
+ sel->select_limit= $3;
+ sel->offset_limit= $1;
}
- | LIMIT ULONG_NUM ',' ULONG_NUM
+ | ULONG_NUM OFFSET_SYM ULONG_NUM
{
- LEX *lex=Lex;
- if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->select_lex()->olap !=
- UNSPECIFIED_OLAP_TYPE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP",
- "LIMIT");
- YYABORT;
- }
- SELECT_LEX_NODE *sel= lex->current_select;
- sel->select_limit= $4;
- sel->offset_limit= $2;
- };
+ SELECT_LEX_NODE *sel= Select;
+ sel->select_limit= $1;
+ sel->offset_limit= $3;
+ }
+ ;
+
delete_limit_clause:
/* empty */
{
LEX *lex=Lex;
- if (lex->sql_command == SQLCOM_MULTI_UPDATE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "DELETE", "LIMIT");
- YYABORT;
- }
lex->current_select->select_limit= HA_POS_ERROR;
}
| LIMIT ulonglong_num
@@ -2754,11 +2760,12 @@ do: DO_SYM
*/
drop:
- DROP TABLE_SYM if_exists table_list opt_restrict
+ DROP opt_temporary TABLE_SYM if_exists table_list opt_restrict
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DROP_TABLE;
- lex->drop_if_exists = $3;
+ lex->drop_temporary= $2;
+ lex->drop_if_exists= $4;
}
| DROP INDEX ident ON table_ident {}
{
@@ -2795,14 +2802,25 @@ table_name:
if_exists:
/* empty */ { $$=0; }
- | IF EXISTS { $$= 1; };
+ | IF EXISTS { $$= 1; }
+ ;
+opt_temporary:
+ /* empty */ { $$= 0; }
+ | TEMPORARY { $$= 1; }
+ ;
/*
** Insert : add new data to table
*/
insert:
- INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option opt_ignore insert2 insert_field_spec;
+ INSERT { Lex->sql_command = SQLCOM_INSERT; } insert_lock_option
+ opt_ignore insert2
+ {
+ set_lock_for_tables($3);
+ }
+ insert_field_spec
+ ;
replace:
REPLACE
@@ -2811,17 +2829,23 @@ replace:
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
}
- replace_lock_option insert2 insert_field_spec;
+ replace_lock_option insert2
+ {
+ set_lock_for_tables($3);
+ }
+ insert_field_spec
+ ;
insert_lock_option:
- /* empty */ { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; }
- | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; }
- | HIGH_PRIORITY { Lex->lock_option= TL_WRITE; };
+ /* empty */ { $$= TL_WRITE_CONCURRENT_INSERT; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }
+ | DELAYED_SYM { $$= TL_WRITE_DELAYED; }
+ | HIGH_PRIORITY { $$= TL_WRITE; }
+ ;
replace_lock_option:
- opt_low_priority {}
- | DELAYED_SYM { Lex->lock_option= TL_WRITE_DELAYED; };
+ opt_low_priority { $$= $1; }
+ | DELAYED_SYM { $$= TL_WRITE_DELAYED; };
insert2:
INTO insert_table {}
@@ -2867,7 +2891,7 @@ insert_values:
mysql_init_select(lex);
}
select_options select_item_list select_from select_lock_type
- union {};
+ opt_union {};
values_list:
values_list ',' no_braces
@@ -2940,7 +2964,12 @@ update:
lex->sql_command= SQLCOM_UPDATE;
lex->select_lex.init_order();
}
- opt_low_priority opt_ignore join_table_list SET update_list where_clause opt_order_clause delete_limit_clause;
+ opt_low_priority opt_ignore join_table_list
+ SET update_list where_clause opt_order_clause delete_limit_clause
+ {
+ set_lock_for_tables($3);
+ }
+ ;
update_list:
update_list ',' simple_ident equal expr
@@ -2955,8 +2984,8 @@ update_list:
};
opt_low_priority:
- /* empty */ { Lex->lock_option= current_thd->update_lock_default; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; };
+ /* empty */ { $$= current_thd->update_lock_default; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
/* Delete rows from a table */
@@ -2969,13 +2998,20 @@ delete:
lex->lock_option= lex->thd->update_lock_default;
lex->select_lex.init_order();
}
- opt_delete_options single_multi {};
+ opt_delete_options single_multi {}
+ ;
single_multi:
- FROM table_name where_clause opt_order_clause delete_limit_clause {}
+ FROM table_ident
+ {
+ if (!add_table_to_list($2, NULL, 1, Lex->lock_option))
+ YYABORT;
+ }
+ where_clause opt_order_clause
+ delete_limit_clause
| table_wild_list
{ mysql_init_multi_delete(Lex); }
- FROM join_table_list where_clause
+ FROM join_table_list where_clause
| FROM table_wild_list
{ mysql_init_multi_delete(Lex); }
USING join_table_list where_clause;
@@ -2985,18 +3021,19 @@ table_wild_list:
| table_wild_list ',' table_wild_one {};
table_wild_one:
- ident opt_wild
- {
- if (!Select->add_table_to_list(new Table_ident($1), NULL, 1,
- TL_WRITE))
- YYABORT;
- }
- | ident '.' ident opt_wild
- {
- if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL,
- 1, TL_WRITE))
+ ident opt_wild
+ {
+ if (!Select->add_table_to_list(new Table_ident($1), NULL, 1,
+ Lex->lock_option))
+ YYABORT;
+ }
+ | ident '.' ident opt_wild
+ {
+ if (!Select->add_table_to_list(new Table_ident($1, $3, 0), NULL, 1,
+ Lex->lock_option))
YYABORT;
- };
+ }
+ ;
opt_wild:
/* empty */ {}
@@ -3018,7 +3055,8 @@ truncate:
lex->sql_command= SQLCOM_TRUNCATE;
lex->select_lex.options= 0;
lex->select_lex.init_order();
- lex->lock_option= lex->thd->update_lock_default; };
+ }
+ ;
opt_table_sym:
/* empty */
@@ -3145,7 +3183,7 @@ show_param:
lex->grant_user=$3;
lex->grant_user->password.str=NullS;
}
- | CREATE DATABASE opt_with_if_not_exists ident
+ | CREATE DATABASE opt_if_not_exists ident
{
Lex->sql_command=SQLCOM_SHOW_CREATE_DB;
Lex->create_info.options=$3;
@@ -3310,7 +3348,8 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_LOAD;
- lex->local_file= $4;
+ lex->lock_option= $3;
+ lex->local_file= $4;
if (!(lex->exchange= new sql_exchange($6.str,0)))
YYABORT;
lex->field_list.empty();
@@ -3340,9 +3379,9 @@ opt_local:
| LOCAL_SYM { $$=1;};
load_data_lock:
- /* empty */ { Lex->lock_option= current_thd->update_lock_default; }
- | CONCURRENT { Lex->lock_option= TL_WRITE_CONCURRENT_INSERT ; }
- | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; };
+ /* empty */ { $$= current_thd->update_lock_default; }
+ | CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; }
+ | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; };
opt_duplicate:
@@ -3485,12 +3524,13 @@ ident:
IDENT { $$=$1; }
| keyword
{
- LEX *lex;
- $$.str=sql_strmake($1.str,$1.length);
+ LEX *lex= Lex;
+ $$.str= lex->thd->strmake($1.str,$1.length);
$$.length=$1.length;
- if ((lex=Lex)->next_state != STATE_END)
+ if (lex->next_state != STATE_END)
lex->next_state=STATE_OPERATOR_OR_IDENT;
- };
+ }
+ ;
ident_or_text:
ident { $$=$1;}
@@ -3613,6 +3653,7 @@ keyword:
| NEW_SYM {}
| NO_SYM {}
| NONE_SYM {}
+ | OFFSET_SYM {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
@@ -4198,7 +4239,7 @@ rollback:
*/
-union:
+opt_union:
/* empty */ {}
| union_list;
@@ -4225,11 +4266,14 @@ union_list:
;
union_opt:
- union {}
+ union_list {}
| optional_order_or_limit {};
optional_order_or_limit:
- /* empty */ {}
+ /* empty
+ intentional reduce/reduce conflict here !!!
+ { code } below should not be executed
+ when neither ORDER BY nor LIMIT are used */ {}
|
{
LEX *lex=Lex;
diff --git a/sql/stacktrace.c b/sql/stacktrace.c
index 1aba73dda33..f5c0a59b572 100644
--- a/sql/stacktrace.c
+++ b/sql/stacktrace.c
@@ -206,7 +206,7 @@ resolve it\n");
/* Produce a core for the thread */
-#ifdef HAVE_LINUXTHREADS
+#ifdef NOT_USED /* HAVE_LINUXTHREADS */
void write_core(int sig)
{
signal(sig, SIG_DFL);
diff --git a/sql/table.cc b/sql/table.cc
index bad453f2cad..84a072c886d 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -95,15 +95,15 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
if (my_read(file,(byte*) head,64,MYF(MY_NABP))) goto err_not_open;
if (head[0] != (uchar) 254 || head[1] != 1 ||
- (head[2] < FRM_VER && head[2] > FRM_VER+2))
- goto err_not_open; /* purecov: inspected */
+ (head[2] != FRM_VER && head[2] > FRM_VER+2))
+ goto err_not_open; /* purecov: inspected */
new_field_pack_flag=head[27];
new_frm_ver= (head[2] - FRM_VER);
field_pack_length= new_frm_ver < 2 ? 11 : 15;
error=3;
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
- goto err_not_open; /* purecov: inspected */
+ goto err_not_open; /* purecov: inspected */
*fn_ext(index_file)='\0'; // Remove .frm extension
outparam->db_type=ha_checktype((enum db_type) (uint) *(head+3));
@@ -145,7 +145,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
goto err_not_open; /* purecov: inspected */
bzero((char*) keyinfo,n_length);
outparam->key_info=keyinfo;
- outparam->max_key_length=0;
+ outparam->max_key_length= outparam->total_key_length= 0;
key_part= (KEY_PART_INFO*) (keyinfo+keys);
strpos=disk_buff+6;
@@ -203,11 +203,13 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
}
set_if_bigger(outparam->max_key_length,keyinfo->key_length+
keyinfo->key_parts);
+ outparam->total_key_length+= keyinfo->key_length;
if (keyinfo->flags & HA_NOSAME)
set_if_bigger(outparam->max_unique_length,keyinfo->key_length);
}
keynames=(char*) key_part;
strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;
+
outparam->reclength = uint2korr((head+16));
if (*(head+26) == 1)
outparam->system=1; /* one-record-database */
@@ -391,6 +393,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
(TYPELIB*) 0),
outparam->fieldnames.type_names[i],
outparam);
+ if (!reg_field) // Not supported field type
+ {
+ error= 4;
+ goto err_not_open; /* purecov: inspected */
+ }
reg_field->comment=comment;
reg_field->set_charset(charset);
if (!(reg_field->flags & NOT_NULL_FLAG))
diff --git a/sql/table.h b/sql/table.h
index d09194442c8..18079e183ce 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -58,6 +58,7 @@ struct st_table {
uint reclength; /* Recordlength */
uint rec_buff_length;
uint keys,key_parts,primary_key,max_key_length,max_unique_length;
+ uint total_key_length;
uint uniques;
uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */
diff --git a/strings/Makefile.am b/strings/Makefile.am
index 917183320e0..e53ff21cdf8 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -24,11 +24,11 @@ if ASSEMBLER_x86
ASRCS = strings-x86.s longlong2str-x86.s
CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c
else
-if ASSEMBLER_sparc
+if ASSEMBLER_sparc32
# These file MUST all be on the same line!! Otherwise automake
# generats a very broken makefile
-ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s strxmov-sparc.s
-CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c
+ASRCS = bmove_upp-sparc.s strappend-sparc.s strend-sparc.s strinstr-sparc.s strmake-sparc.s strmov-sparc.s strnmov-sparc.s strstr-sparc.s
+CSRCS = strcont.c strfill.c strcend.c is_prefix.c longlong2str.c bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c atof.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c strxmov.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-latin1_de.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-win1250ch.c ctype-bin.c
else
#no assembler
ASRCS =
@@ -68,8 +68,11 @@ conf_to_src_LDFLAGS= @NOINST_LDFLAGS@
if ASSEMBLER
# On Linux gcc can compile the assembly files
%.o : %.s
- $(AS) -o $@ $<
+ $(AS) $(ASFLAGS) -o $@ $<
endif
+str_test: str_test.c $(LIBRARIES)
+ $(LINK) $(FLAGS) -DMAIN $(srcdir)/str_test.c $(LDADD) $(LIBS)
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/strings/bmove_upp-sparc.s b/strings/bmove_upp-sparc.s
index 4fae7f5cc7c..f38c391f8ab 100644
--- a/strings/bmove_upp-sparc.s
+++ b/strings/bmove_upp-sparc.s
@@ -27,11 +27,11 @@ bmove_upp:
nop
.loop:
sub %o1, 1, %o1
- ldub [%o1], %g2
+ ldub [%o1], %o3
sub %o0, 1, %o0
subcc %o2, 1, %o2
bcc .loop
- stb %g2, [%o0]
+ stb %o3, [%o0]
.end:
retl
nop
diff --git a/strings/do_ctype.c b/strings/do_ctype.c
index 14ede6891da..f51770e3633 100644
--- a/strings/do_ctype.c
+++ b/strings/do_ctype.c
@@ -145,7 +145,7 @@ void init_case_convert()
higher_pos= (uchar * ) "\217\216\231\232\220"; /* Extra chars to konv. */
lower_pos= (uchar * ) "\206\204\224\201\202";
#else
-#if defined(HPUX) && ASCII_BITS_USED == 8
+#if defined(HPUX10) && ASCII_BITS_USED == 8
higher_pos= (uchar * ) "\xd0\xd8\xda\xdb\xdc\xd3";
lower_pos= (uchar * ) "\xd4\xcc\xce\xdf\xc9\xd7";
#else
@@ -160,7 +160,7 @@ void init_case_convert()
lower_pos= (uchar * ) "{}|`~";
#endif
#endif /* USE_INTERNAL_CTYPE */
-#endif /* HPUX */
+#endif /* HPUX10 */
#endif /* MSDOS */
while (*higher_pos)
@@ -176,7 +176,7 @@ void init_case_convert()
higher_pos= (uchar *) "\217\216\231\232\220";
lower_pos= (uchar *) "\216\217\231YE";
#else
-#if defined(HPUX) && ASCII_BITS_USED == 8
+#if defined(HPUX10) && ASCII_BITS_USED == 8
higher_pos= lower_pos= (uchar *) ""; /* Tecknen i r{tt ordning */
#else
#ifdef USE_ISO_8859_1 /* As in USG5 ICL-386 */
@@ -186,7 +186,7 @@ void init_case_convert()
higher_pos= (uchar *) "][\\~`"; /* R{tt ordning p} tecknen */
lower_pos= (uchar *) "[\\]YE"; /* Ordning enligt ascii */
#endif /* USE_ISO_8859_1 */
-#endif /* HPUX */
+#endif /* HPUX10 */
#endif /* MSDOS */
while (*higher_pos)
diff --git a/strings/str_test.c b/strings/str_test.c
index bef48814f6d..0c3ff471ad7 100644
--- a/strings/str_test.c
+++ b/strings/str_test.c
@@ -130,9 +130,6 @@ int main(void)
if (errors)
fputs("--- Some functions doesn't work!! Fix them\n",stderr);
return(errors > 0);
-
- fputs("Fatal error\n",stderr);
- return(2);
} /* main */
diff --git a/strings/strappend-sparc.s b/strings/strappend-sparc.s
index 69bb555aa47..30b621c3fce 100644
--- a/strings/strappend-sparc.s
+++ b/strings/strappend-sparc.s
@@ -22,28 +22,28 @@
.type strappend,#function
.proc 020
strappend:
- add %o0, %o1, %g3 ! g3 = endpos
- ldsb [%o0], %g2
+ add %o0, %o1, %o3 ! o3 = endpos
+ ldsb [%o0], %o4
.loop1:
add %o0, 1, %o0 ! find end of str
- cmp %g2, 0
+ cmp %o4, 0
bne,a .loop1
- ldsb [%o0], %g2
+ ldsb [%o0], %o4
sub %o0, 1, %o0
- cmp %o0, %g3
+ cmp %o0, %o3
bgeu .end
nop
stb %o2, [%o0]
.loop2:
add %o0, 1, %o0
- cmp %o0, %g3
+ cmp %o0, %o3
blu,a .loop2
stb %o2, [%o0]
.end:
retl
- stb %g0, [%g3]
+ stb %g0, [%o3]
.strappend_end:
.size strappend,.strappend_end-strappend
.ident "Matt Wagner & Monty"
diff --git a/strings/strend-sparc.s b/strings/strend-sparc.s
index fd1dba4d36f..0f19f6a435a 100644
--- a/strings/strend-sparc.s
+++ b/strings/strend-sparc.s
@@ -22,12 +22,12 @@
.type strend,#function
.proc 0102
strend:
- ldsb [%o0], %g2 ! Handle first char differently to make
+ ldsb [%o0], %o3 ! Handle first char differently to make
.loop: ! a faster loop
add %o0, 1, %o0
- cmp %g2, 0
+ cmp %o3, 0
bne,a .loop
- ldsb [%o0], %g2
+ ldsb [%o0], %o3
retl
sub %o0,1,%o0
.strend_end:
diff --git a/strings/strmake-sparc.s b/strings/strmake-sparc.s
index 9fe72a9f9a2..4effe95774e 100644
--- a/strings/strmake-sparc.s
+++ b/strings/strmake-sparc.s
@@ -25,16 +25,16 @@ strmake:
orcc %g0,%o2,%g0
be,a .end
nop
- ldsb [%o1],%g2
+ ldsb [%o1],%o3
.loop:
- stb %g2,[%o0]
- cmp %g2,0
+ stb %o3,[%o0]
+ cmp %o3,0
be .end ! Jump to end on end of string
add %o1,1,%o1
add %o0,1,%o0
subcc %o2,1,%o2
bne,a .loop
- ldsb [%o1],%g2
+ ldsb [%o1],%o3
.end:
retl
stb %g0,[%o0]
diff --git a/strings/strmov-sparc.s b/strings/strmov-sparc.s
index 6114b0bf6e2..3536685b47b 100644
--- a/strings/strmov-sparc.s
+++ b/strings/strmov-sparc.s
@@ -23,10 +23,10 @@
.proc 0102
strmov:
.loop:
- ldub [%o1], %g2
- stb %g2, [%o0]
+ ldub [%o1], %o3
+ stb %o3, [%o0]
add %o1, 1, %o1
- cmp %g2, 0
+ cmp %o3, 0
bne,a .loop
add %o0, 1, %o0
retl
diff --git a/strings/strnmov-sparc.s b/strings/strnmov-sparc.s
index 2dfcb95ab76..f681318f410 100644
--- a/strings/strnmov-sparc.s
+++ b/strings/strnmov-sparc.s
@@ -25,16 +25,16 @@ strnmov:
orcc %g0,%o2,%g0
be,a .end
nop
- ldsb [%o1],%g2
+ ldsb [%o1],%o3
.loop:
- stb %g2,[%o0]
- cmp %g2,0
+ stb %o3,[%o0]
+ cmp %o3,0
be .end ! Jump to end on end of string
add %o1,1,%o1
add %o0,1,%o0
subcc %o2,1,%o2
bne,a .loop
- ldsb [%o1],%g2
+ ldsb [%o1],%o3
.end:
retl
nop
diff --git a/strings/strstr-sparc.s b/strings/strstr-sparc.s
index 1263236f107..eb658e9f7f0 100644
--- a/strings/strstr-sparc.s
+++ b/strings/strstr-sparc.s
@@ -33,10 +33,10 @@ strstr:
ldsb [%o1],%o2 ! o2= First char of search
.top:
- ldsb [%o0],%g3 ! g3= First char of rest of str
- cmp %g3,0
+ ldsb [%o0],%o4 ! o4= First char of rest of str
+ cmp %o4,0
be .abort ! Found end null ;
- cmp %g3,%o2
+ cmp %o4,%o2
bne .top
add %o0,1,%o0
@@ -45,20 +45,20 @@ strstr:
! while (*j)
! if (*i++ != *j++) goto skipp;
- or %g0,%o0,%g2
- add %o1,1,%g3 ! g3= search+1
+ or %g0,%o0,%o3
+ add %o1,1,%o4 ! o4= search+1
ldsb [%o0],%o5 ! o5= [current_str+1]
.loop2:
- ldsb [%g3],%g4
- add %g3,1,%g3
+ ldsb [%o4],%g4
+ add %o4,1,%o4
cmp %g4,0
be .end
cmp %o5,%g4
bne .top
- add %g2,1,%g2
+ add %o3,1,%o3
ba .loop2
- ldsb [%g2],%o5
+ ldsb [%o3],%o5
.end:
retl
diff --git a/strings/strxmov-sparc.s b/strings/strxmov-sparc.s
index e65b56d317d..b4ca531d2e4 100644
--- a/strings/strxmov-sparc.s
+++ b/strings/strxmov-sparc.s
@@ -15,12 +15,17 @@
! Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
! MA 02111-1307, USA
+!
+! Note that this function only works on 32 bit sparc systems
+! on 64 bits the offsets to %sp are different !
+
.file "strxmov-sparc.s"
.section ".text"
.align 4
.global strxmov
.type strxmov,#function
.proc 0102
+
strxmov:
st %o2, [%sp+76] ! store 3rd param before other params
st %o3, [%sp+80] ! store 4th param " "
@@ -28,18 +33,18 @@ strxmov:
st %o4, [%sp+84] ! store 5th param
be .end
st %o5, [%sp+88] ! store last
- add %sp, 76, %g2 ! put pointer to 3rd arg
+ add %sp, 76, %o4 ! put pointer to 3rd arg
.loop:
- ldub [%o1], %g1 ! set values of src (o1)
+ ldub [%o1], %o5 ! set values of src (o1)
add %o1, 1, %o1 ! inc src
- stb %g1, [%o0] ! and dst (o2) equal
- cmp %g1, 0 ! second while cmp
+ stb %o5, [%o0] ! and dst (o2) equal
+ cmp %o5, 0 ! second while cmp
bne,a .loop
add %o0, 1, %o0 ! inc dst
- ld [%g2], %o1 ! get next param
+ ld [%o4], %o1 ! get next param
cmp %o1, 0 ! check if last param
bne .loop
- add %g2, 4, %g2 ! advance to next param
+ add %o4, 4, %o4 ! advance to next param
.end:
retl
stb %g0, [%o0]
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index 7493fd29856..139bbb3fd6b 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -5,7 +5,7 @@
# Mysql daemon start/stop script.
# Usually this is put in /etc/init.d (at least on machines SYSV R4 based
-# systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/S01mysql.
+# systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql.
# When this is done the mysql server will be started when the machine is
# started and shut down when the systems goes down.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 241caf74465..4935b6cd95a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -24,7 +24,7 @@ EXTRA_DIST = auto_increment.res auto_increment.tst \
insert_and_repair.pl \
grant.pl grant.res test_delayed_insert.pl \
pmail.pl mail_to_db.pl table_types.pl \
- udf_test udf_test.res
+ udf_test udf_test.res myisam-big-rows.tst
#
# C Test for 4.1 protocol
diff --git a/vio/viossl.c b/vio/viossl.c
index 56d3da8a1ac..cf1c98b5382 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -249,35 +249,48 @@ void vio_ssl_in_addr(Vio *vio, struct in_addr *in)
/*
- TODO: Add documentation and error handling
+ TODO: Add documentation
*/
-void sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
+int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
{
char *str;
char buf[1024];
X509* client_cert;
my_bool unused;
+ my_bool net_blocking;
+ enum enum_vio_type old_type;
DBUG_ENTER("sslaccept");
DBUG_PRINT("enter", ("sd=%d ptr=%p", vio->sd,ptr));
+ old_type= vio->type;
+ net_blocking = vio_is_blocking(vio);
vio_blocking(vio, 1, &unused); /* Must be called before reset */
vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE);
vio->ssl_=0;
- vio->open_=FALSE;
if (!(vio->ssl_ = SSL_new(ptr->ssl_context_)))
{
DBUG_PRINT("error", ("SSL_new failure"));
report_errors();
- DBUG_VOID_RETURN;
+ vio_reset(vio, old_type,vio->sd,0,FALSE);
+ vio_blocking(vio, net_blocking, &unused);
+ DBUG_RETURN(1);
}
DBUG_PRINT("info", ("ssl_=%p timeout=%ld",vio->ssl_, timeout));
SSL_clear(vio->ssl_);
SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
SSL_set_fd(vio->ssl_,vio->sd);
SSL_set_accept_state(vio->ssl_);
- SSL_do_handshake(vio->ssl_);
- vio->open_ = TRUE;
+ if (SSL_do_handshake(vio->ssl_) < 1)
+ {
+ DBUG_PRINT("error", ("SSL_do_handshake failure"));
+ report_errors();
+ SSL_free(vio->ssl_);
+ vio->ssl_=0;
+ vio_reset(vio, old_type,vio->sd,0,FALSE);
+ vio_blocking(vio, net_blocking, &unused);
+ DBUG_RETURN(1);
+ }
#ifndef DBUF_OFF
DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'"
,SSL_get_cipher_name(vio->ssl_)));
@@ -309,7 +322,7 @@ void sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
}
#endif
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
@@ -318,17 +331,22 @@ int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
char *str;
X509* server_cert;
my_bool unused;
+ my_bool net_blocking;
+ enum enum_vio_type old_type;
DBUG_ENTER("sslconnect");
DBUG_PRINT("enter", ("sd=%d ptr=%p ctx: %p", vio->sd,ptr,ptr->ssl_context_));
+ old_type= vio->type;
+ net_blocking = vio_is_blocking(vio);
vio_blocking(vio, 1, &unused); /* Must be called before reset */
vio_reset(vio,VIO_TYPE_SSL,vio->sd,0,FALSE);
vio->ssl_=0;
- vio->open_=FALSE;
if (!(vio->ssl_ = SSL_new(ptr->ssl_context_)))
{
DBUG_PRINT("error", ("SSL_new failure"));
report_errors();
+ vio_reset(vio, old_type,vio->sd,0,FALSE);
+ vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
DBUG_PRINT("info", ("ssl_=%p timeout=%ld",vio->ssl_, timeout));
@@ -336,8 +354,16 @@ int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
SSL_set_fd (vio->ssl_, vio->sd);
SSL_set_connect_state(vio->ssl_);
- SSL_do_handshake(vio->ssl_);
- vio->open_ = TRUE;
+ if (SSL_do_handshake(vio->ssl_) < 1)
+ {
+ DBUG_PRINT("error", ("SSL_do_handshake failure"));
+ report_errors();
+ SSL_free(vio->ssl_);
+ vio->ssl_=0;
+ vio_reset(vio, old_type,vio->sd,0,FALSE);
+ vio_blocking(vio, net_blocking, &unused);
+ DBUG_RETURN(1);
+ }
#ifndef DBUG_OFF
DBUG_PRINT("info",("SSL_get_cipher_name() = '%s'"
,SSL_get_cipher_name(vio->ssl_)));
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 9e7a1475951..31bc457d1ae 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -93,7 +93,10 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
{
DBUG_PRINT("error",("unable to get certificate from '%s'\n",cert_file));
/* FIX stderr */
+ fprintf(stderr,"Error when connection to server using SSL:");
ERR_print_errors_fp(stderr);
+ fprintf(stderr,"Unable to get certificate from '%s'\n", cert_file);
+ fflush(stderr);
DBUG_RETURN(0);
}
if (key_file == NULL)
@@ -103,7 +106,10 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
{
DBUG_PRINT("error", ("unable to get private key from '%s'\n",key_file));
/* FIX stderr */
+ fprintf(stderr,"Error when connection to server using SSL:");
ERR_print_errors_fp(stderr);
+ fprintf(stderr,"Unable to get private key from '%s'\n", cert_file);
+ fflush(stderr);
DBUG_RETURN(0);
}