summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@narttu.mysql.fi>2003-05-19 16:35:49 +0300
committerunknown <monty@narttu.mysql.fi>2003-05-19 16:35:49 +0300
commitdaac922bc306847581b9acee4bcf0a31707d72e7 (patch)
tree6025913cf3d482ba0783bf3420f7341c10cd574a
parent7c189b0dcf26ad8e408b8eaa7d69dbbe913ba421 (diff)
parent68aa31f268660db07b634f021716ecb872e19679 (diff)
downloadmariadb-git-daac922bc306847581b9acee4bcf0a31707d72e7.tar.gz
Merge with 4.0.13
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union BUILD/SETUP.sh: Auto merged BitKeeper/deleted/.del-libmysql.def~29fc6d70335f1c4c: Auto merged Makefile.am: Auto merged acinclude.m4: Auto merged BitKeeper/triggers/post-commit: Auto merged Build-tools/Do-compile: Auto merged VC++Files/libmysql/libmysql.dsp: Auto merged VC++Files/mysql.dsw: Auto merged client/mysql.cc: Auto merged client/mysqlbinlog.cc: Auto merged client/mysqldump.c: Auto merged include/config-win.h: Auto merged include/my_base.h: Auto merged include/my_global.h: Auto merged include/my_pthread.h: Auto merged include/my_sys.h: Auto merged include/violite.h: Auto merged innobase/buf/buf0flu.c: Auto merged innobase/buf/buf0lru.c: Auto merged innobase/include/buf0buf.h: Auto merged innobase/include/buf0lru.h: Auto merged innobase/include/row0mysql.h: Auto merged innobase/include/srv0srv.h: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/log/log0log.c: Auto merged innobase/log/log0recv.c: Auto merged innobase/os/os0file.c: Auto merged innobase/row/row0mysql.c: Auto merged innobase/row/row0sel.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/srv/srv0start.c: Auto merged innobase/trx/trx0sys.c: Auto merged innobase/trx/trx0trx.c: Auto merged innobase/ut/ut0ut.c: Auto merged myisam/ft_boolean_search.c: Auto merged myisam/mi_check.c: Auto merged myisam/mi_key.c: Auto merged myisam/mi_open.c: Auto merged myisam/mi_range.c: Auto merged myisam/mi_search.c: Auto merged myisam/sort.c: Auto merged mysql-test/r/delete.result: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/innodb_handler.result: Auto merged mysql-test/r/join.result: Auto merged mysql-test/r/join_outer.result: Auto merged mysql-test/r/key.result: Auto merged mysql-test/r/multi_update.result: Auto merged mysql-test/r/myisam.result: Auto merged mysql-test/r/query_cache.result: Auto merged mysql-test/r/select.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/t/alter_table.test: Auto merged mysql-test/t/ctype_latin1_de.test: Auto merged mysql-test/t/delete.test: Auto merged mysql-test/t/fulltext.test: Auto merged mysql-test/t/innodb_handler.test: Auto merged mysql-test/t/join.test: Auto merged mysql-test/t/join_outer.test: Auto merged mysql-test/t/key.test: Auto merged mysql-test/t/multi_update.test: Auto merged mysql-test/t/myisam.test: Auto merged mysql-test/t/query_cache.test: Auto merged mysql-test/t/repair.test: Auto merged mysql-test/t/select_safe.test: Auto merged mysql-test/t/type_decimal.test: Auto merged mysql-test/t/variables.test: Auto merged mysys/default.c: Auto merged mysys/my_pthread.c: Auto merged scripts/mysql_fix_privilege_tables.sh: Auto merged scripts/mysqld_safe.sh: Auto merged sql/ha_heap.h: Auto merged sql/ha_innodb.h: Auto merged sql/ha_myisam.cc: Auto merged sql/handler.cc: Auto merged sql/handler.h: Auto merged sql/init.cc: Auto merged sql/item.cc: Auto merged sql/item_create.cc: Auto merged sql/item_strfunc.cc: Auto merged sql/item_sum.cc: Auto merged sql/mini_client.cc: Auto merged sql/net_serv.cc: Auto merged sql/opt_range.cc: Auto merged sql/records.cc: Auto merged sql/slave.cc: Auto merged sql/sql_acl.h: Auto merged sql/sql_analyse.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_list.h: Auto merged sql/sql_load.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/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-ny/errmsg.txt: Auto merged sql/share/norwegian/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/unireg.h: Auto merged sql-bench/crash-me.sh: Auto merged sql-bench/test-transactions.sh: Auto merged strings/ctype-tis620.c: Auto merged tests/grant.res: Auto merged sql/log_event.cc: Merge with 4.0.13 Cleaned up comment syntax
-rw-r--r--.bzrignore13
-rw-r--r--BUILD/SETUP.sh4
-rw-r--r--BitKeeper/etc/logging_ok3
-rwxr-xr-xBuild-tools/Do-compile6
-rw-r--r--Docs/Makefile.am5
-rw-r--r--Docs/internals.texi1784
-rw-r--r--Docs/manual_toc.html9
-rw-r--r--Images/.cvsignore1
-rw-r--r--VC++Files/libmysql/libmysql.dsp10
-rw-r--r--VC++Files/mysql.dsw3
-rw-r--r--acinclude.m42
-rw-r--r--client/mysql.cc29
-rw-r--r--client/mysqlbinlog.cc4
-rw-r--r--client/mysqldump.c2
-rw-r--r--configure.in22
-rw-r--r--include/Makefile.am2
-rw-r--r--include/config-win.h3
-rw-r--r--include/my_base.h1
-rw-r--r--include/my_global.h8
-rw-r--r--include/my_pthread.h5
-rw-r--r--include/my_semaphore.h5
-rw-r--r--include/my_sys.h1
-rw-r--r--include/violite.h4
-rw-r--r--innobase/btr/Makefile.am2
-rw-r--r--innobase/buf/Makefile.am2
-rw-r--r--innobase/buf/buf0buf.c36
-rw-r--r--innobase/buf/buf0flu.c53
-rw-r--r--innobase/buf/buf0lru.c58
-rw-r--r--innobase/com/Makefile.am2
-rw-r--r--innobase/data/Makefile.am2
-rw-r--r--innobase/dict/Makefile.am2
-rw-r--r--innobase/dict/dict0crea.c8
-rw-r--r--innobase/dict/dict0dict.c679
-rw-r--r--innobase/dict/dict0load.c39
-rw-r--r--innobase/dyn/Makefile.am2
-rw-r--r--innobase/eval/Makefile.am2
-rw-r--r--innobase/fil/Makefile.am2
-rw-r--r--innobase/fsp/Makefile.am2
-rw-r--r--innobase/fut/Makefile.am2
-rw-r--r--innobase/ha/Makefile.am2
-rw-r--r--innobase/ibuf/Makefile.am2
-rw-r--r--innobase/ibuf/ibuf0ibuf.c13
-rw-r--r--innobase/include/Makefile.i2
-rw-r--r--innobase/include/buf0buf.h7
-rw-r--r--innobase/include/buf0lru.h25
-rw-r--r--innobase/include/db0err.h2
-rw-r--r--innobase/include/dict0dict.h36
-rw-r--r--innobase/include/log0log.h65
-rw-r--r--innobase/include/row0ins.h1
-rw-r--r--innobase/include/row0mysql.h10
-rw-r--r--innobase/include/srv0srv.h3
-rw-r--r--innobase/include/trx0trx.h18
-rw-r--r--innobase/include/univ.i9
-rw-r--r--innobase/include/ut0dbg.h5
-rw-r--r--innobase/lock/Makefile.am2
-rw-r--r--innobase/lock/lock0lock.c42
-rw-r--r--innobase/log/Makefile.am2
-rw-r--r--innobase/log/log0log.c158
-rw-r--r--innobase/log/log0recv.c11
-rw-r--r--innobase/mach/Makefile.am2
-rw-r--r--innobase/mem/Makefile.am2
-rw-r--r--innobase/mtr/Makefile.am2
-rw-r--r--innobase/odbc/Makefile.am2
-rw-r--r--innobase/os/Makefile.am2
-rw-r--r--innobase/os/os0file.c49
-rw-r--r--innobase/os/os0sync.c18
-rw-r--r--innobase/page/Makefile.am2
-rw-r--r--innobase/pars/Makefile.am2
-rw-r--r--innobase/que/Makefile.am2
-rw-r--r--innobase/read/Makefile.am2
-rw-r--r--innobase/rem/Makefile.am2
-rw-r--r--innobase/row/Makefile.am2
-rw-r--r--innobase/row/row0ins.c232
-rw-r--r--innobase/row/row0mysql.c137
-rw-r--r--innobase/row/row0sel.c98
-rw-r--r--innobase/row/row0upd.c2
-rw-r--r--innobase/srv/Makefile.am2
-rw-r--r--innobase/srv/srv0srv.c194
-rw-r--r--innobase/srv/srv0start.c42
-rw-r--r--innobase/sync/Makefile.am2
-rw-r--r--innobase/thr/Makefile.am2
-rw-r--r--innobase/trx/Makefile.am2
-rw-r--r--innobase/trx/trx0sys.c13
-rw-r--r--innobase/trx/trx0trx.c52
-rw-r--r--innobase/usr/Makefile.am2
-rw-r--r--innobase/ut/Makefile.am2
-rw-r--r--innobase/ut/ut0ut.c2
-rw-r--r--libmysql/libmysql.def7
-rw-r--r--libmysqld/libmysqld.c6
-rw-r--r--man/Makefile.am2
-rw-r--r--man/isamchk.12
-rw-r--r--man/isamlog.12
-rw-r--r--man/mysql.12
-rw-r--r--man/mysql_fix_privilege_tables.123
-rw-r--r--man/mysql_zap.12
-rw-r--r--man/mysqlaccess.12
-rw-r--r--man/mysqladmin.12
-rw-r--r--man/mysqld.12
-rw-r--r--man/mysqld_multi.12
-rw-r--r--man/mysqld_safe.12
-rw-r--r--man/mysqldump.12
-rw-r--r--man/mysqlshow.12
-rw-r--r--man/perror.12
-rw-r--r--man/replace.12
-rw-r--r--myisam/ft_boolean_search.c4
-rw-r--r--myisam/mi_check.c34
-rw-r--r--myisam/mi_dynrec.c21
-rw-r--r--myisam/mi_info.c2
-rw-r--r--myisam/mi_key.c23
-rw-r--r--myisam/mi_open.c13
-rw-r--r--myisam/mi_range.c3
-rw-r--r--myisam/mi_rkey.c48
-rw-r--r--myisam/mi_search.c31
-rw-r--r--myisam/mi_test2.c12
-rw-r--r--myisam/myisamchk.c19
-rw-r--r--myisam/myisamdef.h4
-rw-r--r--myisam/sort.c8
-rw-r--r--myisammrg/myrg_extra.c2
-rw-r--r--mysql-test/mysql-test-run.sh31
-rw-r--r--mysql-test/r/alter_table.result156
-rw-r--r--mysql-test/r/ansi.result10
-rw-r--r--mysql-test/r/create.result36
-rw-r--r--mysql-test/r/ctype_latin1_de.result52
-rw-r--r--mysql-test/r/ctype_ujis.result8
-rw-r--r--mysql-test/r/delete.result11
-rw-r--r--mysql-test/r/fulltext.result11
-rw-r--r--mysql-test/r/func_group.result53
-rw-r--r--mysql-test/r/func_misc.result3
-rw-r--r--mysql-test/r/group_by.result36
-rw-r--r--mysql-test/r/having.result15
-rw-r--r--mysql-test/r/innodb.result131
-rw-r--r--mysql-test/r/innodb_handler.result11
-rw-r--r--mysql-test/r/join.result98
-rw-r--r--mysql-test/r/join_outer.result23
-rw-r--r--mysql-test/r/key.result1
-rw-r--r--mysql-test/r/loaddata.result11
-rw-r--r--mysql-test/r/multi_update.result28
-rw-r--r--mysql-test/r/null_key.result2
-rw-r--r--mysql-test/r/order_by.result25
-rw-r--r--mysql-test/r/query_cache.result29
-rw-r--r--mysql-test/r/raid.result3
-rw-r--r--mysql-test/r/repair.result10
-rw-r--r--mysql-test/r/repair_part2.result8
-rw-r--r--mysql-test/r/select.result12
-rw-r--r--mysql-test/r/select_safe.result28
-rw-r--r--mysql-test/r/type_decimal.result6
-rw-r--r--mysql-test/r/union.result60
-rw-r--r--mysql-test/r/update.result73
-rw-r--r--mysql-test/r/variables.result24
-rw-r--r--mysql-test/std_data/loaddata1.dat3
-rw-r--r--mysql-test/t/alter_table.test18
-rw-r--r--mysql-test/t/ansi-master.opt1
-rw-r--r--mysql-test/t/ansi.test17
-rw-r--r--mysql-test/t/create.test33
-rw-r--r--mysql-test/t/ctype_latin1_de.test23
-rw-r--r--mysql-test/t/ctype_ujis-master.opt1
-rw-r--r--mysql-test/t/ctype_ujis.test13
-rw-r--r--mysql-test/t/delete.test6
-rw-r--r--mysql-test/t/fulltext.test13
-rw-r--r--mysql-test/t/func_group.test24
-rw-r--r--mysql-test/t/func_misc.test5
-rw-r--r--mysql-test/t/group_by.test18
-rw-r--r--mysql-test/t/having.test10
-rw-r--r--mysql-test/t/innodb.test81
-rw-r--r--mysql-test/t/innodb_handler.test8
-rw-r--r--mysql-test/t/join.test46
-rw-r--r--mysql-test/t/join_outer.test11
-rw-r--r--mysql-test/t/key.test6
-rw-r--r--mysql-test/t/loaddata.test11
-rw-r--r--mysql-test/t/multi_update-master.opt1
-rw-r--r--mysql-test/t/multi_update.test10
-rw-r--r--mysql-test/t/order_by.test14
-rw-r--r--mysql-test/t/query_cache.test20
-rw-r--r--mysql-test/t/raid.test8
-rw-r--r--mysql-test/t/repair.test13
-rw-r--r--mysql-test/t/repair_part2-master.sh1
-rw-r--r--mysql-test/t/repair_part2.test7
-rw-r--r--mysql-test/t/select_safe.test36
-rw-r--r--mysql-test/t/type_decimal.test10
-rw-r--r--mysql-test/t/union.test93
-rw-r--r--mysql-test/t/update.test46
-rw-r--r--mysql-test/t/variables.test21
-rw-r--r--mysys/default.c8
-rw-r--r--mysys/mf_path.c3
-rw-r--r--mysys/my_bit.c42
-rw-r--r--mysys/my_pthread.c23
-rw-r--r--mysys/my_seek.c3
-rw-r--r--mysys/my_semaphore.c4
-rw-r--r--mysys/raid.cc4
-rwxr-xr-xnetware/BUILD/compile-AUTOTOOLS6
-rwxr-xr-xnetware/BUILD/compile-linux-tools5
-rwxr-xr-xnetware/BUILD/compile-netware-END6
-rwxr-xr-xnetware/BUILD/compile-netware-START5
-rwxr-xr-xnetware/BUILD/compile-netware-all6
-rwxr-xr-xnetware/BUILD/compile-netware-debug6
-rwxr-xr-xnetware/BUILD/compile-netware-standard7
-rwxr-xr-xnetware/BUILD/cron-build46
-rwxr-xr-xnetware/BUILD/crontab4
-rwxr-xr-xnetware/BUILD/mwasmnlm3
-rwxr-xr-xnetware/BUILD/mwccnlm3
-rwxr-xr-xnetware/BUILD/mwldnlm3
-rwxr-xr-xnetware/BUILD/nwbootstrap12
-rw-r--r--repl-tests/README12
-rw-r--r--repl-tests/include/master-slave.inc2
-rwxr-xr-xrepl-tests/run-all-tests9
-rwxr-xr-xrepl-tests/test-auto-inc/run.test10
-rw-r--r--repl-tests/test-auto-inc/x.master4
-rwxr-xr-xrepl-tests/test-bad-query/run.test10
-rw-r--r--repl-tests/test-bad-query/x.master4
-rw-r--r--repl-tests/test-dump/run.test25
-rw-r--r--repl-tests/test-dump/table-dump-check.master2
-rw-r--r--repl-tests/test-dump/table-dump-select.master2
-rw-r--r--repl-tests/test-repl-alter/run.test12
-rw-r--r--repl-tests/test-repl-alter/test.master4
-rw-r--r--repl-tests/test-repl-ts/repl-timestamp.master2
-rw-r--r--repl-tests/test-repl-ts/repl-timestamp.master.reject2
-rw-r--r--repl-tests/test-repl-ts/run.test17
-rw-r--r--repl-tests/test-repl/foo-dump-master.master3
-rw-r--r--repl-tests/test-repl/foo-dump-slave.master3
-rwxr-xr-xrepl-tests/test-repl/run.test24
-rw-r--r--repl-tests/test-repl/sum-wlen-master.master2
-rw-r--r--repl-tests/test-repl/sum-wlen-slave.master2
-rw-r--r--scripts/mysql_fix_privilege_tables.sh24
-rw-r--r--scripts/mysql_install_db.sh5
-rw-r--r--scripts/mysql_setpermission.sh233
-rw-r--r--scripts/mysqld_safe.sh2
-rw-r--r--scripts/mysqlhotcopy.sh36
-rw-r--r--sql-bench/Makefile.am7
-rw-r--r--sql-bench/crash-me.sh45
-rw-r--r--sql/field.cc28
-rw-r--r--sql/field.h2
-rw-r--r--sql/filesort.cc11
-rw-r--r--sql/ha_heap.h5
-rw-r--r--sql/ha_innodb.cc173
-rw-r--r--sql/ha_innodb.h17
-rw-r--r--sql/ha_myisam.cc22
-rw-r--r--sql/handler.cc40
-rw-r--r--sql/handler.h4
-rw-r--r--sql/init.cc2
-rw-r--r--sql/item.cc8
-rw-r--r--sql/item_create.cc2
-rw-r--r--sql/item_func.cc89
-rw-r--r--sql/item_strfunc.cc21
-rw-r--r--sql/item_sum.cc13
-rw-r--r--sql/item_sum.h8
-rw-r--r--sql/log.cc63
-rw-r--r--sql/log_event.cc610
-rw-r--r--sql/log_event.h27
-rw-r--r--sql/mini_client.cc2
-rw-r--r--sql/mysql_priv.h12
-rw-r--r--sql/mysqld.cc109
-rw-r--r--sql/net_serv.cc22
-rw-r--r--sql/opt_range.cc12
-rw-r--r--sql/opt_sum.cc79
-rw-r--r--sql/records.cc2
-rw-r--r--sql/set_var.cc56
-rw-r--r--sql/set_var.h14
-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/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.cc4
-rw-r--r--sql/sql_acl.cc72
-rw-r--r--sql/sql_acl.h3
-rw-r--r--sql/sql_base.cc27
-rw-r--r--sql/sql_cache.cc22
-rw-r--r--sql/sql_class.cc1
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_db.cc25
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_insert.cc19
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_load.cc2
-rw-r--r--sql/sql_parse.cc133
-rw-r--r--sql/sql_repl.cc3
-rw-r--r--sql/sql_select.cc30
-rw-r--r--sql/sql_show.cc8
-rw-r--r--sql/sql_table.cc173
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_update.cc195
-rw-r--r--sql/sql_yacc.yy40
-rw-r--r--sql/time.cc143
-rw-r--r--sql/unireg.h1
-rw-r--r--strings/ctype-tis620.c174
-rw-r--r--support-files/MacOSX/Makefile.am3
-rw-r--r--support-files/MacOSX/ReadMe.txt80
-rw-r--r--support-files/MacOSX/postinstall.sh2
-rw-r--r--support-files/Makefile.am8
-rw-r--r--support-files/MySQL-shared-compat.spec.sh72
-rw-r--r--support-files/my-huge.cnf.sh134
-rw-r--r--support-files/my-large.cnf.sh129
-rw-r--r--support-files/my-medium.cnf.sh116
-rw-r--r--support-files/my-small.cnf.sh42
-rw-r--r--support-files/mysql.server.sh19
-rw-r--r--support-files/mysql.spec.sh12
-rwxr-xr-xtests/big_record.pl41
-rw-r--r--tests/grant.pl43
-rw-r--r--tests/grant.res60
-rwxr-xr-xtests/table_types.pl35
-rw-r--r--vio/viossl.c18
317 files changed, 6660 insertions, 3464 deletions
diff --git a/.bzrignore b/.bzrignore
index 18ad5e18be6..6746bb863b7 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -38,7 +38,11 @@ COPYING.LIB
Docs/#manual.texi#
Docs/INSTALL-BINARY
Docs/include.texi
+Docs/internals.html
Docs/internals.info
+Docs/internals.pdf
+Docs/internals.txt
+Docs/internals_toc.html
Docs/manual.aux
Docs/manual.cp
Docs/manual.cps
@@ -239,6 +243,7 @@ client/select_test
client/ssl_test
client/thimble
client/thread_test
+client_test
cmd-line-utils/libedit/common.h
comon.h
config.cache
@@ -287,6 +292,7 @@ innobase/conftest.subs
innobase/ib_config.h
innobase/ib_config.h.in
innobase/stamp-h1
+insert_test
isam/isamchk
isam/isamlog
isam/pack_isam
@@ -513,6 +519,7 @@ scripts/mysqld_safe
scripts/mysqldumpslow
scripts/mysqlhotcopy
scripts/safe_mysqld
+select_test
sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686
sql-bench/bench-count-distinct
sql-bench/bench-init.pl
@@ -578,6 +585,7 @@ strings/ctype_autoconf.c
strings/ctype_extra_sources.c
support-files/MacOSX/Description.plist
support-files/MacOSX/Info.plist
+support-files/MacOSX/ReadMe.txt
support-files/MacOSX/StartupParameters.plist
support-files/MacOSX/postinstall
support-files/MacOSX/preinstall
@@ -597,6 +605,7 @@ support-files/mysql.spec
tags
test_xml
tests/client_test
+thread_test
tmp/*
tools/my_vsnprintf.c
tools/mysqlmanager
@@ -607,7 +616,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-client_test
-thread_test
-select_test
-insert_test
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index 9a092b84a8f..55b82e38d63 100644
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -71,4 +71,6 @@ else
make=make
fi
-CXX=gcc
+if test -z $CXX ; then
+ CXX=gcc
+fi
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index b6f9647ea49..0f0947a8305 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -51,6 +51,7 @@ miguel@hegel.br
miguel@hegel.local
miguel@light.
miguel@light.local
+mmatthew@markslaptop.
monty@bitch.mysql.fi
monty@butch.
monty@donna.mysql.fi
@@ -67,6 +68,7 @@ mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
mwagner@work.mysql.com
mysql@home.(none)
+mysqldev@build.mysql2.com
nick@mysql.com
nick@nick.leippe.com
papa@gbichot.local
@@ -75,6 +77,7 @@ paul@teton.kitebird.com
pem@mysql.com
peter@linux.local
peter@mysql.com
+peterg@mysql.com
pgulutzan@linux.local
ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index b499e3059b3..07657c0bdeb 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -276,7 +276,11 @@ if ($opt_stage <= 3)
my $flags= "";
log_timestamp();
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");
+ # No need to add the debug symbols, if the binaries are not stripped (saves space)
+ unless ($opt_with_debug || $opt_no_strip)
+ {
+ log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat");
+ }
$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");
diff --git a/Docs/Makefile.am b/Docs/Makefile.am
index af771a5728d..00eb936c408 100644
--- a/Docs/Makefile.am
+++ b/Docs/Makefile.am
@@ -27,7 +27,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt \
all: $(targets) txt_files
txt_files: ../INSTALL-SOURCE ../COPYING ../COPYING.LIB \
- INSTALL-BINARY
+ INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt
CLEAN_FILES: $(BUILD_SOURCES)
touch $(BUILD_SOURCES)
@@ -254,5 +254,8 @@ INSTALL-BINARY: mysql.info $(GT)
../COPYING.LIB: mysql.info $(GT)
perl -w $(GT) mysql.info "LGPL license" "Function Index" > $@
+../support-files/MacOSX/ReadMe.txt: mysql.info $(GT)
+ perl -w $(GT) mysql.info "Mac OS X installation" "Netware installation" > $@
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/Docs/internals.texi b/Docs/internals.texi
index 9f9b08b96c3..ddaedbe5b9b 100644
--- a/Docs/internals.texi
+++ b/Docs/internals.texi
@@ -43,20 +43,19 @@ END-INFO-DIR-ENTRY
@page
@end titlepage
-@node Top, caching, (dir), (dir)
+@node Top, coding guidelines, (dir), (dir)
@ifinfo
This is a manual about @strong{MySQL} internals.
@end ifinfo
@menu
+* coding guidelines:: Coding Guidelines
* caching:: How MySQL Handles Caching
-* join_buffer_size::
* flush tables:: How MySQL Handles @code{FLUSH TABLES}
-* filesort:: How MySQL Does Sorting (@code{filesort})
-* selects:: How MySQL performs different selects
-* transformations:: How MySQL transforms subqueries
-* coding guidelines:: Coding Guidelines
+* Algorithms::
+* selects:: How MySQL performs different selects
+* transformations:: How MySQL transforms subqueries
* mysys functions:: Functions In The @code{mysys} Library
* DBUG:: DBUG Tags To Use
* protocol:: MySQL Client/Server Protocol
@@ -69,7 +68,166 @@ This is a manual about @strong{MySQL} internals.
@end menu
-@node caching, join_buffer_size, Top, Top
+@node coding guidelines, caching, Top, Top
+@chapter Coding Guidelines
+
+@itemize @bullet
+
+@item
+We use @uref{http://www.bitkeeper.com/, BitKeeper} for source management.
+
+@item
+You should use the @strong{MySQL} 4.1 or 5.0 source for all developments.
+
+@item
+If you have any questions about the @strong{MySQL} source, you can post these
+to @email{internals@@lists.mysql.com} and we will answer them.
+
+@item
+Try to write code in a lot of black boxes that can be reused or use at
+least a clean, easy to change interface.
+
+@item
+Reuse code; There is already a lot of algorithms in MySQL for list handling,
+queues, dynamic and hashed arrays, sorting, etc. that can be reused.
+
+@item
+Use the @code{my_*} functions like @code{my_read()}/@code{my_write()}/
+@code{my_malloc()} that you can find in the @code{mysys} library instead
+of the direct system calls; This will make your code easier to debug and
+more portable.
+
+@item
+Try to always write optimized code, so that you don't have to
+go back and rewrite it a couple of months later. It's better to
+spend 3 times as much time designing and writing an optimal function than
+having to do it all over again later on.
+
+@item
+Avoid CPU wasteful code, even where it does not matter, so that
+you will not develop sloppy coding habits.
+
+@item
+If you can write it in fewer lines, do it (as long as the code will not
+be slower or much harder to read).
+
+@item
+Don't use two commands on the same line.
+
+@item
+Do not check the same pointer for @code{NULL} more than once.
+
+@item
+Use long function and variable names in English. This makes your code
+easier to read.
+
+@item
+Use @code{my_var} as opposed to @code{myVar} or @code{MyVar} (@samp{_}
+rather than dancing SHIFT to seperate words in identifiers).
+
+@item
+Think assembly - make it easier for the compiler to optimize your code.
+
+@item
+Comment your code when you do something that someone else may think
+is not ``trivial''.
+
+@item
+Use @code{libstring} functions (in the @file{strings} directory)
+instead of standard @code{libc} string functions whenever possible.
+
+@item
+Avoid using @code{malloc()} (its REAL slow); For memory allocations
+that only need to live for the lifetime of one thread, one should use
+@code{sql_alloc()} instead.
+
+@item
+Before making big design decisions, please first post a summary of
+what you want to do, why you want to do it, and how you plan to do
+it. This way we can easily provide you with feedback and also
+easily discuss it thoroughly if some other developer thinks there is better
+way to do the same thing!
+
+@item
+Class names start with a capital letter.
+
+@item
+Structure types are @code{typedef}'ed to an all-caps identifier.
+
+@item
+Any @code{#define}'s are in all-caps.
+
+@item
+Matching @samp{@{} are in the same column.
+
+@item
+Put the @samp{@{} after a @code{switch} on the same line, as this gives
+better overall indentation for the switch statement:
+
+@example
+switch (arg) @{
+@end example
+
+@item
+In all other cases, @samp{@{} and @samp{@}} should be on their own line, except
+if there is nothing inside @samp{@{} and @samp{@}}.
+
+@item
+Have a space after @code{if}
+
+@item
+Put a space after @samp{,} for function arguments
+
+@item
+Functions return @samp{0} on success, and non-zero on error, so you can do:
+
+@example
+if(a() || b() || c()) @{ error("something went wrong"); @}
+@end example
+
+@item
+Using @code{goto} is okay if not abused.
+
+@item
+Avoid default variable initalizations, use @code{LINT_INIT()} if the
+compiler complains after making sure that there is really no way
+the variable can be used uninitialized.
+
+@item
+Do not instantiate a class if you do not have to.
+
+@item
+Use pointers rather than array indexing when operating on strings.
+
+@end itemize
+
+Suggested mode in emacs:
+
+@example
+(load "cc-mode")
+(setq c-mode-common-hook '(lambda ()
+ (turn-on-font-lock)
+ (setq comment-column 48)))
+(setq c-style-alist
+ (cons
+ '("MY"
+ (c-basic-offset . 2)
+ (c-comment-only-line-offset . 0)
+ (c-offsets-alist . ((statement-block-intro . +)
+ (knr-argdecl-intro . 0)
+ (substatement-open . 0)
+ (label . -)
+ (statement-cont . +)
+ (arglist-intro . c-lineup-arglist-intro-after-paren)
+ (arglist-close . c-lineup-arglist)
+ ))
+ )
+ c-style-alist))
+(c-set-style "MY")
+(setq c-default-style "MY")
+@end example
+
+@node caching, flush tables, coding guidelines, Top
@chapter How MySQL Handles Caching
@strong{MySQL} has the following caches:
@@ -111,8 +269,12 @@ the found rows are cached in a join cache. One @code{SELECT} query can
use many join caches in the worst case.
@end table
-@node join_buffer_size, flush tables, caching, Top
-@chapter How MySQL uses the join_buffer cache
+@menu
+* join_buffer_size::
+@end menu
+
+@node join_buffer_size, , caching, caching
+@section How MySQL uses the join_buffer cache
Basic information about @code{join_buffer_size}:
@@ -183,7 +345,7 @@ same algorithm described above to handle it. (In other words, we store
the same row combination several times into different buffers)
@end itemize
-@node flush tables, filesort, join_buffer_size, Top
+@node flush tables, Algorithms, caching, Top
@chapter How MySQL Handles @code{FLUSH TABLES}
@itemize @bullet
@@ -228,8 +390,19 @@ After this it will give other threads a chance to open the same tables.
@end itemize
-@node filesort, selects, flush tables, Top
-@chapter How MySQL Does Sorting (@code{filesort})
+@node Algorithms, selects, flush tables, Top
+@chapter Different algoritms used in MySQL
+
+MySQL uses a lot of different algorithms. This chapter tries to describe
+some of these:
+
+@menu
+* filesort::
+* bulk-insert::
+@end menu
+
+@node filesort, bulk-insert, Algorithms, Algorithms
+@section How MySQL Does Sorting (@code{filesort})
@itemize @bullet
@@ -268,10 +441,38 @@ and then we read the rows in the sorted order into a row buffer
@end itemize
-@node selects, transformations, flush tables, Top
+@end itemize
+
+@node bulk-insert, , filesort, Algorithms
+@section Bulk insert
+
+Logic behind bulk insert optimisation is simple.
+
+Instead of writing each key value to b-tree (that is to keycache, but
+bulk insert code doesn't know about keycache) keys are stored in
+balanced binary (red-black) tree, in memory. When this tree reaches its
+memory limit it's writes all keys to disk (to keycache, that is). But
+as key stream coming from the binary tree is already sorted inserting
+goes much faster, all the necessary pages are already in cache, disk
+access is minimized, etc.
+
+@node selects, transformations, Algorithms, Top
@chapter How MySQL performs different selects
-@node select steps,,,
+@menu
+* select steps::
+* select select_result::
+* select simple::
+* select structure::
+* select union::
+* select derived::
+* select subselect::
+* select select engine::
+* select union engine::
+* selectexplain::
+@end menu
+
+@node select steps, select select_result, selects, selects
@section Steps of select executing
Every select performed in such base steps:
@@ -317,7 +518,7 @@ Every select performed in such base steps:
@end itemize
@end itemize
-@node select select_result
+@node select select_result, select simple, select steps, selects
@section select_result CLASS
Very important role in SELECT performing have select_result class and
@@ -349,7 +550,7 @@ For example there are fillowing select_result classes:
@strong{multi_update} used for multi-update
@end itemize
-@node select simple
+@node select simple, select structure, select select_result, selects
@section SIMPLE or PRIMARY SELECT.
For performing single primary select SELECT used function mysql_select,
@@ -369,7 +570,7 @@ which:
In previous versions of mysql all SELECTs was performed with help of this
function and mysql_select() was not divided on parts.
-@node select structure
+@node select structure, select union, select simple, selects
@section Structure Of Complex Select
There 2 structures which describe SELECTS:
@@ -425,7 +626,7 @@ LEX::current_select points to SELECT_LEX_UNIT of this unit to store this
parameter in this SELECT_LEX_UNIT (SELECT_LEX and SELECT_LEX_UNIT are
inherited from st_select_lex_node).
-@node select union
+@node select union, select derived, select structure, selects
@section Non-Subselect UNIONs Executing
Non subselect unions performed with help of mysql_union(). for now it
@@ -468,7 +669,7 @@ this SELECT_LEX with JOIN on this mysql_select() session.
PROBLEM: this fake select need workaround in many places.
-@node select derived
+@node select derived, select subselect, select union, selects
@section Derived Tables Executing
Derived tables processing is first operation on any query. It performed
@@ -507,7 +708,7 @@ mysql_derived():
second parameter of it (bool skip_derived) will be true.
@end itemize
-@node select subselect
+@node select subselect, select select engine, select derived, selects
@section Subselects
In expression subselect represented by Item inherited from Item_subselect.
@@ -546,7 +747,7 @@ Item_select will never call cleanup() procedure for JOIN. Every
JOIN::cleanup will call cleanup() for inner JOINs. Most upper
JOIN::cleanup will be called by mysql_select() or mysql_union().
-@node select select engine
+@node select select engine, select union engine, select subselect, selects
@section Single Select Engine
subselect_single_select_engine:
@@ -565,7 +766,7 @@ subselect_single_select_engine:
JOIN::exec() depending of type of subquery.
@end itemize
-@node select union engine
+@node select union engine, selectexplain, select select engine, selects
@section Union Engine
subselect_union_engine:
@@ -585,7 +786,7 @@ subselect_union_engine:
st_select_lex_unit::item is not 0.
@end itemize
-@node selectexplain
+@node selectexplain, , select union engine, selects
@section Explain Execution
For EXPLAIN result showing for every SELECT will be called mysql_select
@@ -611,20 +812,31 @@ mysql_explain_union for every inner UNION
PROBLEM: how it will work with global query optimization?
-@node transformations, coding guidelines, selects, Top
+@node transformations, mysys functions, selects, Top
@chapter How MySQL transforms subqueries
Item_subselect virtual method select_transformer is used to rewrite
subqueries. It is called from Item_subselect::init (which called in
Item_subselect constructor)
-@node transformation IN
+@menu
+* transformation IN::
+* transformations all any::
+* transformations singlerow::
+@end menu
+
+@node transformation IN, transformations all any, transformations, transformations
@section Item_in_subselect::select_transformer
Item_in_subselect::select_transformer is divided on two parts for
scalar left part and row left part:
-@node transformation scalar IN
+@menu
+* transformation scalar IN::
+* transformations row IN::
+@end menu
+
+@node transformation scalar IN, transformations row IN, transformation IN, transformation IN
@subsection Scalar IN Subselect
To rewrite scalar IN subselect used method
@@ -777,7 +989,7 @@ If subselect have not HAVING, sum function or GROUP BY (case b) then:
Single select without FROM will be reduced to just
<left_expression> = <item> without using Item_in_optimizer.
-@node transformations row IN
+@node transformations row IN, , transformation scalar IN, transformation IN
@subsection Row IN Subselect
To rewrite row IN subselect used method
@@ -809,7 +1021,7 @@ In this way will be transformed select without FROM, too.
For other subselect it will be same but for WHERE clause.
-@node transformations all any
+@node transformations all any, transformations singlerow, transformation IN, transformations
@section Item_allany_subselect
Item_allany_subselect is inherited from Item_in_subselect.
@@ -821,7 +1033,7 @@ ANY/SOME use same function that was listed after left expression.
ALL use inverted function, and all subselect passed as argument to
Item_func_not.
-@node transformations singlerow
+@node transformations singlerow, , transformations all any, transformations
@section Item_singlerow_subselect
Item_singlerow_subselect will be rewritten only if it have not FROM
@@ -854,168 +1066,7 @@ expression is Item_fields or Item_ref then name of this new item will
be same as name of this item (but not '(SELECT ...)'). It is done to
prevent broke references on such items from more inner subselects.
-@node coding guidelines, mysys functions, transformations, Top
-@chapter Coding Guidelines
-
-@itemize @bullet
-
-@item
-We are using @uref{http://www.bitkeeper.com/, BitKeeper} for source management.
-
-@item
-You should use the @strong{MySQL} 4.0 source for all developments.
-
-@item
-If you have any questions about the @strong{MySQL} source, you can post these
-to @email{dev-public@@mysql.com} and we will answer them. Please
-remember to not use this internal email list in public!
-
-@item
-Try to write code in a lot of black boxes that can be reused or use at
-least a clean, easy to change interface.
-
-@item
-Reuse code; There is already a lot of algorithms in MySQL for list handling,
-queues, dynamic and hashed arrays, sorting, etc. that can be reused.
-
-@item
-Use the @code{my_*} functions like @code{my_read()}/@code{my_write()}/
-@code{my_malloc()} that you can find in the @code{mysys} library instead
-of the direct system calls; This will make your code easier to debug and
-more portable.
-
-@item
-Try to always write optimized code, so that you don't have to
-go back and rewrite it a couple of months later. It's better to
-spend 3 times as much time designing and writing an optimal function than
-having to do it all over again later on.
-
-@item
-Avoid CPU wasteful code, even where it does not matter, so that
-you will not develop sloppy coding habits.
-
-@item
-If you can write it in fewer lines, do it (as long as the code will not
-be slower or much harder to read).
-
-@item
-Don't use two commands on the same line.
-
-@item
-Do not check the same pointer for @code{NULL} more than once.
-
-@item
-Use long function and variable names in English. This makes your code
-easier to read.
-
-@item
-Use @code{my_var} as opposed to @code{myVar} or @code{MyVar} (@samp{_}
-rather than dancing SHIFT to seperate words in identifiers).
-
-@item
-Think assembly - make it easier for the compiler to optimize your code.
-
-@item
-Comment your code when you do something that someone else may think
-is not ``trivial''.
-
-@item
-Use @code{libstring} functions (in the @file{strings} directory)
-instead of standard @code{libc} string functions whenever possible.
-
-@item
-Avoid using @code{malloc()} (its REAL slow); For memory allocations
-that only need to live for the lifetime of one thread, one should use
-@code{sql_alloc()} instead.
-
-@item
-Before making big design decisions, please first post a summary of
-what you want to do, why you want to do it, and how you plan to do
-it. This way we can easily provide you with feedback and also
-easily discuss it thoroughly if some other developer thinks there is better
-way to do the same thing!
-
-@item
-Class names start with a capital letter.
-
-@item
-Structure types are @code{typedef}'ed to an all-caps identifier.
-
-@item
-Any @code{#define}'s are in all-caps.
-
-@item
-Matching @samp{@{} are in the same column.
-
-@item
-Put the @samp{@{} after a @code{switch} on the same line, as this gives
-better overall indentation for the switch statement:
-
-@example
-switch (arg) @{
-@end example
-
-@item
-In all other cases, @samp{@{} and @samp{@}} should be on their own line, except
-if there is nothing inside @samp{@{} and @samp{@}}.
-
-@item
-Have a space after @code{if}
-
-@item
-Put a space after @samp{,} for function arguments
-
-@item
-Functions return @samp{0} on success, and non-zero on error, so you can do:
-
-@example
-if(a() || b() || c()) @{ error("something went wrong"); @}
-@end example
-
-@item
-Using @code{goto} is okay if not abused.
-
-@item
-Avoid default variable initalizations, use @code{LINT_INIT()} if the
-compiler complains after making sure that there is really no way
-the variable can be used uninitialized.
-
-@item
-Do not instantiate a class if you do not have to.
-
-@item
-Use pointers rather than array indexing when operating on strings.
-
-@end itemize
-
-Suggested mode in emacs:
-
-@example
-(load "cc-mode")
-(setq c-mode-common-hook '(lambda ()
- (turn-on-font-lock)
- (setq comment-column 48)))
-(setq c-style-alist
- (cons
- '("MY"
- (c-basic-offset . 2)
- (c-comment-only-line-offset . 0)
- (c-offsets-alist . ((statement-block-intro . +)
- (knr-argdecl-intro . 0)
- (substatement-open . 0)
- (label . -)
- (statement-cont . +)
- (arglist-intro . c-lineup-arglist-intro-after-paren)
- (arglist-close . c-lineup-arglist)
- ))
- )
- c-style-alist))
-(c-set-style "MY")
-(setq c-default-style "MY")
-@end example
-
-
-@node mysys functions, DBUG, coding guidelines, Top
+@node mysys functions, DBUG, transformations, Top
@chapter Functions In The @code{mysys} Library
Functions in @code{mysys}: (For flags see @file{my_sys.h})
@@ -1211,6 +1262,16 @@ Print query.
* fieldtype codes::
* protocol functions::
* protocol version 2::
+* 4.1 protocol changes::
+* 4.1 field packet::
+* 4.1 field desc::
+* 4.1 ok packet::
+* 4.1 end packet::
+* 4.1 error packet::
+* 4.1 prep init::
+* 4.1 long data::
+* 4.1 execute::
+* 4.1 binary result::
@end menu
@node raw packet without compression, raw packet with compression, protocol, protocol
@@ -1332,6 +1393,7 @@ For details, see @file{sql/net_pkg.cc::send_ok()}.
@node communication, fieldtype codes, basic packets, protocol
@section Communication
+@example
> Packet from server to client
< Paket from client tor server
@@ -1419,7 +1481,7 @@ For details, see @file{sql/net_pkg.cc::send_ok()}.
4 byte header
1-8 byte length of data
n data
-
+@end example
@node fieldtype codes, protocol functions, communication, protocol
@section Fieldtype Codes
@@ -1448,7 +1510,9 @@ Date 03 0A 00 00 |01 0A |03 00 00 00
@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
+@c This should be merged with the above one and changed to texi format
+
+@example
Raw packets
-----------
@@ -1553,12 +1617,14 @@ 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.
+@end example
-@node protocol version 2, , protocol functions, protocol
+@node protocol version 2, 4.1 protocol changes, protocol functions, protocol
@section Another description of the protocol
-This should be merged with the above one and changed to texi format.
+@c This should be merged with the above one and changed to texi format.
+@example
*****************************
*
* PROTOCOL OVERVIEW
@@ -2233,7 +2299,7 @@ one packet is sent from the server, for simplicity's sake):
Followed immediately by one 'LAST DATA' packet:
fe 00 . .
-
+@end example
@c The Index was empty, and ugly, so I removed it. (jcole, Sep 7, 2000)
@@ -2246,7 +2312,7 @@ fe 00 . .
@c @node 4.1 protocol,,,
@c @chapter MySQL 4.1 protocol
-@node 4.1 protocol changes,,,
+@node 4.1 protocol changes, 4.1 field packet, protocol version 2, protocol
@section Changes to 4.0 protocol in 4.1
All basic packet handling is identical to 4.0. When communication
@@ -2281,7 +2347,7 @@ results will sent as binary (low-byte-first).
@end itemize
-@node 4.1 field packet,,,
+@node 4.1 field packet, 4.1 field desc, 4.1 protocol changes, protocol
@section 4.1 field description packet
The field description packet is sent as a response to a query that
@@ -2301,7 +2367,7 @@ uses this to send the number of rows in the table)
This packet is always followed by a field description set.
@xref{4.1 field desc}.
-@node 4.1 field desc,,,
+@node 4.1 field desc, 4.1 ok packet, 4.1 field packet, protocol
@section 4.1 field description result set
The field description result set contains the meta info for a result set.
@@ -2326,7 +2392,7 @@ The field description result set contains the meta info for a result set.
@end multitable
-@node 4.1 ok packet,,,
+@node 4.1 ok packet, 4.1 end packet, 4.1 field desc, protocol
@section 4.1 ok packet
The ok packet is the first that is sent as an response for a query
@@ -2352,7 +2418,7 @@ 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 packet,,,
+@node 4.1 end packet, 4.1 error packet, 4.1 ok packet, protocol
@section 4.1 end packet
The end packet is sent as the last packet for
@@ -2381,7 +2447,7 @@ by checking the packet length < 9 bytes (in which case it's and end
packet).
-@node 4.1 error packet
+@node 4.1 error packet, 4.1 prep init, 4.1 end packet, protocol
@section 4.1 error packet.
The error packet is sent when something goes wrong.
@@ -2398,7 +2464,7 @@ The client/server protocol is designed in such a way that a packet
can only start with 255 if it's an error packet.
-@node 4.1 prep init,,,
+@node 4.1 prep init, 4.1 long data, 4.1 error packet, protocol
@section 4.1 prepared statement init packet
This is the return packet when one sends a query with the COM_PREPARE
@@ -2433,7 +2499,7 @@ prepared statement will contain a result set. In this case the packet
is followed by a field description result set. @xref{4.1 field desc}.
-@node 4.1 long data,,,
+@node 4.1 long data, 4.1 execute, 4.1 prep init, protocol
@section 4.1 long data handling
This is used by mysql_send_long_data() to set any parameter to a string
@@ -2460,7 +2526,7 @@ The server will NOT send an @code{ok} or @code{error} packet 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,,,
+@node 4.1 execute, 4.1 binary result, 4.1 long data, protocol
@section 4.1 execute
On execute we send all parameters to the server in a COM_EXECUTE
@@ -2498,7 +2564,7 @@ The parameters are stored the following ways:
The result for this will be either an ok packet or a binary result
set.
-@node 4.1 binary result,,,
+@node 4.1 binary result, , 4.1 execute, protocol
@section 4.1 binary result set
A binary result are sent the following way.
@@ -2589,7 +2655,7 @@ When you say:
@*
MySQL creates files named Table1.MYD ("MySQL Data"), Table1.MYI
-("MySQL Index"), and Table1.FRM ("Format"). These files will be in the
+("MySQL Index"), and Table1.frm ("Format"). These files will be in the
directory: @*
/<datadir>/<database>/
@*
@@ -2604,12 +2670,15 @@ And if you use Windows, you might find the files in this directory: @*
@*@*
Let's look at the .MYD Data file (MyISAM SQL Data file) more closely.
+There are three possible formats -- fixed, dynamic, and packed. First,
+let's discuss the fixed format.
+
@table @strong
@item Page Size
Unlike most DBMSs, MySQL doesn't store on disk using pages. Therefore
you will not see filler space between rows. (Reminder: This does not
-refer to BDB and INNODB tables, which do use pages).
+refer to BDB and InnoDB tables, which do use pages).
@*
@item Record Header
@@ -2625,6 +2694,12 @@ The minimal record header is a set of flags:
@end table
@*
+The length of the record header is thus:@*
+(1 + number of NULL columns + 7) / 8 bytes@*
+After the header, all columns are stored in
+the order that they were created, which is the
+same order that you would get from SHOW COLUMNS.
+
Here's an example. Suppose you say:
@*
@@ -2667,10 +2742,73 @@ right is @code{on}, and (b) remember that the first flag bit is the X bit.)
There are complications -- the record header is more complex if there
are variable-length fields -- but the simple display shown in the
-example is exactly what you'd see if you took a debugger and looked
-at the MySQL Data file.
+example is exactly what you'd see if you looked at the MySQL Data file
+with a debugger or a hexadecimal file dumper.
+@*
+
+So much for the fixed format. Now, let's discuss the dynamic format.
+@*
+
+The dynamic file format is necessary if rows can vary in size. That will
+be the case if there are BLOB columns, or "true" VARCHAR columns. (Remember
+that MySQL may treat VARCHAR columns as if they're CHAR columns, in which
+case the fixed format is used.) A dynamic row has more fields in the header.
+The important ones are "the actual length", "the unused length", and "the
+overflow pointer". The actual length is the total number of bytes in all the
+columns. The unused length is the total number of bytes between one physical
+record and the next one. The overflow pointer is the location of the rest of
+the record if there are multiple parts.
+@*
+
+For example, here is a dynamic row:
+@*
+@example
+03, 00 start of header
+04 actual length
+0c unused length
+01, fc flags + overflow pointer
+**** data in the row
+************ unused bytes
+ <-- next row starts here)
+@end example
+
+In the example, the actual length and the unused length
+are short (one byte each) because the table definition
+says that the columns are short -- if the columns were
+potentially large, then the actual length and the unused
+length could be two bytes each, three bytes each, and so
+on. In this case, actual length plus unused length is 10
+hexadecimal (sixteen decimal), which is a minimum.
+
+As for the third format -- packed -- we will only say
+briefly that:
+@itemize @bullet
+@item
+Numeric values are stored in a form that depends on the
+range (start/end values) for the data type.
+@item
+All columns are packed using either Huffman or enum coding.
+@end itemize
+
+For details, see the source files /myisam/mi_statrec.c
+(for fixed format), /myisam/mi_dynrec.c (for dynamic
+format), and /myisam/mi_packrec.c (for packed format).
+
+Note: Internally, MySQL uses a format much like the fixed format
+which it uses for disk storage. The main differences are:
+@enumerate
+@item
+BLOBs have a length and a memory pointer rather than being stored inline.
+@item
+"True VARCHAR" (a column storage which will be fully implemented in
+version 5.0) will have a 16-bit length plus the data.
+@item
+All integer or floating-point numbers are stored with the low byte first.
+Point (3) does not apply for ISAM storage or internals.
+@end enumerate
@*
+
@section Physical Attributes of Columns
Next I'll describe the physical attributes of each column in a row.
@@ -2701,8 +2839,8 @@ Example: a VARCHAR(7) column containing 'A' looks like:@*
@item The numeric data types
-Important: MySQL stores all multi-byte binary numbers with the
-high byte first. This is called "little-endian" numeric storage;
+Important: MySQL almost always stores multi-byte binary numbers with
+the low byte first. This is called "little-endian" numeric storage;
it's normal on Intel x86 machines; MySQL uses it even for non-Intel
machines so that databases will be portable.
@*
@@ -2877,7 +3015,7 @@ Example: a SET('A','B','C') column containing 'A' looks like:@*
Storage: one byte if less than 256 alternatives, else two bytes.
@item
This is an index. The value 1 corresponds to the first listed
-alternative. (Note: ENUM always reserves 0 for a blank '' value. This
+alternative. (Note: ENUM always reserves 0 for an erroneous value. This
explains why 'A' is 1 instead of 0.)
@item
Example: an ENUM('A','B','C') column containing 'A' looks like:@*
@@ -2893,9 +3031,6 @@ of correspondence between the BLOB and the INT types. There isn't -- a
BLOB's preceding length is not four bytes long (the size of an INT).
@*
-(NOTE TO SELF: BLOB storage has not been fully addressed here.)
-@*
-
@strong{TINYBLOB}
@itemize @bullet
@item
@@ -2962,10 +3097,13 @@ Storage: same as LONGBLOB.
@strong{References:} @*
Most of the formatting work for MyISAM columns is visible
-in the program /sql/field.cc in the source code directory.
+in the program /sql/field.cc in the source code directory.
+And in the MyISAM directory, the files that do formatting
+work for different record formats are: /myisam/mi_statrec.c,
+/myisam/mi_dynrec.c, and /myisam/mi_packrec.c.
@*
-@node InnoDB Record Structure,InnoDB Page Structure,MyISAM Record Structure,Top
+@node InnoDB Record Structure, InnoDB Page Structure, MyISAM Record Structure, Top
@chapter InnoDB Record Structure
This page contains:
@@ -3271,7 +3409,7 @@ shorter because the NULLs take no space.
The most relevant InnoDB source-code files are rem0rec.c, rem0rec.ic,
and rem0rec.h in the rem ("Record Manager") directory.
-@node InnoDB Page Structure,Files in MySQL Sources,InnoDB Record Structure,Top
+@node InnoDB Page Structure, Files in MySQL Sources, InnoDB Record Structure, Top
@chapter InnoDB Page Structure
InnoDB stores all records inside a fixed-size unit which is commonly called a
@@ -3702,12 +3840,12 @@ header.
The most relevant InnoDB source-code files are page0page.c,
page0page.ic, and page0page.h in \page directory.
-@node Files in MySQL Sources,Files in InnoDB Sources,InnoDB Page Structure,Top
+@node Files in MySQL Sources, Files in InnoDB Sources, InnoDB Page Structure, Top
@chapter Annotated List Of Files in the MySQL Source Code Distribution
This is a description of the files that you get when you download the
source code of MySQL. This description begins with a list
-of the 43 directories and a short comment about each one. Then, for
+of the main directories and a short comment about each one. Then, for
each directory, in alphabetical order, a longer description is
supplied. When a directory contains significant program files, a list of each C
program is given along with an explanation of its intended function.
@@ -3717,47 +3855,37 @@ program is given along with an explanation of its intended function.
@strong{Directory -- Short Comment}
@itemize @bullet
@item
-bdb -- The Berkeley Database table handler
-@item
-BitKeeper -- BitKeeper administration
-@item
-BUILD -- Build switches
-@item
-Build-tools -- Build tools
+bdb -- The Berkeley Database table handler
@item
-client -- Client library
+BitKeeper -- BitKeeper administration (not part of the source distribution)
@item
-cmd-line-utils -- Command-line utilities
+BUILD -- Frequently used build scripts
@item
-dbug -- Fred Fish's dbug library
+Build-tools -- Build tools (not part of the source distribution)
@item
-div -- Deadlock test
+client -- Client library
@item
-Docs -- Preliminary documents about internals and new modules
+cmd-line-utils -- Command-line utilities (libedit and readline)
@item
-extra -- Eight minor standalone utility programs
+dbug -- Fred Fish's dbug library
@item
-fs -- File System
+Docs -- Preliminary documents about internals and new modules; will eventually be moved to the mysqldoc repository
@item
-heap -- The HEAP table handler
+extra -- Some minor standalone utility programs
@item
-Images -- Empty directory
+heap -- The HEAP table handler
@item
-include -- Include (*.h) files
+include -- Header (*.h) files for most libraries; includes all header files distributed with the MySQL binary distribution
@item
-innobase -- The Innobase (InnoDB) table handler
+innobase -- The Innobase (InnoDB) table handler
@item
-isam -- The ISAM (MySQL) table handler
+libmysql -- For producing MySQL as a library (e.g. a Windows .DLL)
@item
-libmysql -- For producing MySQL as a library (e.g. a Windows DLL)
+libmysql_r -- For building a thread-safe libmysql library
@item
-libmysql_r -- Only one file, a makefile
+libmysqld -- The MySQL Server as an embeddable library
@item
-libmysqld -- The MySQL Library
-@item
-man -- Manual pages
-@item
-merge -- The MERGE table handler (see Reference Manual section 7.2)
+man -- Some user-contributed manual pages
@item
myisam -- The MyISAM table handler
@item
@@ -3765,45 +3893,41 @@ myisammrg -- The MyISAM Merge table handler
@item
mysql-test -- A test suite for mysqld
@item
-mysys -- MySQL system library (Low level routines for file access
-etc.)
+mysys -- MySQL system library (Low level routines for file access etc.)
@item
netware -- Files related to the Novell NetWare version of MySQL
@item
-NEW-RPMS -- New "RPM Package Manager" files
+NEW-RPMS -- Directory to place RPMs while making a distribution
@item
-os2 -- Routines for working with the OS/2 operating system
+os2 -- Routines for working with the OS/2 operating system
@item
-pstack -- Process stack display
+pstack -- Process stack display (not currently used)
@item
-regex -- Regular Expression library for support of REGEXP function
+regex -- Henry Spencer's Regular Expression library for support of REGEXP function
@item
-repl-tests -- Test cases for replication
+SCCS -- Source Code Control System (not part of source distribution)
@item
-SCCS -- Source Code Control System
+scripts -- SQL batches, e.g. mysqlbug and mysql_install_db
@item
-scripts -- SQL batches, e.g. for converting msql to MySQL
-@item
-sql -- Programs for handling SQL commands. The "core" of MySQL
+sql -- Programs for handling SQL commands; the "core" of MySQL
@item
sql-bench -- The MySQL benchmarks
@item
-SSL -- Secure Sockets Layer
+SSL -- Secure Sockets Layer; includes an example certification one can use to test an SSL (secure) database connection
@item
strings -- Library for C string routines, e.g. atof, strchr
@item
-support-files -- 15 files used for building, containing switches?
+support-files -- Files used to build MySQL on different systems
@item
-tests -- Tests in Perl
+tests -- Tests in Perl and in C
@item
-tools -- mysqlmanager.c
+tools -- mysqlmanager.c (tool under development, not yet useful)
@item
-VC++Files -- Includes this entire directory, repeated for VC++
-(Windows) use
+VC++Files -- Includes this entire directory, repeated for VC++ (Windows) use
@item
vio -- Virtual I/O Library
@item
-zlib -- data compression library
+zlib -- Data compression library, used on Windows
@end itemize
@subsection bdb
@@ -3812,6 +3936,8 @@ The Berkeley Database table handler.
@*@*
The Berkeley Database (BDB) is maintained by Sleepycat Software.
+MySQL AB maintains only a few small patches to make BDB work
+better with MySQL.
@*@*
The documentation for BDB is available at
@@ -3825,15 +3951,21 @@ in this document.
BitKeeper administration.
@*@*
-This directory may be present if you downloaded the MySQL source using
+Bitkeeper administration is not part of the source distribution. This
+directory may be present if you downloaded the MySQL source using
BitKeeper rather than via the mysql.com site. The files in the
BitKeeper directory are for maintenance purposes only -- they are not
part of the MySQL package.
@*@*
+The MySQL Reference Manual explains how to use Bitkeeper to get the
+MySQL source. Please see @url{http://www.mysql.com/doc/en/Installing_source_tree.html}
+for more information.
+@*@*
+
@subsection BUILD
-Build switches.
+Frequently used build scripts.
@*@*
This directory contains the build switches for compilation on various
@@ -3856,10 +3988,11 @@ solaris
Build tools.
@*@*
-This directory contains batch files for extracting, making
-directories, and making programs from source files. There are several
-subdirectories -- for building Linux executables, for compiling, for
-performing all build steps, etc.
+Build-tools is not part of the source distribution. This directory
+contains batch files for extracting, making directories, and making
+programs from source files. There are several subdirectories with
+different scripts -- for building Linux executables, for compiling,
+for performing all build steps, and so on.
@*@*
@subsection client
@@ -3877,56 +4010,40 @@ server.
The C program files in the directory are:
@itemize @bullet
@item
-connect_test.c -- test that a connect is possible
-@item
-get_password.c -- ask for a password from the console
-@item
-insert_test.c -- test that an insert is possible
-@item
-list_test.c -- test that a select is possible
+get_password.c -- ask for a password from the console
@item
-mysql.cc -- "The MySQL command tool"
+mysql.cc -- "The MySQL command tool"
@item
-mysqladmin.c -- maintenance of MYSQL databases
+mysqladmin.c -- maintenance of MySQL databases
@item
-mysqlcheck.c -- check all databases, check connect, etc.
+mysqlcheck.c -- check all databases, check connect, etc.
@item
-mysqldump.c -- dump table's contents in ascii
+mysqldump.c -- dump table's contents as SQL statements, suitable to backup a MySQL database
@item
-mysqlimport.c -- import file into a table
+mysqlimport.c -- import text files in different formats into tables
@item
-mysqlmanager-pwgen.c -- pwgen seems to stand for "password
-generation"
+mysqlmanager-pwgen.c -- pwgen stands for "password generation" (not currently maintained)
@item
-mysqlmanagerc.c -- entry point for mysql manager
+mysqlmanagerc.c -- entry point for mysql manager (not currently maintained)
@item
mysqlshow.c -- show databases, tables or columns
@item
-mysqltest.c -- test program
+mysqltest.c -- test program used by the mysql-test suite, mysql-test-run
@item
-password.c -- password checking routines
-@item
-select_test.c -- test that a select is possible
-@item
-showdb_test.c -- test that a show-databases is possible
-@item
-ssl_test.c -- test that SSL is possible
-@item
-thread_test.c -- test that threading is possible
+password.c -- password checking routines (version 4.1 and up)
@end itemize
@*@*
@subsection cmd-line-utils
-Command-line utilities.
+Command-line utilities (libedit and readline).
@*@*
There are two subdirectories: \readline and \libedit. All the files
-here are "non-MYSQL" files, in the sense that MySQL AB didn't produce
+here are "non-MySQL" files, in the sense that MySQL AB didn't produce
them, it just uses them. It should be unnecessary to study the
-programs in these files unless
-you are writing or debugging a tty-like client for MySQL, such as
-mysql.exe.
+programs in these files unless you are writing or debugging a tty-like
+client for MySQL, such as mysql.exe.
@*@*
The \readline subdirectory contains the files of the GNU Readline
@@ -3936,51 +4053,54 @@ Software Foundation.
@*@*
The \libedit (library of edit functions) subdirectory has files
-written by Christos Zoulas. They are for editing the line contents.
+written by Christos Zoulas. They are distributed and modifed under
+the BSD License. These files are for editing the line contents.
+@*@*
+
These are the program files in the \libedit subdirectory:
@itemize @bullet
@item
-chared.c -- character editor
+chared.c -- character editor
@item
-common.c -- common editor functions
+common.c -- common editor functions
@item
-el.c -- editline interface functions
+el.c -- editline interface functions
@item
-emacs.c -- emacs functions
+emacs.c -- emacs functions
@item
-fgetln.c -- get line
+fgetln.c -- get line
@item
-hist.c -- history access functions
+hist.c -- history access functions
@item
-history.c -- more history access functions
+history.c -- more history access functions
@item
-key.c -- procedures for maintaining the extended-key map
+key.c -- procedures for maintaining the extended-key map
@item
-map.c -- editor function definitions
+map.c -- editor function definitions
@item
-parse.c -- parse an editline extended command
+parse.c -- parse an editline extended command
@item
-prompt.c -- prompt printing functions
+prompt.c -- prompt printing functions
@item
-read.c -- terminal read functions
+read.c -- terminal read functions
@item
-readline.c -- read line
+readline.c -- read line
@item
-refresh.c -- "lower level screen refreshing functions"
+refresh.c -- "lower level screen refreshing functions"
@item
-search.c -- "history and character search functions"
+search.c -- "history and character search functions"
@item
-sig.c -- for signal handling
+sig.c -- for signal handling
@item
-strlcpy.c -- string copy
+strlcpy.c -- string copy
@item
-term.c -- "editor/termcap-curses interface"
+term.c -- "editor/termcap-curses interface"
@item
-tokenizer.c -- Bourne shell line tokenizer
+tokenizer.c -- Bourne shell line tokenizer
@item
-tty.c -- for a tty interface
+tty.c -- for a tty interface
@item
-vi.c -- commands used when in the vi (editor) mode
+vi.c -- commands used when in the vi (editor) mode
@end itemize
@*@*
@@ -3991,6 +4111,8 @@ Fred Fish's dbug library.
This is not really part of the MySQL package. Rather, it's a set of
public-domain routines which are useful for debugging MySQL programs.
+The MySQL Server and all .c and .cc programs support the use of this
+package.
@*@*
How it works: One inserts a function call that begins with DBUG_* in
@@ -4000,68 +4122,62 @@ DBUG_ENTER("get_tty_password"); @*
at the start of a routine, and this line: @*
DBUG_RETURN(my_strdup(to,MYF(MY_FAE))); @*
at the end of the routine. These lines don't affect production code.
-Features of the dbug library include profiling and state pushing.
+Features of the dbug library include extensive reporting and profiling
+(the latter has not been used by the MySQL team).
@*@*
The C programs in this directory are:
@itemize @bullet
@item
-dbug.c -- The main module
+dbug.c -- The main module
@item
-dbug_analyze.c -- Reads a file produced by trace functions
+dbug_analyze.c -- Reads a file produced by trace functions
@item
-example1.c -- A tiny example
+example1.c -- A tiny example
@item
-example2.c -- A tiny example
+example2.c -- A tiny example
@item
-example3.c -- A tiny example
+example3.c -- A tiny example
@item
-factorial.c -- A tiny example
+factorial.c -- A tiny example
@item
-main.c -- A tiny example
+main.c -- A tiny example
@item
-sanity.c -- Declaration of a variable
+sanity.c -- Declaration of a variable
@end itemize
@*@*
-@subsection div
-
-Deadlock test.
-@*@*
-
-This file contains only one program, deadlock_test.c.
-@*@*
-
@subsection Docs
-Preliminary documents about internals and new modules.
+Preliminary documents about internals and new modules, which will eventually
+be moved to the mysqldoc repository.
@*@*
This directory doesn't have much at present that's very useful to the
student, but the plan is that some documentation related to the source
files and the internal workings of MySQL, including perhaps some
-documentation from developers themselves, will be placed here.
+documentation from developers themselves, will be placed here. Files in
+this directory will eventually be moved to the MySQL documentation repository.
@*@*
These sub-directories are part of this directory:
@itemize @bullet
@item
-books -- .gif images and empty .txt files; no real information
+books -- .gif images and empty .txt files; no real information
@item
-flags -- images of flags of countries
+flags -- images of flags of countries
@item
-images -- flag backgrounds and the MySQL dolphin logo
+images -- flag backgrounds and the MySQL dolphin logo
@item
-mysql-logos -- more MySQL-related logos, some of them moving
+mysql-logos -- more MySQL-related logos, some of them moving
@item
-raw-flags -- more country flags, all .gif files
+raw-flags -- more country flags, all .gif files
@item
-support -- various files for generating texinfo/docbook
-documentation
+support -- various files for generating texinfo/docbook documentation
@item
-to-be-included... -- an empty subdirectory
+to-be-included... -- contains a MySQL-for-dummies file
@item
-translations -- some Portuguese myodbc documentation
+translations -- some Portuguese myodbc documentation
@end itemize
@*@*
@@ -4072,74 +4188,38 @@ has any importance -- internals.texi -- The "MySQL Internals"
document.
@*@*
-Despite the name, internals.texi is not really much of a description
-of MySQL internals. However, there is some useful description of the
-functions in the mysys directory (see below), and of the structure of
-client/server messages (doubtless very useful for people who want to
-make their own JDBC drivers, or just sniff).
+Despite the name, internals.texi is not yet much of a description of MySQL
+internals although work is in progress to make it so. However, there is
+some useful description of the functions in the mysys directory (see below),
+and of the structure of client/server messages (doubtless very useful for
+eople who want to make their own JDBC drivers, or just sniff).
@*@*
@subsection extra
-Eight minor standalone utility programs.
+Some minor standalone utility programs.
@*@*
-These eight programs are all standalone utilities, that is, they have
+These programs are all standalone utilities, that is, they have
a main() function and their main role is to show information that the
MySQL server needs or produces. Most are unimportant. They are as
follows:
@itemize @bullet
@item
-my_print_defaults.c -- print all parameters in a default file
-@item
-mysql_install.c -- startup: install MySQL server
+my_print_defaults.c -- print parameters from my.ini files. Can also be used in scripts to enable processing of my.ini files.
@item
-mysql_waitpid.c -- wait for a program to terminate
+mysql_waitpid.c -- wait for a program to terminate. Useful for shell scripts when one needs to wait until a process terminates.
@item
-perror.c -- "print error" -- given error number, display message
+perror.c -- "print error" -- given error number, display message
@item
-replace.c -- replace strings in text files
+replace.c -- replace strings in text files or pipe
@item
-resolve_stack_dump.c -- show symbolic info from a stack dump
+resolve_stack_dump.c -- show symbolic information from a MySQL stack dump, normally found in the mysql.err file
@item
-resolveip.c -- convert an IP address to a hostname, or vice versa
+resolveip.c -- convert an IP address to a hostname, or vice versa
@end itemize
@*@*
-@subsection fs
-
-File System.
-@*@*
-
-Here the word "File System" does not refer to the mere idea of a
-directory of files on a disk drive, but to object-based access. The
-concept has been compared with Oracle's Internet File System (iFS).
-@*@*
-
-The original developer of the files on this directory is Tonu Samuel,
-a former MySQL AB employee. Here is a quote (somewhat edited) from
-Tonu Samuel's web page (http://no.spam.ee/~tonu/index.php):
-"Question: What is it?
-Answer: Actually this is not filesystem in common terms. MySQL FS
-makes it possible to make SQL tables and some functions available over
-a filesystem. MySQL does not require disk space, it uses an ordinary
-MySQL daemon to store data."
-The descriptions imply that this is a development project.
-@*@*
-
-There are four program files in the directory:
-@itemize @bullet
-@item
-database.c -- "emulate filesystem behaviour on top of SQL database"
-@item
-libmysqlfs.c -- Search/replace, show-functions, and parse routines
-@item
-mysqlcorbafs.c -- Connection with the CORBA "Object Request Broker"
-@item
-mysqlcorbafs_test.c -- Utility to test the working of mysqlcorbafs.c
-
-@*@*
-
@subsection heap
The HEAP table handler.
@@ -4151,59 +4231,63 @@ produces) have files with similar names and functions. Thus, this
(for the MyISAM table handler). Such duplicates have been marked with
an "*" in the following list. For example, you will find that
\heap\hp_extra.c has a close equivalent in the myisam directory
-(\myisam\mi_extra.c) with the same descriptive comment.
+(\myisam\mi_extra.c) with the same descriptive comment. (Some of the
+differences arise because HEAP has different structures. HEAP does not
+need to use the sort of B-tree indexing that ISAM and MyISAM use; instead
+there is a hash index. Most importantly, HEAP is entirely in memory.
+File-I/O routines lose some of their vitality in such a context.)
@*@*
+@itemize
@item
hp_block.c -- Read/write a block (i.e. a page)
@item
-hp_clear.c -- Remove all records in the database
+hp_clear.c -- Remove all records in the table
@item
-hp_close.c -- * close database
+hp_close.c -- * close database
@item
-hp_create.c -- * create a table
+hp_create.c -- * create a table
@item
-hp_delete.c -- * delete a row
+hp_delete.c -- * delete a row
@item
hp_extra.c -- * for setting options and buffer sizes when optimizing
@item
-hp_hash.c -- Hash functions used for saving keys
+hp_hash.c -- Hash functions used for saving keys
@item
-hp_info.c -- * Information about database status
+hp_info.c -- * Information about database status
@item
-hp_open.c -- * open database
+hp_open.c -- * open database
@item
-hp_panic.c -- * the hp_panic routine, probably for sudden shutdowns
+hp_panic.c -- * the hp_panic routine, for shutdowns and flushes
@item
-hp_rename.c -- * rename a table
+hp_rename.c -- * rename a table
@item
hp_rfirst.c -- * read first row through a specific key (very short)
@item
-hp_rkey.c -- * read record using a key
+hp_rkey.c -- * read record using a key
@item
hp_rlast.c -- * read last row with same key as previously-read row
@item
hp_rnext.c -- * read next row with same key as previously-read row
@item
-hp_rprev.c -- * read previous row with same key as previously-read
-row
+hp_rprev.c -- * read previous row with same key as previously-read row
@item
-hp_rrnd.c -- * read a row based on position
+hp_rrnd.c -- * read a row based on position
@item
hp_rsame.c -- * find current row using positional read or key-based
-read
+read
@item
-hp_scan.c -- * read all rows sequentially
+hp_scan.c -- * read all rows sequentially
@item
hp_static.c -- * static variables (very short)
@item
-hp_test1.c -- * testing basic functions
+hp_test1.c -- * testing basic functions
@item
-hp_test2.c -- * testing database and storing results
+hp_test2.c -- * testing database and storing results
@item
-hp_update.c -- * update an existing row
+hp_update.c -- * update an existing row
@item
-hp_write.c -- * insert a new row
+hp_write.c -- * insert a new row
@end itemize
@*@*
@@ -4213,17 +4297,10 @@ for a \myisam\mi_cache.c equivalent (to cache reads) or a
\myisam\log.c equivalent (to log statements).
@*@*
-@subsection Images
-
-Empty directory.
-@*@*
-
-There are no files in this directory.
-@*@*
-
@subsection include
-Include (*.h) files.
+Header (*.h) files for most libraries; includes all header files distributed
+with the MySQL binary distribution.
@*@*
These files may be included in C program files. Note that each
@@ -4238,7 +4315,7 @@ rijndael.h. Looking further, you'll find that rijndael.h is also
included in other places: by my_aes.c and my_aes.h.
@*@*
-The include directory contains 51 *.h (include) files.
+The include directory contains 51 *.h (header) files.
@*@*
@subsection innobase
@@ -4250,100 +4327,6 @@ A full description of these files can be found elsewhere in this
document.
@*@*
-@subsection isam
-
-The ISAM table handler.
-@*@*
-
-The C files in this directory are:
-@itemize @bullet
-@item
-_cache.c -- for reading records from a cache
-@item
-changed.c -- a single routine for setting a "changed" flag (very
-short)
-@item
-close.c -- close database
-@item
-create.c -- create a table
-@item
-_dbug.c -- support routines for use with "dbug" (see the \dbug
-description)
-@item
-delete.c -- delete a row
-@item
-_dynrec.c -- functions to handle space-packed records and blobs
-@item
-extra.c -- setting options and buffer sizes when optimizing table
-handling
-@item
-info.c -- Information about database status
-@item
-_key.c -- for handling keys
-@item
-_locking.c -- lock database
-@item
-log.c -- save commands in log file which myisamlog program can read
-@item
-_packrec.c -- compress records
-@item
-_page.c -- read and write pages containing keys
-@item
-panic.c -- the mi_panic routine, probably for sudden shutdowns
-@item
-range.c -- approximate count of how many records lie between two
-keys
-@item
-rfirst.c -- read first row through a specific key (very short)
-@item
-rkey.c -- read a record using a key
-@item
-rlast.c -- read last row with same key as previously-read row
-@item
-rnext.c -- read next row with same key as previously-read row
-@item
-rprev.c -- read previous row with same key as previously-read row
-@item
-rrnd.c -- read a row based on position
-@item
-rsame.c -- find current row using positional read or key-based read
-@item
-rsamepos.c -- positional read
-@item
-_search.c -- key-handling functions
-@item
-static.c -- static variables (very short)
-@item
-_statrec.c -- functions to handle fixed-length records
-@item
-test1.c -- testing basic functions
-@item
-test2.c -- testing database and storing results
-@item
-test3.c -- testing locking
-@item
-update.c -- update an existing row
-@item
-write.c -- insert a new row
-@item
-pack_isam.c -- pack isam file (NOTE TO SELF ?? equivalent to
-\myisam\myisampack.c)
-@end itemize
-@*@*
-
-Except for one minor C file (pack_isam.c) every program in the ISAM
-directory has a counterpart in the MyISAM directory. For example
-\isam\update.c corresponds to \myisam\mi_update.c. However, the
-reverse is not true -- there are many files in the MyISAM directory
-which have no counterpart in the ISAM directory.
-@*@*
-
-The reason is simple -- it's because the ISAM files are becoming
-obsolete. When MySQL programmers add new features, they add them for
-MyISAM only. The student can therefore ignore all files in this
-directory and study the MyISAM programs instead.
-@*@*
-
@subsection libmysql
The MySQL Library, Part 1.
@@ -4357,25 +4340,33 @@ sending messages, the client part merely calls the server part.
The libmysql files are split into three directories: libmysql (this
one), libmysql_r (the next one), and libmysqld (the next one after
-that). It may be that the original intention was that the libmysql
-directory would hold the "client part" files, and the libmysqld
-directory would hold the "server part" files.
+that).
+@*@*
+
+The "library of mysql" has some client-connection
+modules. For example, as described in an earlier
+section of this manual, there is a discussion of
+libmysql/libmysql.c which sends packets from the
+client to the server. Many of the entries in the
+libmysql directory (and in the following libmysqld
+directory) are 'symlinks' on Linux, that is, they
+are in fact pointers to files in other directories.
@*@*
The program files on this directory are:
@itemize @bullet
@item
-conf_to_src.c -- has to do with charsets
+conf_to_src.c -- has to do with charsets
@item
-dll.c -- initialization of the dll library
+dll.c -- initialization of the dll library
@item
-errmsg.c -- English error messages, compare \mysys\errors.c
+errmsg.c -- English error messages, compare \mysys\errors.c
@item
-get_password.c -- get password
+get_password.c -- get password
@item
-libmysql.c -- the main "packet-sending emulation" program
+libmysql.c -- the code that implements the MySQL API, i.e. the functions a client that wants to connect to MySQL will call
@item
-manager.c -- initialize/connect/fetch with MySQL manager
+manager.c -- initialize/connect/fetch with MySQL manager
@end itemize
@*@*
@@ -4384,8 +4375,7 @@ manager.c -- initialize/connect/fetch with MySQL manager
The MySQL Library, Part 2.
@*@*
-This is a continuation of the libmysql directory. There is only one
-file here:
+There is only one file here, used to build a thread-safe libmysql library:
@itemize @bullet
@item
makefile.am
@@ -4397,83 +4387,27 @@ makefile.am
The MySQL library, Part 3.
@*@*
-This is a continuation of the libmysql directory. The program files on
-this directory are:
+The Embedded MySQL Server Library. The product of libmysqld
+is not a client/server affair, but a library. There is a wrapper
+to emulate the client calls. The program files on this directory
+are:
@itemize @bullet
@item
-libmysqld.c -- The called side, compare the mysqld.exe source
+libmysqld.c -- The called side, compare the mysqld.exe source
@item
-lib_vio.c -- Emulate the vio directory's communication buffer
+lib_vio.c -- Emulate the vio directory's communication buffer
@end itemize
@*@*
@subsection man
-Manual pages.
+Some user-contributed manual pages
@*@*
-These are not the actual "man" (manual) pages, they are switches for
-the production.
-@*@*
-
-@subsection merge
-
-The MERGE table handler.
-@*@*
-
-For a description of the MERGE table handler, see the MySQL Reference
-Manual, section 7.2.
-@*@*
-
-You'll notice that there seem to be several directories with
-similar-sounding names of C files in them. That's because the MySQL
-table handlers are all quite similar.
-@*@*
-
-The related directories are:
-@itemize @bullet
-@item
-\isam -- for ISAM
-@item
-\myisam -- for MyISAM
-@item
-\merge -- for ISAM MERGE (mostly call functions in \isam programs)
-@item
-\myisammrg -- for MyISAM MERGE (mostly call functions in \myisam
-programs)
-@end itemize
-@*@*
-
-To avoid duplication, only the \myisam program versions are discussed.
-@*@*
-
-The C programs in this (merge) directory are:
-@itemize @bullet
-@item
-mrg_close.c -- compare \isam's close.c
-@item
-mrg_create.c -- "" create.c
-@item
-mrg_delete.c -- "" delete.c
-@item
-mrg_extra.c -- "" extra.c
-@item
-mrg_info.c -- "" info.c
-@item
-mrg_locking.c -- "" locking.c
-@item
-mrg_open.c -- "" open.c
-@item
-mrg_panic.c -- "" panic.c
-@item
-mrg_rrnd.c -- "" rrnd.c
-@item
-mrg_rsame.c -- "" rsame.c
-@item
-mrg_static.c -- "" static.c
-@item
-mrg_update.c -- "" update.c
-@end itemize
+These are user-contributed "man" (manual) pages in a special markup
+format. The format is described in a document with a heading like
+"man page for man" or "macros to format man pages" which you can find
+in a Linux directory or on the Internet.
@*@*
@subsection myisam
@@ -4484,23 +4418,17 @@ The MyISAM table handler.
The C files in this subdirectory come in six main groups:
@itemize @bullet
@item
-ft*.c files -- ft stands for "Full Text", code contributed by Sergei
-Golubchik
+ft*.c files -- ft stands for "Full Text", code contributed by Sergei Golubchik
@item
-mi*.c files -- mi stands for "My Isam", these are the main programs
-for Myisam
+mi*.c files -- mi stands for "My Isam", these are the main programs for Myisam
@item
-myisam*.c files -- for example, "myisamchk" utility routine
-functions source
+myisam*.c files -- for example, "myisamchk" utility routine functions source
@item
-rt*.c files -- rt stands for "rtree", some code was written by
-Alexander Barkov
+rt*.c files -- rt stands for "rtree", some code was written by Alexander Barkov
@item
-sp*.c files -- sp stands for "spatial", some code was written by
-Ramil Kalimullin
+sp*.c files -- sp stands for "spatial", some code was written by Ramil Kalimullin
@item
-sort.c -- this is a single file that sorts keys for index-create
-purposes
+sort.c -- this is a single file that sorts keys for index-create purposes
@end itemize
@*@*
@@ -4511,10 +4439,9 @@ programs. They are:
@item
mi_cache.c -- for reading records from a cache
@item
-mi_changed.c -- a single routine for setting a "changed" flag (very
-short)
+mi_changed.c -- a single routine for setting a "changed" flag (very short)
@item
-mi_check.c -- doesn't just do checks, ?? for myisamchk program?
+mi_check.c -- for checking and repairing tables. Used by the myisamchk program and by the MySQL server.
@item
mi_checksum.c -- calculates a checksum for a row
@item
@@ -4522,8 +4449,7 @@ mi_close.c -- close database
@item
mi_create.c -- create a table
@item
-mi_dbug.c -- support routines for use with "dbug" (see \dbug
-description)
+mi_dbug.c -- support routines for use with "dbug" (see \dbug description)
@item
mi_delete.c -- delete a row
@item
@@ -4535,66 +4461,63 @@ mi_dynrec.c -- functions to handle space-packed records and blobs
@item
mi_extra.c -- setting options and buffer sizes when optimizing
@item
-mi_info.c -- "Ger tillbaka en struct med information om isam-filen"
+mi_info.c -- return useful base information for an open table
@item
-mi_key.c -- for handling keys
+mi_key.c -- for handling keys
@item
mi_locking.c -- lock database
@item
-mi_log.c -- save commands in log file which myisamlog program can
-read
+mi_log.c -- save commands in a log file which myisamlog program can read. Can be used to exactly replay a set of changes to a table.
@item
mi_open.c -- open database
@item
-mi_packrec.c -- compress records
+mi_packrec.c -- read from a data file compresed with myisampack
@item
-mi_page.c -- read and write pages containing keys
+mi_page.c -- read and write pages containing keys
@item
-mi_panic.c -- the mi_panic routine, probably for sudden shutdowns
+mi_panic.c -- the mi_panic routine, probably for sudden shutdowns
@item
-mi_range.c -- approximate count of how many records lie between two
-keys
+mi_range.c -- approximate count of how many records lie between two keys
@item
-mi_rename.c -- rename a table
+mi_rename.c -- rename a table
@item
mi_rfirst.c -- read first row through a specific key (very short)
@item
-mi_rkey.c -- read a record using a key
+mi_rkey.c -- read a record using a key
@item
-mi_rlast.c -- read last row with same key as previously-read row
+mi_rlast.c -- read last row with same key as previously-read row
@item
-mi_rnext.c -- read next row with same key as previously-read row
+mi_rnext.c -- read next row with same key as previously-read row
@item
-mi_rnext_same.c -- same as mi_rnext.c, but abort if the key changes
+mi_rnext_same.c -- same as mi_rnext.c, but abort if the key changes
@item
mi_rprev.c -- read previous row with same key as previously-read row
@item
-mi_rrnd.c -- read a row based on position
+mi_rrnd.c -- read a row based on position
@item
-mi_rsame.c -- find current row using positional read or key-based
-read
+mi_rsame.c -- find current row using positional read or key-based read
@item
-mi_rsamepos.c -- positional read
+mi_rsamepos.c -- positional read
@item
-mi_scan.c -- read all rows sequentially
+mi_scan.c -- read all rows sequentially
@item
-mi_search.c -- key-handling functions
+mi_search.c -- key-handling functions
@item
mi_static.c -- static variables (very short)
@item
-mi_statrec.c -- functions to handle fixed-length records
+mi_statrec.c -- functions to handle fixed-length records
@item
-mi_test1.c -- testing basic functions
+mi_test1.c -- testing basic functions
@item
-mi_test2.c -- testing database and storing results
+mi_test2.c -- testing database and storing results
@item
-mi_test3.c -- testing locking
+mi_test3.c -- testing locking
@item
-mi_unique.c -- functions to check if a row is unique
+mi_unique.c -- functions to check if a row is unique
@item
-mi_update.c -- update an existing row
+mi_update.c -- update an existing row
@item
-mi_write.c -- insert a new row
+mi_write.c -- insert a new row
@end itemize
@*@*
@@ -4702,14 +4625,12 @@ There are other tests in these directories:
@item
sql-bench
@item
-repl-tests
-@item
tests
@end itemize
@subsection mysys
-MySQL system library (Low level routines for file access etc.).
+MySQL system library. Low level routines for file access and so on.
@*@*
There are 115 *.c programs in this directory:
@@ -4717,13 +4638,11 @@ There are 115 *.c programs in this directory:
@item
array.c -- Dynamic array handling
@item
-charset.c -- Using dynamic character sets, set default character
-set, ...
+charset.c -- Using dynamic character sets, set default character set, ...
@item
-charset2html.c -- Checking what character set a browser is using
+charset2html.c -- Check what character set a browser is using
@item
-checksum.c -- Calculate checksum for a memory block, used for
-pack_isam
+checksum.c -- Calculate checksum for a memory block, used for pack_isam
@item
default.c -- Find defaults from *.cnf or *.ini files
@item
@@ -4733,54 +4652,51 @@ hash.c -- Hash search/compare/free functions "for saving keys"
@item
list.c -- Double-linked lists
@item
-make-conf.c -- "Make a charset .conf file out of a ctype-charset.c
-file"
+make-conf.c -- "Make a charset .conf file out of a ctype-charset.c file"
@item
md5.c -- MD5 ("Message Digest 5") algorithm from RSA Data Security
@item
-mf_brkhant.c -- Prevent user from doing a Break during critical
-execution
+mf_brkhant.c -- Prevent user from doing a Break during critical execution (not used in MySQL; can be used by standalone MyISAM applications)
@item
-mf_cache.c -- "Open a temporary file and cache it with io_cache"
+mf_cache.c -- "Open a temporary file and cache it with io_cache"
@item
-mf_dirname.c -- Parse/convert directory names
+mf_dirname.c -- Parse/convert directory names
@item
-mf_fn_ext.c -- Get filename extension
+mf_fn_ext.c -- Get filename extension
@item
-mf_format.c -- Format a filename
+mf_format.c -- Format a filename
@item
-mf_getdate.c -- Get date, return in yyyy-mm-dd hh:mm:ss format
+mf_getdate.c -- Get date, return in yyyy-mm-dd hh:mm:ss format
@item
-mf_iocache.c -- Cached read/write of files in fixed-size units
+mf_iocache.c -- Cached read/write of files in fixed-size units
@item
-mf_iocache2.c -- Continuation of mf_iocache.c
+mf_iocache2.c -- Continuation of mf_iocache.c
@item
-mf_keycache.c -- Key block caching for certain file types
+mf_keycache.c -- Key block caching for certain file types
@item
mf_loadpath.c -- Return full path name (no ..\ stuff)
@item
mf_pack.c -- Packing/unpacking directory names for create purposes
@item
-mf_path.c -- Determine where a program can find its files
+mf_path.c -- Determine where a program can find its files
@item
-mf_qsort.c -- Quicksort
+mf_qsort.c -- Quicksort
@item
-mf_qsort2.c -- Quicksort, part 2
+mf_qsort2.c -- Quicksort, part 2 (allows the passing of an extra argument to the sort-compare routine)
@item
-mf_radix.c -- Radix sort
+mf_radix.c -- Radix sort
@item
-mf_same.c -- Determine whether filenames are the same
+mf_same.c -- Determine whether filenames are the same
@item
-mf_sort.c -- Sort with choice of Quicksort or Radix sort
+mf_sort.c -- Sort with choice of Quicksort or Radix sort
@item
-mf_soundex.c -- Soundex algorithm derived from EDN Nov. 14, 1985
-(pg. 36)
+mf_soundex.c -- Soundex algorithm derived from EDN Nov. 14, 1985 (pg. 36)
@item
-mf_strip.c -- Strip trail spaces from a string
+mf_strip.c -- Strip trail spaces from a string
@item
-mf_tempdir.c -- Initialize/find/free temporary directory
+mf_tempdir.c -- Initialize/find/free temporary directory
@item
-mf_tempfile.c -- Create a temporary file
+mf_tempfile.c -- Create a temporary file
@item
mf_unixpath.c -- Convert filename to UNIX-style filename
@item
@@ -4870,8 +4786,7 @@ free"
@item
my_open.c -- Open a file
@item
-my_os2cond.c -- OS2-specific: "A simple implementation of posix
-conditions"
+my_os2cond.c -- OS2-specific: "A simple implementation of posix conditions"
@item
my_os2dirsrch.c -- OS2-specific: Emulate a Win32 directory search
@item
@@ -4885,12 +4800,11 @@ my_os2thread.c -- OS2-specific: For thread handling
@item
my_os2tls.c -- OS2-specific: For thread-local storage
@item
-my_port.c -- AIX-specific: my_ulonglong2double()
+my_port.c -- OS/machine-dependent porting functions, e.g. AIX-specific my_ulonglong2double()
@item
my_pread.c -- Read a specified number of bytes from a file
@item
-my_pthread.c -- A wrapper for thread-handling functions in different
-OSs
+my_pthread.c -- A wrapper for thread-handling functions in different OSs
@item
my_quick.c -- Read/write (labelled a "quicker" interface, perhaps
obsolete)
@@ -4907,78 +4821,69 @@ my_rename.c -- Rename without delete
@item
my_seek.c -- Seek, i.e. point to a spot within a file
@item
-my_semaphore.c -- Semaphore routines, for use on OS that doesn't
-support them
+my_semaphore.c -- Semaphore routines, for use on OS that doesn't support them
@item
my_sleep.c -- Wait n microseconds
@item
-my_static.c -- Static-variable definitions
+my_static.c -- Static variables used by the mysys library
@item
-my_symlink.c -- Read a symbolic link (symlinks are a UNIX thing, I
-guess)
+my_symlink.c -- Read a symbolic link (symlinks are a UNIX thing, I guess)
@item
-my_symlink2.c -- Part 2 of my_symlink.c
+my_symlink2.c -- Part 2 of my_symlink.c
@item
-my_tempnam.c -- Obsolete temporary-filename routine used by ISAM
-table handler
+my_tempnam.c -- Obsolete temporary-filename routine used by ISAM table handler
@item
-my_thr_init.c -- initialize/allocate "all mysys & debug thread
-variables"
+my_thr_init.c -- initialize/allocate "all mysys & debug thread variables"
@item
-my_wincond.c -- Windows-specific: emulate Posix conditions
+my_wincond.c -- Windows-specific: emulate Posix conditions
@item
-my_winsem.c -- Windows-specific: emulate Posix threads
+my_winsem.c -- Windows-specific: emulate Posix threads
@item
-my_winthread.c -- Windows-specific: emulate Posix threads
+my_winthread.c -- Windows-specific: emulate Posix threads
@item
-my_write.c -- Write a specified number of bytes to a file
+my_write.c -- Write a specified number of bytes to a file
@item
-ptr_cmp.c -- Point to an optimal byte-comparison function
+ptr_cmp.c -- Point to an optimal byte-comparison function
@item
-queues.c -- Handle priority queues as in Robert Sedgewick's book
+queues.c -- Handle priority queues as in Robert Sedgewick's book
@item
raid2.c -- RAID support (the true implementation is in raid.cc)
@item
-rijndael.c -- "Optimised ANSI C code for the Rijndael cipher (now
-AES")
+rijndael.c -- "Optimised ANSI C code for the Rijndael cipher (now AES")
@item
-safemalloc.c -- A version of the standard malloc() with safety
-checking
+safemalloc.c -- A version of the standard malloc() with safety checking
@item
-sha1.c -- Implementation of Secure Hashing Algorithm 1
+sha1.c -- Implementation of Secure Hashing Algorithm 1
@item
-string.c -- Initialize/append/free dynamically-sized strings
+string.c -- Initialize/append/free dynamically-sized strings; see also sql_string.cc in the /sql directory
@item
-testhash.c -- Standalone program: test the hash library routines
+testhash.c -- Standalone program: test the hash library routines
@item
-test_charset.c -- Standalone program: display character set
-information
+test_charset.c -- Standalone program: display character set information
@item
-test_dir.c -- Standalone program: placeholder for "test all
-functions" idea
+test_dir.c -- Standalone program: placeholder for "test all functions" idea
@item
-test_fn.c -- Standalone program: apparently tests a function
+test_fn.c -- Standalone program: apparently tests a function
@item
-test_xml.c -- Standalone program: test XML routines
+test_xml.c -- Standalone program: test XML routines
@item
-thr_alarm.c -- Thread alarms and signal handling
+thr_alarm.c -- Thread alarms and signal handling
@item
-thr_lock.c -- "Read and write locks for Posix threads"
+thr_lock.c -- "Read and write locks for Posix threads"
@item
-thr_mutex.c -- A wrapper for mutex functions
+thr_mutex.c -- A wrapper for mutex functions
@item
-thr_rwlock.c -- Synchronizes the readers' thread locks with the
-writer's lock
+thr_rwlock.c -- Synchronizes the readers' thread locks with the writer's lock
@item
-tree.c -- Initialize/search/free binary trees
+tree.c -- Initialize/search/free binary trees
@item
-typelib.c -- Determine what type a field has
+typelib.c -- Find a string in a set of strings; returns the offset to the string found
@end itemize
@*@*
You can find documentation for the main functions in these files
-elsewhere in this document.
-For example, the main functions in my_getwd.c are described thus:
+elsewhere in this document. For example, the main functions in my_getwd.c
+are described thus:
@*@*
@example
@@ -5008,15 +4913,15 @@ testing.
These are the five *.c files, all from Novell Inc.:
@itemize @bullet
@item
-libmysqlmain.c -- Only one function: init_available_charsets()
+libmysqlmain.c -- Only one function: init_available_charsets()
@item
-my_manage.c -- Standalone management utility
+my_manage.c -- Standalone management utility
@item
-mysql_install_db.c -- Compare \scripts\mysql_install_db.sh
+mysql_install_db.c -- Compare \scripts\mysql_install_db.sh
@item
-mysql_test_run.c -- Short test program
+mysql_test_run.c -- Short test program
@item
-mysqld_safe.c -- Compare \scripts\mysqld_safe.sh
+mysqld_safe.c -- Compare \scripts\mysqld_safe.sh
@end itemize
Perhaps the most important file is:
@@ -5028,18 +4933,17 @@ netware.patch -- NetWare-specific build instructions and switches
@*@*
For instructions about basic installation, see "Deployment Guide For
-NetWare AMP" at:
+NetWare AMP" at:
@url{http://developer.novell.com/ndk/whitepapers/namp.htm}
@*
@subsection NEW-RPMS
-New "RPM Package Manager" files.
+Directory to place RPMs while making a distribution.
@*@*
-This directory is not part of the Windows distribution. Perhaps in
-MYSQL's Linux distribution it has files for use with Red Hat
-installations -- a point that needs checking someday.
+This directory is not part of the Windows distribution. It is
+a temporary directory used during RPM builds with Linux distributions.
@*@*
@subsection os2
@@ -5052,10 +4956,10 @@ people from outside MySQL: Yuri Dario, Timo Maier, and John M
Alfredsson. There are no .C program files in this directory.
@*@*
-The contents of \os2 are:
+The contents of \os2 are:
@itemize @bullet
@item
-A Readme.Txt file
+A Readme.Txt file
@item
An \include subdirectory containing .h files which are for OS/2 only
@item
@@ -5070,7 +4974,7 @@ there have been no updates for MySQL 4.0 for this section.
@subsection pstack
-Process stack display.
+Process stack display (not currently used).
@*@*
This is a set of publicly-available debugging aids which all do pretty
@@ -5088,7 +4992,7 @@ and it crashes.
@subsection regex
-Regular Expression library for support of REGEXP function.
+Henry Spencer's Regular Expression library for support of REGEXP function.
@*@*
This is the copyrighted product of Henry Spencer from the University
@@ -5112,31 +5016,9 @@ This program calls the 'regcomp' function, which is the entry point in
\regex\regexp.c.
@*@*
-@subsection repl-tests
-
-Test cases for replication.
-@*@*
-
-There are six short and trivial-looking tests in these subdirectories:
-@itemize @bullet
-@item
-\test-auto-inc -- Do auto-Increment columns work?
-@item
-\test-bad-query -- Does insert in PK column work?
-@item
-\test-dump -- Do LOAD statements work?
-@item
-\test-repl -- Does replication work?
-@item
-\test-repl-alter -- Does ALTER TABLE work?
-@item
-\test-repl-ts -- Does TIMESTAMP column work?
-@end itemize
-@*@*
-
@subsection SCCS
-Source Code Control System.
+Source Code Control System (not part of source distribution).
@*@*
You will see this directory if and only if you used BitKeeper for
@@ -5146,63 +5028,57 @@ administration and are not of interest to application programmers.
@subsection scripts
-SQL batches, e.g. for converting msql to MySQL.
+SQL batches, e.g. mysqlbug and mysql_install_db.
@*@*
-The *.sh filename extension apparently stands for "shell script".
-Linux programmers use it where Windows programmers would use a *.bat
+The *.sh filename extension stands for "shell script". Linux
+programmers use it where Windows programmers would use a *.bat
(batch filename extension).
@*@*
The *.sh files on this directory are:
@itemize @bullet
@item
-fill_help_tables.sh -- Create help-information tables and insert
+fill_help_tables.sh -- Create help-information tables and insert
@item
-make_binary_distribution.sh -- Get configure information, make,
-produce tar
+make_binary_distribution.sh -- Get configure information, make, produce tar
@item
-msql2mysql.sh -- Convert mSQL to MySQL
+msql2mysql.sh -- Convert (partly) mSQL programs and scripts to MySQL
@item
-mysqlbug.sh -- Create a bug report and mail it
+mysqlbug.sh -- Create a bug report and mail it
@item
-mysqld_multi.sh -- Start/stop any number of mysqld instances
+mysqld_multi.sh -- Start/stop any number of mysqld instances
@item
-mysqld_safe-watch.sh -- Start/restart in safe mode
+mysqld_safe-watch.sh -- Start/restart in safe mode
@item
-mysqld_safe.sh -- Start/restart in safe mode
+mysqld_safe.sh -- Start/restart in safe mode
@item
-mysqldumpslow.sh -- Parse and summarize the slow query log
+mysqldumpslow.sh -- Parse and summarize the slow query log
@item
-mysqlhotcopy.sh -- Hot backup
+mysqlhotcopy.sh -- Hot backup
@item
-mysql_config.sh -- Get configure information that client might need
+mysql_config.sh -- Get configuration information that might be needed to compile a client
@item
-mysql_convert_table_format.sh -- Conversion, e.g. from ISAM to
-MyISAM
+mysql_convert_table_format.sh -- Conversion, e.g. from ISAM to MyISAM
@item
-mysql_explain_log.sh -- Put a log (made with --log) into a MySQL
-table
+mysql_explain_log.sh -- Put a log (made with --log) into a MySQL table
@item
-mysql_find_rows.sh -- Search for queries containing <regexp>
+mysql_find_rows.sh -- Search for queries containing <regexp>
@item
-mysql_fix_extensions.sh -- Renames some file extensions, not
-recommended
+mysql_fix_extensions.sh -- Renames some file extensions, not recommended
@item
-mysql_fix_privilege_tables.sh -- Fix mysql.user etc. if upgrading to
-MySQL 3.23.14+
+mysql_fix_privilege_tables.sh -- Fix mysql.user etc. when upgrading. Can be safely run during any upgrade to get the newest
+MySQL privilege tables
@item
-mysql_install_db.sh -- Create privilege tables and func table
+mysql_install_db.sh -- Create privilege tables and func table
@item
-mysql_secure_installation.sh -- Disallow remote root login,
-eliminate test, etc.
+mysql_secure_installation.sh -- Disallow remote root login, eliminate test, etc.
@item
-mysql_setpermission.sh -- Aid to add users or databases, sets
-privileges
+mysql_setpermission.sh -- Aid to add users or databases, sets privileges
@item
mysql_tableinfo.sh -- Puts info re MySQL tables into a MySQL table
@item
-mysql_zap.sh -- Kill processes which match pattern
+mysql_zap.sh -- Kill processes which match pattern
@end itemize
@*@*
@@ -5214,197 +5090,191 @@ Programs for handling SQL commands. The "core" of MySQL.
These are the .c and .cc files in the sql directory:
@itemize @bullet
@item
-cache_manager.cc -- manages a number of blocks
+convert.cc -- convert tables between different character sets
@item
-convert.cc -- convert tables between different character sets
+derror.cc -- read language-dependent message file
@item
-derror.cc -- read language-dependent message file
+des_key_file.cc -- load DES keys from plaintext file
@item
-des_key_file.cc -- load DES keys from plaintext file
+field.cc -- "implement classes defined in field.h" (long); defines all storage methods MySQL uses to store field information
+into records that are then passed to handlers
@item
-field.cc -- "implement classes defined in field.h" (long)
+field_conv.cc -- functions to copy data between fields
@item
-field_conv.cc -- functions to copy data to or from fields
+filesort.cc -- sort a result set, using memory or temporary files
@item
-filesort.cc -- sort file
+frm_crypt.cc -- contains only one short function: get_crypt_for_frm
@item
-frm_crypt.cc -- contains only one short function: get_crypt_for_frm
+gen_lex_hash.cc -- Knuth's algorithm from Vol 3 Sorting and Searching, Chapter 6.3; used to search for SQL keywords in a query
@item
-gen_lex_hash.cc -- Knuth's algorithm from Vol 3 Sorting and
-Searching, Chapter 6.3
+gstream.cc -- GTextReadStream, used to read GIS objects
@item
-gstream.cc -- GTextReadStream
+handler.cc -- handler-calling functions
@item
-handler.cc -- handler-calling functions
+hash_filo.cc -- static-sized hash tables, used to store info like hostname -> ip tables in a FIFO manner
@item
-hash_filo.cc -- static-sized hash tables
+ha_berkeley.cc -- Handler: BDB
@item
-ha_berkeley.cc -- Handler: BDB
+ha_heap.cc -- Handler: Heap
@item
-ha_heap.cc -- Handler: Heap
+ha_innodb.cc -- Handler: InnoDB
@item
-ha_innodb.cc -- Handler: InnoDB
-@item
-ha_isam.cc -- Handler: ISAM
+ha_isam.cc -- Handler: ISAM
@item
ha_isammrg.cc -- Handler: (ISAM MERGE)
@item
-ha_myisam.cc -- Handler: MyISAM
+ha_myisam.cc -- Handler: MyISAM
@item
ha_myisammrg.cc -- Handler: (MyISAM MERGE)
@item
-hostname.cc -- Given IP, return hostname
+hostname.cc -- Given IP, return hostname
@item
-init.cc -- Init and dummy functions for interface with unireg
+init.cc -- Init and dummy functions for interface with unireg
@item
-item.cc -- Item functions
+item.cc -- Item functions
@item
-item_buff.cc -- Buffers to save and compare item values
+item_buff.cc -- Buffers to save and compare item values
@item
-item_cmpfunc.cc -- Definition of all compare functions
+item_cmpfunc.cc -- Definition of all compare functions
@item
-item_create.cc -- Create an item. Used by lex.h.
+item_create.cc -- Create an item. Used by lex.h.
@item
-item_func.cc -- Numerical functions
+item_func.cc -- Numerical functions
@item
-item_row.cc -- Row items for comparing rows and for IN on rows
+item_row.cc -- Row items for comparing rows and for IN on rows
@item
-item_sum.cc -- Set functions (sum, avg, etc.)
+item_sum.cc -- Set functions (SUM, AVG, etc.)
@item
-item_strfunc.cc -- String functions
+item_strfunc.cc -- String functions
@item
-item_subselect.cc -- Item subselect
+item_subselect.cc -- Item subselect
@item
-item_timefunc.cc -- Date/time functions, e.g. week of year
+item_timefunc.cc -- Date/time functions, e.g. week of year
@item
-item_uniq.cc -- Empty file, here for compatibility reasons
+item_uniq.cc -- Empty file, here for compatibility reasons
@item
-key.cc -- Functions to handle keys and fields in forms
+key.cc -- Functions to create keys from records and compare a key to a key in a record
@item
-lock.cc -- Locks
+lock.cc -- Locks
@item
-log.cc -- Logs
+log.cc -- Logs
@item
-log_event.cc -- Log event
+log_event.cc -- Log event (a binary log consists of a stream of log events)
@item
-matherr.c -- Handling overflow, underflow, etc.
+matherr.c -- Handling overflow, underflow, etc.
@item
-mf_iocache.cc -- Caching of (sequential) reads
+mf_iocache.cc -- Caching of (sequential) reads and writes
@item
-mini_client.cc -- Client included in server for server-server
-messaging
+mini_client.cc -- Client included in server for server-server messaging; used by the replication code
@item
-mysqld.cc -- Source of mysqld.exe
+mysqld.cc -- Source of mysqld.exe; includes the main() program that starts mysqld, handling of signals and connections
@item
-my_lock.c -- Lock part of a file
+my_lock.c -- Lock part of a file (like /mysys/my_lock.c, but with timeout handling for threads)
@item
-net_serv.cc -- Read/write of packets on a network socket
+net_serv.cc -- Read/write of packets on a network socket
@item
-nt_servc.cc -- Initialize/register/remove an NT service
+nt_servc.cc -- Initialize/register/remove an NT service
@item
opt_ft.cc -- Create a FT or QUICK RANGE based on a key (very short)
-* opt_range.cc -- Range of keys
+@item
+opt_range.cc -- Range of keys
@item
opt_sum.cc -- Optimize functions in presence of (implied) GROUP BY
@item
-password.c -- Password checking
+password.c -- Password checking
@item
-procedure.cc -- Procedure
+procedure.cc -- Procedure interface, as used in SELECT * FROM Table_name PROCEDURE ANALYSE
@item
-protocol.cc -- Low level functions for storing data to be sent to
-client
+protocol.cc -- Low level functions for PACKING data that is sent to client; actual sending done with net_serv.cc
@item
-records.cc -- Functions to read, write, and lock records
+records.cc -- Functions for easy reading of records, possible through a cache
@item
-repl_failsafe.cc -- Replication fail-save
+repl_failsafe.cc -- Replication fail-save (not yet implemented)
@item
-set_var.cc -- MySQL variables
+set_var.cc -- Set and retrieve MySQL user variables
@item
-slave.cc -- Procedures for a slave in a master/slave (replication?)
-relation
+slave.cc -- Procedures for a slave in a master/slave (replication) relation
@item
spatial.cc -- Geometry stuff (lines, points, etc.)
@item
-sql_acl.cc -- Functions related to ACL security
+sql_acl.cc -- Functions related to ACL security; checks, stores, retrieves, and deletes MySQL user level privileges
@item
-sql_analyse.cc -- Analyse an input string (?)
+sql_analyse.cc -- Implements the PROCEDURE analyse, which analyses a query result and returns the 'optimal' data type for each result column
@item
-sql_base.cc -- Basic functions needed by many modules
+sql_base.cc -- Basic functions needed by many modules, like opening and closing tables with table cache management
@item
-sql_cache.cc -- SQL cache, with long comments about how caching
-works
+sql_cache.cc -- SQL query cache, with long comments about how caching works
@item
-sql_class.cc -- SQL class
+sql_class.cc -- SQL class; implements the SQL base classes, of which THD (THREAD object) is the most important
@item
-sql_crypt.cc -- Encode / decode, very short
+sql_crypt.cc -- Encode / decode, very short
@item
-sql_db.cc -- Create / drop database
+sql_db.cc -- Create / drop database
@item
-sql_delete.cc -- The DELETE statement
+sql_delete.cc -- The DELETE statement
@item
-sql_derived.cc -- Derived tables, with long comments
+sql_derived.cc -- Derived tables, with long comments
@item
-sql_do.cc -- The DO statement
+sql_do.cc -- The DO statement
@item
-sql_error.cc -- Errors and warnings
+sql_error.cc -- Errors and warnings
@item
-sql_handler.cc -- Direct access to ISAM
+sql_handler.cc -- Implements the HANDLER interface, which gives direct access to rows in MyISAM and InnoDB
@item
-sql_help.cc -- The HELP statement (if there is one?)
+sql_help.cc -- The HELP statement
@item
-sql_insert.cc -- The INSERT statement
+sql_insert.cc -- The INSERT statement
@item
-sql_lex.cc -- Related to lex or yacc
+sql_lex.cc -- Does lexical analysis of a query; i.e. breaks a query string into pieces and determines the basic type (number,
+string, keyword, etc.) of each piece
@item
-sql_list.cc -- Only list_node_end_of_list, short
+sql_list.cc -- Only list_node_end_of_list, short (the rest of the list class is implemented in sql_list.h)
@item
-sql_load.cc -- The LOAD DATA statement?
+sql_load.cc -- The LOAD DATA statement
@item
-sql_map.cc -- Memory-mapped files?
+sql_map.cc -- Memory-mapped files (not yet in use)
@item
-sql_manager.cc -- Maintenance tasks, e.g. flushing the buffers
-periodically
+sql_manager.cc -- Maintenance tasks, e.g. flushing the buffers periodically; used with BDB table logs
@item
-sql_olap.cc -- ROLLUP
+sql_olap.cc -- ROLLUP
@item
-sql_parse.cc -- Parse an SQL statement
+sql_parse.cc -- Parse an SQL statement; do initial checks and then jump to the function that should execute the statement
@item
-sql_prepare.cc -- Prepare an SQL statement
+sql_prepare.cc -- Prepare an SQL statement, or use a prepared statement
@item
-sql_repl.cc -- Replication
+sql_repl.cc -- Replication
@item
-sql_rename.cc -- Rename table
+sql_rename.cc -- Rename table
@item
-sql_select.cc -- Select and join optimisation
+sql_select.cc -- Select and join optimisation
@item
-sql_show.cc -- The SHOW statement
+sql_show.cc -- The SHOW statement
@item
-sql_string.cc -- String functions: alloc, realloc, copy, convert,
-etc.
+sql_string.cc -- String functions: alloc, realloc, copy, convert, etc.
@item
-sql_table.cc -- The DROP TABLE and ALTER TABLE statements
+sql_table.cc -- The DROP TABLE and ALTER TABLE statements
@item
-sql_test.cc -- Some debugging information
+sql_test.cc -- Some debugging information
@item
-sql_udf.cc -- User-defined functions
+sql_udf.cc -- User-defined functions
@item
-sql_union.cc -- The UNION operator
+sql_union.cc -- The UNION operator
@item
-sql_update.cc -- The UPDATE statement
+sql_update.cc -- The UPDATE statement
@item
-stacktrace.c -- Display stack trace (Linux/Intel only?)
+stacktrace.c -- Display stack trace (Linux/Intel only)
@item
-table.cc -- Table metadata retrieval, mostly
+table.cc -- Table metadata retrieval; read the table definition from a .frm file and store it in a TABLE object
@item
-thr_malloc.cc -- Mallocs used in threads
+thr_malloc.cc -- Thread-safe interface to /mysys/my_alloc.c
@item
-time.cc -- Date and time functions
+time.cc -- Date and time functions
@item
-udf_example.cc -- Example file of user-defined functions
+udf_example.cc -- Example file of user-defined functions
@item
-uniques.cc -- Function to handle quick removal of duplicates
+uniques.cc -- Function to handle quick removal of duplicates
@item
-unireg.cc -- Create a unireg form file from a FIELD and field-info struct
+unireg.cc -- Create a unireg form file (.frm) from a FIELD and field-info struct
@end itemize
@*@*
@@ -5422,17 +5292,15 @@ available all the material necessary to reproduce all the tests.
There are five subdirectories and sub-subdirectories:
@itemize @bullet
@item
-\Comments -- Comments about results from tests of Access, Adabas,
-etc.
+\Comments -- Comments about results from tests of Access, Adabas, etc.
@item
-\Data\ATIS -- .txt files containing input data for the "ATIS" tests
+\Data\ATIS -- .txt files containing input data for the "ATIS" tests
@item
-\Data\Wisconsin -- .txt files containing input data for the
-"Wisconsin" tests
+\Data\Wisconsin -- .txt files containing input data for the "Wisconsin" tests
@item
-\Results -- old test results
+\Results -- old test results
@item
-\Results-win32 -- old test results from Windows 32-bit tests
+\Results-win32 -- old test results from Windows 32-bit tests
@end itemize
@*@*
@@ -5448,7 +5316,8 @@ There is one README file and one TODO file.
@subsection SSL
-Secure Sockets Layer.
+Secure Sockets Layer; includes an example certification one can use
+test an SSL (secure) database connection.
@*@*
This isn't a code directory. It contains a short note from Tonu Samuel
@@ -5477,7 +5346,7 @@ recent Pentium class processors, though.
The .C files are:
@itemize @bullet
@item
-atof.c -- ascii-to-float, MySQL version
+atof.c -- ascii-to-float, MySQL version
@item
bchange.c -- short replacement routine written by Monty Widenius in
1987
@@ -5499,8 +5368,7 @@ bmove_upp.c -- bmove.c variant, starting with last byte
@item
bzero.c -- something like bfill with an argument of 0
@item
-conf_to_src.c -- reading a configuration file (NOTE TO SELF ? what's
-this doing here?)
+conf_to_src.c -- reading a configuration file
@item
ctype*.c -- string handling programs for each char type MySQL
handles
@@ -5526,7 +5394,7 @@ r_strinstr.c -- see if one string is within another
@item
str2int.c -- convert string to integer
@item
-strappend.c -- append one string to another
+strappend.c -- fill up a string to n characters
@item
strcat.c -- concatenate strings
@item
@@ -5546,11 +5414,11 @@ strinstr.c -- find string within string
@item
strlen.c -- return length of string in bytes
@item
-strmake.c -- move n characters, or move till end
+strmake.c -- create new string from old string with fixed length, append end \0 if needed
@item
-strmov.c -- move source to dest and return pointer to end
+strmov.c -- move source to dest and return pointer to end
@item
-strnlen.c -- return length of string, or return n
+strnlen.c -- return min(length of string, n)
@item
strnmov.c -- move source to dest for source size, or for n bytes
@item
@@ -5574,9 +5442,9 @@ strxnmov.c -- like strxmov.c but with a maximum length n
@item
str_test.c -- test of all the string functions encoded in assembler
@item
-udiv.c -- unsigned long divide
+udiv.c -- unsigned long divide, for operating systems that don't support these
@item
-xml.c -- read and parse XML strings
+xml.c -- read and parse XML strings; used to read character definition information stored in /sql/share/charsets
@end itemize
@*@*
@@ -5588,21 +5456,41 @@ members of the Intel processor family.
@subsection support-files
-Support files.
+Files used to build MySQL on different systems.
@*@*
The files here are for building ("making") MySQL given a package
manager, compiler, linker, and other build tools. The support files
-provide instructions and switches for the build processes.
+provide instructions and switches for the build processes. They
+include example my.cnf files one can use as a default setup for
+MySQL.
@*@*
@subsection tests
-Tests in Perl.
+Tests in Perl and in C.
@*@*
-These are tests that were run once to check for bugs in various
-scenarios: forks, locks, big records, exporting, truncating, etc.
+The files in this directory are test programs that can be used
+as a base to write a program to simulate problems in MySQL in various
+scenarios: forks, locks, big records, exporting, truncating, and so on.
+Some examples are:
+@itemize @bullet
+@item
+connect_test.c -- test that a connect is possible
+@item
+insert_test.c -- test that an insert is possible
+@item
+list_test.c -- test that a select is possible
+@item
+select_test.c -- test that a select is possible
+@item
+showdb_test.c -- test that a show-databases is possible
+@item
+ssl_test.c -- test that SSL is possible
+@item
+thread_test.c -- test that threading is possible
+@end itemize
@*@*
@subsection tools
@@ -5613,7 +5501,9 @@ Tools -- well, actually, one tool.
The only file is:
@itemize @bullet
@item
-mysqlmanager.c -- A "server management daemon" by Sasha Pachev
+mysqlmanager.c -- A "server management daemon" by Sasha Pachev. This
+is a tool under development and is not yet useful. Related to fail-safe
+replication.
@end itemize
@*@*
@@ -5625,11 +5515,16 @@ Visual C++ Files.
Includes this entire directory, repeated for VC++ (Windows) use.
@*@*
-VC++Files has subdirectories which are copies of the main directories.
-For example there is a subdirectory \VC++Files\heap, which has the
-same files as \heap. So for a description of the files in
-\VC++Files\heap, see the description of the files in \heap. The same
-applies for almost all of VC++Files's subdirectories (bdb, client,
+VC++Files includes a complete environment to compile MySQL with the VC++
+compiler. To use it, just copy the files on this directory; the make_win_src_distribution.sh
+script uses these files to create a Windows source installation.
+@*@*
+
+This directory has subdirectories which are copies of the main directories.
+For example, there is a subdirectory \VC++Files\heap, which has the Microsoft
+developer studio project file to compile \heap with VC++. So for a description
+of the files in \VC++Files\heap, see the description of the files in \heap. The
+same applies for almost all of VC++Files's subdirectories (bdb, client,
isam, libmysql, etc.). The difference is that the \VC++Files variants
are specifically for compilation with Microsoft Visual C++ in 32-bit
Windows environments.
@@ -5640,54 +5535,60 @@ directories", VC++Files contains these subdirectories, which are not
duplicates:
@itemize @bullet
@item
-comp_err -- (nearly empty)
+comp_err -- (nearly empty)
@item
-contrib -- (nearly empty)
+contrib -- (nearly empty)
@item
-InstallShield script files
+InstallShield -- script files
@item
-isamchk -- (nearly empty)
+isamchk -- (nearly empty)
@item
-libmysqltest -- one small non-MySQL test program: mytest.c
+libmysqltest -- one small non-MySQL test program: mytest.c
@item
-myisamchk -- (nearly empty)
+myisamchk -- (nearly empty)
@item
-myisamlog -- (nearly empty)
+myisamlog -- (nearly empty)
@item
-myisammrg -- (nearly empty)
+myisammrg -- (nearly empty)
@item
-mysqlbinlog -- (nearly empty)
+mysqlbinlog -- (nearly empty)
@item
-mysqlmanager -- MFC foundation class files created by AppWizard
+mysqlmanager -- MFC foundation class files created by AppWizard
@item
-mysqlserver -- (nearly empty)
+mysqlserver -- (nearly empty)
@item
-mysqlshutdown -- one short program, mysqlshutdown.c
+mysqlshutdown -- one short program, mysqlshutdown.c
@item
-mysqlwatch.c -- Windows service initialization and monitoring
+mysqlwatch.c -- Windows service initialization and monitoring
@item
-my_print_defaults -- (nearly empty)
+my_print_defaults -- (nearly empty)
@item
-pack_isam -- (nearly empty)
+pack_isam -- (nearly empty)
@item
-perror -- (nearly empty)
+perror -- (nearly empty)
@item
-prepare -- (nearly empty)
+prepare -- (nearly empty)
@item
-replace -- (nearly empty)
+replace -- (nearly empty)
@item
-SCCS -- source code control system
+SCCS -- source code control system
@item
-test1 -- tests connecting via X threads
+test1 -- tests connecting via X threads
@item
-thr_insert_test -- (nearly empty)
+thr_insert_test -- (nearly empty)
@item
thr_test -- one short program used to test for memory-allocation bug
@item
-winmysqladmin -- the winmysqladmin.exe source. machine-generated?
+winmysqladmin -- the winmysqladmin.exe source
@end itemize
@*@*
+The "nearly empty" subdirectories noted above (e.g. comp_err and isamchk)
+are needed because VC++ requires one directory per project (i.e. executable).
+We are trying to keep to the MySQL standard source layout and compile only
+to different directories.
+@*@*
+
@subsection vio
Virtual I/O Library.
@@ -5735,7 +5636,12 @@ obsolete.
@subsection zlib
-Data compression library.
+Data compression library, used on Windows.
+@*@*
+
+zlib is a data compression library used to support the compressed
+protocol and the COMPRESS/UNCOMPRESS functions under Windows.
+On Unix, MySQL uses the system libgz.a library for this purpose.
@*@*
Zlib -- which presumably stands for "Zip Library" -- is not a MySQL
@@ -5745,11 +5651,11 @@ variation of the famous "Lempel-Ziv" method, which is also used by
bytes is as follows:
@itemize @bullet
@item
-Find a substring which occurs twice in the string.
+Find a substring which occurs twice in the string.
@item
Replace the second occurrence of the substring with (a) a pointer to
the first occurrence, plus (b) an indication of the length of the
-first occurrence.
+first occurrence.
@end itemize
There is a full description of the library's functions in the gzip
@@ -5758,11 +5664,11 @@ manual at: @*
There is therefore no need to list the modules in this document.
@*@*
-The MySQL program that uses zlib is \mysys\my_compress.c. The use is
-for packet compression. The client sends messages to the server which
-are compressed by zlib. See also: \sql\net_serv.cc.
+The MySQL program \mysys\my_compress.c uses zlib for packet compression.
+The client sends messages to the server which are compressed by zlib.
+See also: \sql\net_serv.cc.
-@node Files in InnoDB Sources,,Files in MySQL Sources,Top
+@node Files in InnoDB Sources, , Files in MySQL Sources, Top
@chapter Annotated List Of Files in the InnoDB Source Code Distribution
ERRATUM BY HEIKKI TUURI (START)
diff --git a/Docs/manual_toc.html b/Docs/manual_toc.html
new file mode 100644
index 00000000000..b9014e5efb9
--- /dev/null
+++ b/Docs/manual_toc.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>Place holder for manual_toc.html</title>
+</head>
+<body>
+This is just a place holder for the autogenerated manual_toc.html
+to make "make dist" happy.
+</body>
+</html>
diff --git a/Images/.cvsignore b/Images/.cvsignore
deleted file mode 100644
index 6d0d61a83d5..00000000000
--- a/Images/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-logo_nusphere_b.tif
diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp
index 1a276c75447..e27b4977a7c 100644
--- a/VC++Files/libmysql/libmysql.dsp
+++ b/VC++Files/libmysql/libmysql.dsp
@@ -25,7 +25,7 @@ CFG=libmysql - Win32 Debug
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
-CPP=cl.exe
+CPP=xicl6.exe
MTL=midl.exe
RSC=rc.exe
@@ -52,7 +52,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release"
# SUBTRACT LINK32 /pdb:none
@@ -85,7 +85,7 @@ PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release /y
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
-LINK32=link.exe
+LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug"
# SUBTRACT LINK32 /pdb:none
@@ -251,6 +251,10 @@ SOURCE=..\mysys\mf_pack.c
# End Source File
# Begin Source File
+SOURCE=..\mysys\mf_path.c
+# End Source File
+# Begin Source File
+
SOURCE=..\mysys\mf_unixpath.c
# End Source File
# Begin Source File
diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw
index eef82588fa8..9903c91ba1b 100644
--- a/VC++Files/mysql.dsw
+++ b/VC++Files/mysql.dsw
@@ -605,6 +605,9 @@ Package=<5>
Package=<4>
{{{
+ Begin Project Dependency
+ Project_Dep_Name strings
+ End Project Dependency
}}}
###############################################################################
diff --git a/acinclude.m4 b/acinclude.m4
index 970620d9be7..269b505386c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -78,7 +78,7 @@ AC_LANG_SAVE
AC_LANG_CPLUSPLUS
if test "$ac_cv_prog_gxx" = "yes"
then
- CXXFLAGS="$CXXFLAGS -Werror"
+ CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'`
fi
mysql_cv_btype_last_arg_accept=none
[AC_TRY_COMPILE([#if defined(inline)
diff --git a/client/mysql.cc b/client/mysql.cc
index 2623660033b..155d8b03231 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1091,7 +1091,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
{ // Add found char to buffer
if (inchar == *in_string)
*in_string=0;
- else if (!*in_string && (inchar == '\'' || inchar == '"'))
+ else if (!*in_string && (inchar == '\'' || inchar == '"' || inchar == '`'))
*in_string=(char) inchar;
if (!(*ml_comment))
*out++ = (char) inchar;
@@ -2709,31 +2709,32 @@ select_limit, max_join_size);
static int
put_info(const char *str,INFO_TYPE info_type,uint error)
{
+ FILE *file= (info_type == INFO_ERROR ? stderr : stdout);
static int inited=0;
if (status.batch)
{
if (info_type == INFO_ERROR)
{
- (void) fflush(stdout);
- fprintf(stderr,"ERROR");
+ (void) fflush(file);
+ fprintf(file,"ERROR");
if (error)
- (void) fprintf(stderr," %d",error);
+ (void) fprintf(file," %d",error);
if (status.query_start_line && line_numbers)
{
- (void) fprintf(stderr," at line %lu",status.query_start_line);
+ (void) fprintf(file," at line %lu",status.query_start_line);
if (status.file_name)
- (void) fprintf(stderr," in file: '%s'", status.file_name);
+ (void) fprintf(file," in file: '%s'", status.file_name);
}
- (void) fprintf(stderr,": %s\n",str);
- (void) fflush(stderr);
+ (void) fprintf(file,": %s\n",str);
+ (void) fflush(file);
if (!ignore_errors)
return 1;
}
else if (info_type == INFO_RESULT && verbose > 1)
- tee_puts(str, stdout);
+ tee_puts(str, file);
if (unbuffered)
- fflush(stdout);
+ fflush(file);
return info_type == INFO_ERROR ? -1 : 0;
}
if (!opt_silent || info_type == INFO_ERROR)
@@ -2751,17 +2752,17 @@ put_info(const char *str,INFO_TYPE info_type,uint error)
putchar('\007'); /* This should make a bell */
vidattr(A_STANDOUT);
if (error)
- (void) tee_fprintf(stderr, "ERROR %d: ", error);
+ (void) tee_fprintf(file, "ERROR %d: ", error);
else
- tee_puts("ERROR: ", stdout);
+ tee_puts("ERROR: ", file);
}
else
vidattr(A_BOLD);
- (void) tee_puts(str, stdout);
+ (void) tee_puts(str, file);
vidattr(A_NORMAL);
}
if (unbuffered)
- fflush(stdout);
+ fflush(file);
return info_type == INFO_ERROR ? -1 : 0;
}
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 3f85f0be008..36508cdf5f4 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -44,6 +44,7 @@ static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
void sql_print_error(const char *format, ...);
static bool one_database = 0;
+static bool force_opt= 0;
static const char* database;
static bool short_form = 0;
static ulonglong offset = 0;
@@ -199,6 +200,9 @@ static struct my_option my_long_options[] =
{"database", 'd', "List entries for just this database (local log only)",
(gptr*) &database, (gptr*) &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
+ {"force-read", 'f', "Force reading unknown binlog events",
+ (gptr*) &force_opt, (gptr*) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+ 0, 0},
{"help", '?', "Display this help and exit",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Get the binlog from server", (gptr*) &host, (gptr*) &host,
diff --git a/client/mysqldump.c b/client/mysqldump.c
index b5e596ba072..17780458a2a 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1613,7 +1613,7 @@ int main(int argc, char **argv)
else
{
row = mysql_fetch_row(master);
- if (row[0] && row[1])
+ if (row && row[0] && row[1])
{
fprintf(md_result_file,
"\n--\n-- Position to start replication from\n--\n\n");
diff --git a/configure.in b/configure.in
index 90c8e81bd47..c0ce5221832 100644
--- a/configure.in
+++ b/configure.in
@@ -1005,8 +1005,9 @@ case $SYSTEM_TYPE in
*darwin5*)
if test "$ac_cv_prog_gcc" = "yes"
then
- CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
- CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE"
+ FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
+ CFLAGS="$CFLAGS $FLAGS"
+ CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O"
with_named_curses=""
fi
@@ -1014,8 +1015,9 @@ case $SYSTEM_TYPE in
*darwin6*)
if test "$ac_cv_prog_gcc" = "yes"
then
- CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
- CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE"
+ FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
+ CFLAGS="$CFLAGS $FLAGS"
+ CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O"
fi
;;
@@ -1365,10 +1367,8 @@ then
with_named_thread="-Kthread -lsocket -lnsl"
if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
then
-# AC_DEFINE(HAVE_OpenUNIX8_THREADS)
AC_DEFINE(HAVE_UNIXWARE7_THREADS)
else
-# AC_DEFINE(HAVE_OpenUNIX8_POSIX)
AC_DEFINE(HAVE_UNIXWARE7_POSIX)
fi
# We must have cc
@@ -1377,10 +1377,8 @@ then
then
{ echo "configure: error: On OpenUNIX8 and UnixWare7 MySQL must be compiled with cc. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
else
-# CC="$CC -Kthread -DOpenUNIX8";
-# CXX="$CXX -Kthread -DOpenUNIX8";
- CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
+ CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
+ CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
fi
AC_MSG_RESULT("yes")
else
@@ -1877,7 +1875,7 @@ AC_LANG_SAVE
AC_LANG_CPLUSPLUS
if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
then
- CXXFLAGS="$CXXFLAGS -Werror"
+ CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'`
fi
AC_TRY_COMPILE(
[#undef inline
@@ -1909,7 +1907,7 @@ AC_LANG_SAVE
AC_LANG_CPLUSPLUS
if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
then
- CXXFLAGS="$CXXFLAGS -Werror"
+ CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'`
fi
AC_TRY_COMPILE(
[#undef inline
diff --git a/include/Makefile.am b/include/Makefile.am
index 7372d3ab417..3a197c310aa 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -35,7 +35,7 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \
SUPERCLEANFILES = mysql_version.h my_config.h
# Some include files that may be moved and patched by configure
-DISTCLEANFILES = sched.h
+DISTCLEANFILES = sched.h $(SUPERCLEANFILES)
clean:
$(RM) -f readline/*
diff --git a/include/config-win.h b/include/config-win.h
index 0e01aa75570..b0a30353196 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -153,6 +153,9 @@ typedef uint rf_SetTimer;
#define USE_MB_IDENT 1
#define USE_STRCOLL 1
+/* If LOAD DATA LOCAL INFILE should be enabled by default */
+#define ENABLED_LOCAL_INFILE 1
+
/* Convert some simple functions to Posix */
#define sigset(A,B) signal((A),(B))
diff --git a/include/my_base.h b/include/my_base.h
index b806436fe0e..ac41d9e50ef 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -225,6 +225,7 @@ enum ha_base_keytype {
/* Errorcodes given by functions */
+/* opt_sum_query() assumes these codes are > 1 */
#define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */
#define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */
#define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */
diff --git a/include/my_global.h b/include/my_global.h
index 510de43c9ee..86fb2a5ee4d 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -287,6 +287,10 @@ C_MODE_END
#include <asm/atomic.h>
#endif
#include <errno.h> /* Recommended by debian */
+/* We need the following to go around a problem with openssl on solaris */
+#if defined(HAVE_CRYPT_H)
+#include <crypt.h>
+#endif
/* Go around some bugs in different OS and compilers */
#if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H)
@@ -306,9 +310,7 @@ C_MODE_END
/* This has to be after include limits.h */
#define HAVE_ERRNO_AS_DEFINE
#define HAVE_FCNTL_LOCK
-#undef HAVE_SYS_UN_H
#undef HAVE_FINITE
-#undef HAVE_RINT
#undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */
#undef LONGLONG_MAX /* standard system library 'limits.h' */
#endif
@@ -377,7 +379,7 @@ typedef unsigned short ushort;
#define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1))
#define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0])))
#ifndef HAVE_RINT
-#define rint(A) floor((A)+0.5)
+#define rint(A) floor((A)+(((A) < 0)? -0.5 : 0.5))
#endif
/* Define some general constants */
diff --git a/include/my_pthread.h b/include/my_pthread.h
index 58f89517679..bff82ef7320 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -248,6 +248,11 @@ extern int my_sigwait(const sigset_t *set,int *sig);
#error Requires at least rev 2 of EMX pthreads library.
#endif
+#ifdef __NETWARE__
+void my_pthread_exit(void *status);
+#define pthread_exit(A) my_pthread_exit(A)
+#endif
+
extern int my_pthread_getprio(pthread_t thread_id);
#define pthread_key(T,V) pthread_key_t V
diff --git a/include/my_semaphore.h b/include/my_semaphore.h
index 3431212ec82..7f182bea6bf 100644
--- a/include/my_semaphore.h
+++ b/include/my_semaphore.h
@@ -31,6 +31,8 @@
#ifndef _my_semaphore_h_
#define _my_semaphore_h_
+#ifdef THREAD
+
C_MODE_START
#ifdef HAVE_SEMAPHORE_H
#include <semaphore.h>
@@ -56,4 +58,7 @@ int sem_getvalue(sem_t * sem, unsigned int * sval);
#endif /* !__bsdi__ */
C_MODE_END
+
+#endif /* THREAD */
+
#endif /* !_my_semaphore_h_ */
diff --git a/include/my_sys.h b/include/my_sys.h
index 86ca6ec6a1f..a2dd4c987a7 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -744,6 +744,7 @@ extern my_bool my_uncompress(byte *, ulong *, ulong *);
extern byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen);
extern ulong checksum(const byte *mem, uint count);
extern uint my_bit_log2(ulong value);
+uint my_count_bits(ulonglong v);
extern void my_sleep(ulong m_seconds);
#ifdef __WIN__
diff --git a/include/violite.h b/include/violite.h
index a5c063700b4..3b61fbf344e 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -165,7 +165,7 @@ my_bool vio_ssl_should_retry(Vio* vio);
int vio_ssl_close(Vio* vio);
/* Return last error number */
int vio_ssl_errno(Vio *vio);
-my_bool vio_ssl_peer_addr(Vio* vio, char *buf);
+my_bool vio_ssl_peer_addr(Vio* vio, char *buf, uint16 *port);
void vio_ssl_in_addr(Vio *vio, struct in_addr *in);
int vio_ssl_blocking(Vio * vio, my_bool set_blocking_mode, my_bool *old_mode);
@@ -242,7 +242,7 @@ struct st_vio
my_bool (*is_blocking)(Vio*);
int (*viokeepalive)(Vio*, my_bool);
int (*fastsend)(Vio*);
- my_bool (*peer_addr)(Vio*, gptr, uint16*);
+ my_bool (*peer_addr)(Vio*, char *, uint16*);
void (*in_addr)(Vio*, struct in_addr*);
my_bool (*should_retry)(Vio*);
int (*vioclose)(Vio*);
diff --git a/innobase/btr/Makefile.am b/innobase/btr/Makefile.am
index 6e3dd4fb007..ed61facb695 100644
--- a/innobase/btr/Makefile.am
+++ b/innobase/btr/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libbtr.a
+noinst_LIBRARIES = libbtr.a
libbtr_a_SOURCES = btr0btr.c btr0cur.c btr0pcur.c btr0sea.c
diff --git a/innobase/buf/Makefile.am b/innobase/buf/Makefile.am
index b1463c2220e..3f56c8b02d7 100644
--- a/innobase/buf/Makefile.am
+++ b/innobase/buf/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libbuf.a
+noinst_LIBRARIES = libbuf.a
libbuf_a_SOURCES = buf0buf.c buf0flu.c buf0lru.c buf0rea.c
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 14d538a14bc..1cdddaf6cb4 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -597,8 +597,9 @@ buf_pool_init(
/* Wipe contents of frame to eliminate a Purify
warning */
+#ifdef HAVE_purify
memset(block->frame, '\0', UNIV_PAGE_SIZE);
-
+#endif
if (srv_use_awe) {
/* Add to the list of blocks mapped to
frames */
@@ -1837,7 +1838,7 @@ buf_pool_invalidate(void)
freed = TRUE;
while (freed) {
- freed = buf_LRU_search_and_free_block(0);
+ freed = buf_LRU_search_and_free_block(100);
}
mutex_enter(&(buf_pool->mutex));
@@ -2057,6 +2058,29 @@ buf_get_n_pending_ios(void)
}
/*************************************************************************
+Returns the ratio in percents of modified pages in the buffer pool /
+database pages in the buffer pool. */
+
+ulint
+buf_get_modified_ratio_pct(void)
+/*============================*/
+{
+ ulint ratio;
+
+ mutex_enter(&(buf_pool->mutex));
+
+ ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
+ / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
+ + UT_LIST_GET_LEN(buf_pool->free));
+
+ /* 1 + is there to avoid division by zero */
+
+ mutex_exit(&(buf_pool->mutex));
+
+ return(ratio);
+}
+
+/*************************************************************************
Prints info of the buffer i/o. */
void
@@ -2109,8 +2133,10 @@ buf_print_io(
buf += sprintf(buf,
"Pending writes: LRU %lu, flush list %lu, single page %lu\n",
- buf_pool->n_flush[BUF_FLUSH_LRU],
- buf_pool->n_flush[BUF_FLUSH_LIST],
+ buf_pool->n_flush[BUF_FLUSH_LRU]
+ + buf_pool->init_flush[BUF_FLUSH_LRU],
+ buf_pool->n_flush[BUF_FLUSH_LIST]
+ + buf_pool->init_flush[BUF_FLUSH_LIST],
buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
current_time = time(NULL);
@@ -2144,7 +2170,7 @@ buf_print_io(
/ (buf_pool->n_page_gets - buf_pool->n_page_gets_old)));
} else {
buf += sprintf(buf,
- "No buffer pool activity since the last printout\n");
+ "No buffer pool page gets since the last printout\n");
}
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index 02587487a92..47ac9c6b041 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -107,7 +107,7 @@ buf_flush_ready_for_replace(
BUF_BLOCK_FILE_PAGE and in the LRU list */
{
ut_ad(mutex_own(&(buf_pool->mutex)));
- ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
+ ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
|| (block->buf_fix_count != 0)
@@ -227,7 +227,9 @@ buf_flush_buffered_writes(void)
}
for (i = 0; i < trx_doublewrite->first_free; i++) {
+
block = trx_doublewrite->buf_block_arr[i];
+ ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (block->check_index_page_at_flush
&& !page_simple_validate(block->frame)) {
@@ -236,10 +238,12 @@ buf_flush_buffered_writes(void)
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: Apparent corruption of an index page\n"
+ " InnoDB: Apparent corruption of an index page n:o %lu in space %lu\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");
+ "InnoDB: files.\n",
+ block->offset, block->space);
+
ut_a(0);
}
}
@@ -394,7 +398,7 @@ buf_flush_write_block_low(
"Warning: cannot force log to disk in the log debug version!\n");
#else
/* Force the log to the disk before writing the modified block */
- log_flush_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS);
+ log_write_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS, TRUE);
#endif
buf_flush_init_for_writing(block->frame, block->newest_modification,
block->space, block->offset);
@@ -432,6 +436,8 @@ buf_flush_try_page(
block = buf_page_hash_get(space, offset);
+ ut_a(block->state == BUF_BLOCK_FILE_PAGE);
+
if (flush_type == BUF_FLUSH_LIST
&& block && buf_flush_ready_for_flush(block, flush_type)) {
@@ -567,7 +573,8 @@ buf_flush_try_page(
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
if (buf_debug_prints) {
- printf("Flushing single page space %lu, page no %lu \n",
+ printf(
+ "Flushing single page space %lu, page no %lu \n",
block->space, block->offset);
}
@@ -608,15 +615,7 @@ buf_flush_try_neighbors(
low = offset;
high = offset + 1;
- } else if (flush_type == BUF_FLUSH_LIST) {
- /* Since semaphore waits require us to flush the
- doublewrite buffer to disk, it is best that the
- search area is just the page itself, to minimize
- chances for semaphore waits */
-
- low = offset;
- high = offset + 1;
- }
+ }
/* printf("Flush area: low %lu high %lu\n", low, high); */
@@ -633,13 +632,20 @@ buf_flush_try_neighbors(
if (block && flush_type == BUF_FLUSH_LRU && i != offset
&& !block->old) {
- /* We avoid flushing 'non-old' blocks in an LRU flush,
- because the flushed blocks are soon freed */
+ /* We avoid flushing 'non-old' blocks in an LRU flush,
+ because the flushed blocks are soon freed */
- continue;
+ continue;
}
- if (block && buf_flush_ready_for_flush(block, flush_type)) {
+ if (block && buf_flush_ready_for_flush(block, flush_type)
+ && (i == offset || block->buf_fix_count == 0)) {
+ /* We only try to flush those neighbors != offset
+ where the buf fix count is zero, as we then know that
+ we probably can latch the page without a semaphore
+ wait. Semaphore waits are expensive because we must
+ flush the doublewrite buffer before we start
+ waiting. */
mutex_exit(&(buf_pool->mutex));
@@ -758,7 +764,6 @@ buf_flush_batch(
page_count +=
buf_flush_try_neighbors(space, offset,
flush_type);
-
/* printf(
"Flush type %lu, page no %lu, neighb %lu\n",
flush_type, offset,
@@ -884,11 +889,19 @@ buf_flush_free_margin(void)
/*=======================*/
{
ulint n_to_flush;
+ ulint n_flushed;
n_to_flush = buf_flush_LRU_recommendation();
if (n_to_flush > 0) {
- buf_flush_batch(BUF_FLUSH_LRU, n_to_flush, ut_dulint_zero);
+ n_flushed = buf_flush_batch(BUF_FLUSH_LRU, n_to_flush,
+ ut_dulint_zero);
+ if (n_flushed == ULINT_UNDEFINED) {
+ /* There was an LRU type flush batch already running;
+ let us wait for it to end */
+
+ buf_flush_wait_batch_end(BUF_FLUSH_LRU);
+ }
}
}
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 051aa0191f6..40f49f1fddc 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -104,12 +104,15 @@ ibool
buf_LRU_search_and_free_block(
/*==========================*/
/* out: TRUE if freed */
- ulint n_iterations __attribute__((unused))) /* in: how many times
- this has been called repeatedly without
- result: a high value means that we should
- search farther */
+ ulint n_iterations) /* in: how many times this has been called
+ repeatedly without result: a high value means
+ that we should search farther; if value is
+ k < 10, then we only search k/10 * [number
+ of pages in the buffer pool] from the end
+ of the LRU list */
{
buf_block_t* block;
+ ulint distance = 0;
ibool freed;
mutex_enter(&(buf_pool->mutex));
@@ -152,6 +155,18 @@ buf_LRU_search_and_free_block(
}
block = UT_LIST_GET_PREV(LRU, block);
+ distance++;
+
+ if (!freed && n_iterations <= 10
+ && distance > 100 + (n_iterations * buf_pool->curr_size)
+ / 10) {
+
+ buf_pool->LRU_flush_ended = 0;
+
+ mutex_exit(&(buf_pool->mutex));
+
+ return(FALSE);
+ }
}
if (buf_pool->LRU_flush_ended > 0) {
@@ -186,7 +201,7 @@ buf_LRU_try_free_flushed_blocks(void)
mutex_exit(&(buf_pool->mutex));
- buf_LRU_search_and_free_block(0);
+ buf_LRU_search_and_free_block(1);
mutex_enter(&(buf_pool->mutex));
}
@@ -208,7 +223,7 @@ buf_LRU_get_free_block(void)
{
buf_block_t* block = NULL;
ibool freed;
- ulint n_iterations = 0;
+ ulint n_iterations = 1;
ibool mon_value_was = 0; /* remove bug */
ibool started_monitor = FALSE;
loop:
@@ -236,9 +251,12 @@ loop:
fprintf(stderr,
" InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n"
"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
-"InnoDB: transactions do not set too many row locks. Starting InnoDB\n"
-"InnoDB: Monitor to print diagnostics, including lock heap and hash index\n"
-"InnoDB: sizes.\n");
+"InnoDB: transactions do not set too many row locks.\n"
+"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
+"InnoDB: the buffer pool bigger?\n"
+"InnoDB: Starting the InnoDB Monitor to print diagnostics, including\n"
+"InnoDB: lock heap and hash index sizes.\n",
+ buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE));
srv_print_innodb_monitor = TRUE;
@@ -251,14 +269,6 @@ loop:
srv_print_innodb_monitor = FALSE;
}
-
- if (buf_pool->LRU_flush_ended > 0) {
- mutex_exit(&(buf_pool->mutex));
-
- buf_LRU_try_free_flushed_blocks();
-
- mutex_enter(&(buf_pool->mutex));
- }
/* If there is a block in the free list, take it */
if (UT_LIST_GET_LEN(buf_pool->free) > 0) {
@@ -340,6 +350,20 @@ loop:
os_aio_simulated_wake_handler_threads();
+ mutex_enter(&(buf_pool->mutex));
+
+ if (buf_pool->LRU_flush_ended > 0) {
+ /* We have written pages in an LRU flush. To make the insert
+ buffer more efficient, we try to move these pages to the free
+ list. */
+
+ mutex_exit(&(buf_pool->mutex));
+
+ buf_LRU_try_free_flushed_blocks();
+ } else {
+ mutex_exit(&(buf_pool->mutex));
+ }
+
if (n_iterations > 10) {
os_thread_sleep(500000);
diff --git a/innobase/com/Makefile.am b/innobase/com/Makefile.am
index 27ae396bc6e..a3d2f8a76c6 100644
--- a/innobase/com/Makefile.am
+++ b/innobase/com/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libcom.a
+noinst_LIBRARIES = libcom.a
libcom_a_SOURCES = com0com.c com0shm.c
diff --git a/innobase/data/Makefile.am b/innobase/data/Makefile.am
index 0e502708e85..eeb6f129de0 100644
--- a/innobase/data/Makefile.am
+++ b/innobase/data/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libdata.a
+noinst_LIBRARIES = libdata.a
libdata_a_SOURCES = data0data.c data0type.c
diff --git a/innobase/dict/Makefile.am b/innobase/dict/Makefile.am
index 693048b6784..0034d2f8f1e 100644
--- a/innobase/dict/Makefile.am
+++ b/innobase/dict/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libdict.a
+noinst_LIBRARIES = libdict.a
libdict_a_SOURCES = dict0boot.c dict0crea.c dict0dict.c dict0load.c\
dict0mem.c
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index b0f84e5663a..3619ac02f4d 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -1173,6 +1173,7 @@ dict_create_add_foreigns_to_dictionary(
if (NULL == dict_table_get_low((char *) "SYS_FOREIGN")) {
fprintf(stderr,
"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
+
return(DB_ERROR);
}
@@ -1259,6 +1260,13 @@ loop:
"InnoDB: at http://www.innodb.com/ibman.html\n");
}
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Internal error in foreign key constraint creation for table %.500s.\n"
+"See the MySQL .err log in the datadir for more information.\n", table->name);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(error);
}
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 9be10fe70d8..c11a5f76d94 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -185,6 +185,14 @@ dict_foreign_free(
/*==============*/
dict_foreign_t* foreign); /* in, own: foreign key struct */
+/* Buffers for storing detailed information about the latest foreign key
+and unique key errors */
+char* dict_foreign_err_buf = NULL;
+char* dict_unique_err_buf = NULL;
+mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign
+ and unique error buffers */
+
+
/************************************************************************
Checks if the database name in two table names is the same. */
static
@@ -573,6 +581,13 @@ dict_init(void)
rw_lock_create(&dict_operation_lock);
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
+
+ dict_foreign_err_buf = mem_alloc(DICT_FOREIGN_ERR_BUF_LEN);
+ dict_foreign_err_buf[0] = '\0';
+ dict_unique_err_buf = mem_alloc(DICT_FOREIGN_ERR_BUF_LEN);
+ dict_unique_err_buf[0] = '\0';
+ mutex_create(&dict_foreign_err_mutex);
+ mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
}
/**************************************************************************
@@ -1818,6 +1833,7 @@ dict_foreign_add_to_cache(
dict_foreign_t* for_in_cache = NULL;
dict_index_t* index;
ibool added_to_referenced_list = FALSE;
+ char* buf = dict_foreign_err_buf;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1850,9 +1866,29 @@ dict_foreign_add_to_cache(
for_in_cache->foreign_index);
if (index == NULL) {
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s:\n"
+"there is no index in referenced table which would contain\n"
+"the columns as the first columns, or the data types in the\n"
+"referenced table do not match to the ones in table. Constraint:\n",
+ for_in_cache->foreign_table_name);
+ dict_print_info_on_foreign_key_in_create_format(
+ for_in_cache, buf + strlen(buf));
+ if (for_in_cache->foreign_index) {
+ sprintf(buf + strlen(buf),
+"\nThe index in the foreign key in table is %.500s\n"
+"See http://www.innodb.com/ibman.html about correct foreign key definition.\n",
+ for_in_cache->foreign_index->name);
+ }
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
if (for_in_cache == foreign) {
mem_heap_free(foreign->heap);
}
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -1871,6 +1907,25 @@ dict_foreign_add_to_cache(
for_in_cache->referenced_index);
if (index == NULL) {
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s:\n"
+"there is no index in the table which would contain\n"
+"the columns as the first columns, or the data types in the\n"
+"table do not match to the ones in the referenced table. Constraint:\n",
+ for_in_cache->foreign_table_name);
+ dict_print_info_on_foreign_key_in_create_format(
+ for_in_cache, buf + strlen(buf));
+ if (for_in_cache->foreign_index) {
+ sprintf(buf + strlen(buf),
+"\nIndex of the foreign key in the referenced table is %.500s\n"
+"See http://www.innodb.com/ibman.html about correct foreign key definition.\n",
+ for_in_cache->referenced_index->name);
+ }
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
if (for_in_cache == foreign) {
if (added_to_referenced_list) {
UT_LIST_REMOVE(referenced_list,
@@ -2038,7 +2093,7 @@ dict_scan_col(
if (*ptr == '`') {
ptr++;
}
-
+
return(ptr);
}
@@ -2141,18 +2196,21 @@ dict_scan_table_name(
}
/*************************************************************************
-Skips one 'word', like an id. For the lexical definition of 'word', see the
-code below. */
+Scans an id. For the lexical definition of an 'id', see the code below.
+Strips backquotes from around the id. */
static
char*
-dict_skip_word(
-/*===========*/
+dict_scan_id(
+/*=========*/
/* out: scanned to */
char* ptr, /* in: scanned to */
- ibool* success)/* out: TRUE if success, FALSE if just spaces left in
- string */
+ char** start, /* out: start of the id; NULL if no id was
+ scannable */
+ ulint* len) /* out: length of the id */
{
- *success = FALSE;
+ ibool scanned_backquote = FALSE;
+
+ *start = NULL;
while (isspace(*ptr)) {
ptr++;
@@ -2164,24 +2222,61 @@ dict_skip_word(
}
if (*ptr == '`') {
+ scanned_backquote = TRUE;
ptr++;
}
- while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`'
- && *ptr != '\0') {
+ *start = ptr;
+
+ while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != ')'
+ && *ptr != '\0' && *ptr != '`') {
ptr++;
}
- *success = TRUE;
+ *len = (ulint) (ptr - *start);
+
+ if (scanned_backquote) {
+ if (*ptr == '`') {
+ ptr++;
+ } else {
+ /* Syntax error */
+ *start = NULL;
+ }
+ }
return(ptr);
}
/*************************************************************************
+Skips one id. */
+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 or a syntax error */
+{
+ char* start;
+ ulint len;
+
+ *success = FALSE;
+
+ ptr = dict_scan_id(ptr, &start, &len);
+
+ if (start) {
+ *success = TRUE;
+ }
+
+ return(ptr);
+}
+
+#ifdef currentlynotused
+/*************************************************************************
Returns the number of opening brackets '(' subtracted by the number
of closing brackets ')' between string and ptr. */
-#ifdef NOT_USED
static
int
dict_bracket_count(
@@ -2206,16 +2301,116 @@ dict_bracket_count(
return(count);
}
#endif
+
+/*************************************************************************
+Removes MySQL comments from an SQL string. A comment is either
+(a) '#' to the end of the line,
+(b) '--<space>' to the end of the line, or
+(c) '<slash><asterisk>' till the next '<asterisk><slash>' (like the familiar
+C comment syntax). */
+static
+char*
+dict_strip_comments(
+/*================*/
+ /* out, own: SQL string stripped from
+ comments; the caller must free this
+ with mem_free()! */
+ char* sql_string) /* in: SQL string */
+{
+ char* str;
+ char* sptr;
+ char* ptr;
+
+ str = mem_alloc(strlen(sql_string) + 1);
+
+ sptr = sql_string;
+ ptr = str;
+
+ for (;;) {
+ if (*sptr == '\0') {
+ *ptr = '\0';
+
+ return(str);
+ }
+
+ if (*sptr == '#'
+ || (strlen(sptr) >= 3 && 0 == memcmp("-- ", sptr, 3))) {
+ for (;;) {
+ /* In Unix a newline is 0x0D while in Windows
+ it is 0x0A followed by 0x0D */
+
+ if (*sptr == (char)0x0A
+ || *sptr == (char)0x0D
+ || *sptr == '\0') {
+
+ break;
+ }
+
+ sptr++;
+ }
+ }
+
+ if (strlen(sptr) >= 2 && *sptr == '/' && *(sptr + 1) == '*') {
+ for (;;) {
+ if (strlen(sptr) >= 2
+ && *sptr == '*' && *(sptr + 1) == '/') {
+
+ sptr += 2;
+
+ break;
+ }
+
+ if (*sptr == '\0') {
+
+ break;
+ }
+
+ sptr++;
+ }
+ }
+
+ *ptr = *sptr;
+
+ ptr++;
+ sptr++;
+ }
+}
+
+/*************************************************************************
+Reports a simple foreign key create clause syntax error. */
+static
+void
+dict_foreign_report_syntax_err(
+/*===========================*/
+ char* name, /* in: table name */
+ char* start_of_latest_foreign,/* in: start of the foreign key clause
+ in the SQL string */
+ char* ptr) /* in: place of the syntax error */
+{
+ char* buf = dict_foreign_err_buf;
+
+ mutex_enter(&dict_foreign_err_mutex);
+
+ ut_sprintf_timestamp(buf);
+
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s,\n%.500s.\n"
+"Syntax error close to:\n%.500s\n", name, start_of_latest_foreign, ptr);
+
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+}
+
/*************************************************************************
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
the indexes for a table have been created. Each foreign key constraint must
be accompanied with indexes in both participating tables. The indexes are
allowed to contain more fields than mentioned in the constraint. */
-
+static
ulint
-dict_create_foreign_constraints(
-/*============================*/
+dict_create_foreign_constraints_low(
+/*================================*/
/* out: error code or DB_SUCCESS */
trx_t* trx, /* in: transaction */
char* sql_string, /* in: table create or ALTER TABLE
@@ -2231,7 +2426,9 @@ dict_create_foreign_constraints(
dict_table_t* referenced_table;
dict_index_t* index;
dict_foreign_t* foreign;
- char* ptr = sql_string;
+ char* ptr = sql_string;
+ char* start_of_latest_foreign = sql_string;
+ char* buf = dict_foreign_err_buf;
ibool success;
ulint error;
ulint i;
@@ -2249,6 +2446,15 @@ dict_create_foreign_constraints(
table = dict_table_get_low(name);
if (table == NULL) {
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s.\n"
+"Cannot find the table from the internal data dictionary of InnoDB.\n"
+"Create table statement:\n%.2000\n", name, sql_string);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_ERROR);
}
loop:
@@ -2264,6 +2470,8 @@ loop:
return(error);
}
+ start_of_latest_foreign = ptr;
+
ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
if (!isspace(*ptr)) {
@@ -2284,13 +2492,19 @@ loop:
ptr = dict_skip_word(ptr, &success);
if (!success) {
+ dict_foreign_report_syntax_err(name,
+ start_of_latest_foreign, ptr);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
- return(DB_CANNOT_ADD_CONSTRAINT);
+ /* We do not flag a syntax error here because in an
+ ALTER TABLE we may also have DROP FOREIGN KEY abc */
+
+ goto loop;
}
}
@@ -2301,6 +2515,15 @@ col_loop1:
ptr = dict_scan_col(ptr, &success, table, columns + i,
column_names + i, column_name_lens + i);
if (!success) {
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s,\n%.500s.\n"
+"Cannot resolve column name close to:\n%.500s\n", name,
+ start_of_latest_foreign, ptr);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2315,6 +2538,8 @@ col_loop1:
ptr = dict_accept(ptr, (char *) ")", &success);
if (!success) {
+ dict_foreign_report_syntax_err(name, start_of_latest_foreign,
+ ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2324,12 +2549,24 @@ col_loop1:
index = dict_foreign_find_index(table, column_names, i, NULL);
if (!index) {
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s:\n"
+"There is no index in the table %.500s where the columns appear\n"
+"as the first columns. Constraint:\n%.500s\n"
+"See http://www.innodb.com/ibman.html for correct foreign key definition.\n",
+ name, name, start_of_latest_foreign);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
-
ptr = dict_accept(ptr, (char *) "REFERENCES", &success);
if (!success || !isspace(*ptr)) {
+ dict_foreign_report_syntax_err(name, start_of_latest_foreign,
+ ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2359,6 +2596,15 @@ col_loop1:
if (!success || (!referenced_table && trx->check_foreigns)) {
dict_foreign_free(foreign);
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s,\n%.500s.\n"
+"Cannot resolve table name close to:\n"
+"%.500s\n", name, start_of_latest_foreign, ptr);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2366,7 +2612,8 @@ col_loop1:
if (!success) {
dict_foreign_free(foreign);
-
+ dict_foreign_report_syntax_err(name, start_of_latest_foreign,
+ ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2381,6 +2628,15 @@ col_loop2:
if (!success) {
dict_foreign_free(foreign);
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s,\n%.500s\n"
+"Cannot resolve column name close to:\n"
+"%.500s\n", name, start_of_latest_foreign, ptr);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2395,6 +2651,8 @@ col_loop2:
if (!success || foreign->n_fields != i) {
dict_foreign_free(foreign);
+ dict_foreign_report_syntax_err(name, start_of_latest_foreign,
+ ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2417,9 +2675,10 @@ scan_on_conditions:
ptr = dict_accept(ptr, "UPDATE", &success);
if (!success) {
-
dict_foreign_free(foreign);
+ dict_foreign_report_syntax_err(name,
+ start_of_latest_foreign, ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2455,6 +2714,8 @@ scan_on_conditions:
if (!success) {
dict_foreign_free(foreign);
+ dict_foreign_report_syntax_err(name,
+ start_of_latest_foreign, ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2472,7 +2733,8 @@ scan_on_conditions:
if (!success) {
dict_foreign_free(foreign);
-
+ dict_foreign_report_syntax_err(name, start_of_latest_foreign,
+ ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2480,7 +2742,8 @@ scan_on_conditions:
if (!success) {
dict_foreign_free(foreign);
-
+ dict_foreign_report_syntax_err(name, start_of_latest_foreign,
+ ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2494,6 +2757,15 @@ scan_on_conditions:
dict_foreign_free(foreign);
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s,\n%.500s.\n"
+"You have defined a SET NULL condition though some of the\n"
+"columns is defined as NOT NULL.\n", name, start_of_latest_foreign);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
}
@@ -2512,6 +2784,15 @@ try_find_index:
dict_foreign_free(foreign);
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s,\n%.500s.\n"
+"You have twice an ON DELETE clause or twice an ON UPDATE clause.\n",
+ name, start_of_latest_foreign);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -2525,6 +2806,18 @@ try_find_index:
foreign->foreign_index);
if (!index) {
dict_foreign_free(foreign);
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in foreign key constraint of table %.500s:\n"
+"Cannot find an index in the referenced table where the\n"
+"referenced columns appear as the first columns, or column types\n"
+"in the table and the referenced table do not match for constraint:\n%.500s\n"
+"See http://www.innodb.com/ibman.html for correct foreign key definition.\n",
+ name, start_of_latest_foreign);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_CANNOT_ADD_CONSTRAINT);
}
} else {
@@ -2565,6 +2858,165 @@ try_find_index:
goto loop;
}
+/*************************************************************************
+Scans a table create SQL string and adds to the data dictionary the foreign
+key constraints declared in the string. This function should be called after
+the indexes for a table have been created. Each foreign key constraint must
+be accompanied with indexes in both participating tables. The indexes are
+allowed to contain more fields than mentioned in the constraint. */
+
+ulint
+dict_create_foreign_constraints(
+/*============================*/
+ /* out: error code or DB_SUCCESS */
+ trx_t* trx, /* in: transaction */
+ char* sql_string, /* in: table create or ALTER TABLE
+ statement where foreign keys are declared like:
+ FOREIGN KEY (a, b) REFERENCES table2(c, d),
+ table2 can be written also with the database
+ name before it: test.table2; the default
+ database id the database of parameter name */
+ char* name) /* in: table full name in the normalized form
+ database_name/table_name */
+{
+ char* str;
+ ulint err;
+
+ str = dict_strip_comments(sql_string);
+
+ err = dict_create_foreign_constraints_low(trx, str, name);
+
+ mem_free(str);
+
+ return(err);
+}
+
+/**************************************************************************
+Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
+
+ulint
+dict_foreign_parse_drop_constraints(
+/*================================*/
+ /* out: DB_SUCCESS or
+ DB_CANNOT_DROP_CONSTRAINT if
+ syntax error or the constraint
+ id does not match */
+ mem_heap_t* heap, /* in: heap from which we can
+ allocate memory */
+ trx_t* trx, /* in: transaction */
+ dict_table_t* table, /* in: table */
+ ulint* n, /* out: number of constraints
+ to drop */
+ char*** constraints_to_drop) /* out: id's of the
+ constraints to drop */
+{
+ dict_foreign_t* foreign;
+ ibool success;
+ char* str;
+ char* ptr;
+ char* buf = dict_foreign_err_buf;
+ char* start;
+ char* id;
+ ulint len;
+
+ *n = 0;
+
+ *constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
+
+ str = dict_strip_comments(*(trx->mysql_query_str));
+ ptr = str;
+
+ ut_ad(mutex_own(&(dict_sys->mutex)));
+loop:
+ ptr = dict_scan_to(ptr, (char *) "DROP");
+
+ if (*ptr == '\0') {
+ ut_a(*n < 1000);
+
+ mem_free(str);
+
+ return(DB_SUCCESS);
+ }
+
+ ptr = dict_accept(ptr, (char *) "DROP", &success);
+
+ if (!isspace(*ptr)) {
+
+ goto loop;
+ }
+
+ ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
+
+ if (!success) {
+
+ goto loop;
+ }
+
+ ptr = dict_accept(ptr, (char *) "KEY", &success);
+
+ if (!success) {
+
+ goto syntax_error;
+ }
+
+ ptr = dict_scan_id(ptr, &start, &len);
+
+ if (start == NULL) {
+
+ goto syntax_error;
+ }
+
+ id = mem_heap_alloc(heap, len + 1);
+ ut_memcpy(id, start, len);
+ id[len] = '\0';
+ (*constraints_to_drop)[*n] = id;
+ (*n)++;
+
+ /* Look for the given constraint id */
+
+ foreign = UT_LIST_GET_FIRST(table->foreign_list);
+
+ while (foreign != NULL) {
+ if (0 == ut_strcmp(foreign->id, id)) {
+
+ /* Found */
+ break;
+ }
+
+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ }
+
+ if (foreign == NULL) {
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Error in dropping of a foreign key constraint of table %.500s,\n"
+"just before:\n%s\n in SQL command\n%s\nCannot find a constraint with the\n"
+"given id %s.\n", table->name, ptr, str, id);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ mem_free(str);
+
+ return(DB_CANNOT_DROP_CONSTRAINT);
+ }
+
+ goto loop;
+
+syntax_error:
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf),
+" Syntax error in dropping of a foreign key constraint of table %.500s,\n"
+"close to:\n%s\n in SQL command\n%s\n", table->name, ptr, str);
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
+ mem_free(str);
+
+ return(DB_CANNOT_DROP_CONSTRAINT);
+}
+
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
/**************************************************************************
@@ -3286,7 +3738,6 @@ dict_index_print_low(
n_vals = index->stat_n_diff_key_vals[1];
}
-
printf(
" INDEX: name %s, table name %s, id %lu %lu, fields %lu/%lu, type %lu\n",
index->name, index->table_name,
@@ -3328,6 +3779,99 @@ dict_field_print_low(
}
/**************************************************************************
+Sprintfs to a string info on a foreign key of a table in a format suitable
+for CREATE TABLE. */
+
+char*
+dict_print_info_on_foreign_key_in_create_format(
+/*============================================*/
+ /* out: how far in buf we printed */
+ dict_foreign_t* foreign,/* in: foreign key constraint */
+ char* buf) /* in: buffer of at least 5000 bytes */
+{
+ char* buf2 = buf;
+ ulint i;
+
+ buf2 += sprintf(buf2, ",\n CONSTRAINT `%s` FOREIGN KEY (",
+ foreign->id);
+ for (i = 0; i < foreign->n_fields; i++) {
+ if ((ulint)(buf2 - buf) >= 4000) {
+
+ goto no_space;
+ }
+ buf2 += sprintf(buf2, "`%.250s`",
+ foreign->foreign_col_names[i]);
+
+ if (i + 1 < foreign->n_fields) {
+ buf2 += sprintf(buf2, ", ");
+ }
+ }
+
+ if (dict_tables_have_same_db(foreign->foreign_table_name,
+ foreign->referenced_table_name)) {
+ /* Do not print the database name of the referenced
+ table */
+ buf2 += sprintf(buf2, ") REFERENCES `%.500s` (",
+ dict_remove_db_name(
+ foreign->referenced_table_name));
+ } else {
+ buf2 += sprintf(buf2, ") REFERENCES `%.500s` (",
+ foreign->referenced_table_name);
+ /* Change the '/' in the table name to '.' */
+
+ for (i = ut_strlen(buf); i > 0; i--) {
+ if (buf[i] == '/') {
+
+ buf[i] = '.';
+
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < foreign->n_fields; i++) {
+ if ((ulint)(buf2 - buf) >= 4000) {
+
+ goto no_space;
+ }
+ buf2 += sprintf(buf2, "`%.250s`",
+ foreign->referenced_col_names[i]);
+ if (i + 1 < foreign->n_fields) {
+ buf2 += sprintf(buf2, ", ");
+ }
+ }
+
+ buf2 += sprintf(buf2, ")");
+
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
+ buf2 += sprintf(buf2, " ON DELETE CASCADE");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
+ buf2 += sprintf(buf2, " ON DELETE SET NULL");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
+ buf2 += sprintf(buf2, " ON DELETE NO ACTION");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
+ buf2 += sprintf(buf2, " ON UPDATE CASCADE");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
+ buf2 += sprintf(buf2, " ON UPDATE SET NULL");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
+ buf2 += sprintf(buf2, " ON UPDATE NO ACTION");
+ }
+
+no_space:
+ return(buf2);
+}
+
+/**************************************************************************
Sprintfs to a string info on foreign keys of a table in a format suitable
for CREATE TABLE. */
static
@@ -3336,13 +3880,12 @@ dict_print_info_on_foreign_keys_in_create_format(
/*=============================================*/
char* buf, /* in: auxiliary buffer */
char* str, /* in/out: pointer to a string */
- ulint len, /* in: str has to be a buffer at least
- len + 5000 bytes */
+ ulint len, /* in: buf has to be a buffer of at least
+ len + 5000 bytes; str must have at least
+ len + 1 bytes */
dict_table_t* table) /* in: table */
{
-
dict_foreign_t* foreign;
- ulint i;
char* buf2;
buf2 = buf;
@@ -3358,78 +3901,12 @@ dict_print_info_on_foreign_keys_in_create_format(
}
while (foreign != NULL) {
- buf2 += sprintf(buf2, ",\n FOREIGN KEY (");
-
- for (i = 0; i < foreign->n_fields; i++) {
- if ((ulint)(buf2 - buf) >= len) {
- goto no_space;
- }
- buf2 += sprintf(buf2, "`%s`",
- foreign->foreign_col_names[i]);
-
- if (i + 1 < foreign->n_fields) {
- buf2 += sprintf(buf2, ", ");
- }
- }
-
- 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 '.' */
-
- for (i = ut_strlen(buf); i > 0; i--) {
- if (buf[i] == '/') {
+ if ((ulint)(buf2 - buf) >= len) {
+ goto no_space;
+ }
- buf[i] = '.';
-
- break;
- }
- }
- }
-
- for (i = 0; i < foreign->n_fields; i++) {
- if ((ulint)(buf2 - buf) >= len) {
- goto no_space;
- }
- buf2 += sprintf(buf2, "`%s`",
- foreign->referenced_col_names[i]);
- if (i + 1 < foreign->n_fields) {
- buf2 += sprintf(buf2, ", ");
- }
- }
-
- buf2 += sprintf(buf2, ")");
-
- if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
- buf2 += sprintf(buf2, " ON DELETE CASCADE");
- }
-
- if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
- buf2 += sprintf(buf2, " ON DELETE SET NULL");
- }
-
- if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
- buf2 += sprintf(buf2, " ON DELETE NO ACTION");
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
- buf2 += sprintf(buf2, " ON UPDATE CASCADE");
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
- buf2 += sprintf(buf2, " ON UPDATE SET NULL");
- }
-
- if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
- buf2 += sprintf(buf2, " ON UPDATE NO ACTION");
- }
+ buf2 = dict_print_info_on_foreign_key_in_create_format(
+ foreign, buf2);
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
@@ -3490,7 +3967,7 @@ dict_print_info_on_foreign_keys(
goto no_space;
}
- buf2 += sprintf(buf2, "%s",
+ buf2 += sprintf(buf2, "%.500s",
foreign->foreign_col_names[i]);
if (i + 1 < foreign->n_fields) {
@@ -3498,14 +3975,14 @@ dict_print_info_on_foreign_keys(
}
}
- buf2 += sprintf(buf2, ") REFER %s(",
+ buf2 += sprintf(buf2, ") REFER %.500s(",
foreign->referenced_table_name);
for (i = 0; i < foreign->n_fields; i++) {
if ((ulint)(buf2 - buf) >= len) {
goto no_space;
}
- buf2 += sprintf(buf2, "%s",
+ buf2 += sprintf(buf2, "%.500s",
foreign->referenced_col_names[i]);
if (i + 1 < foreign->n_fields) {
buf2 += sprintf(buf2, " ");
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index 1070a8f5426..999eb55bb20 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -456,7 +456,7 @@ dict_load_indexes(
ut_ad(len == 8);
id = mach_read_from_8(field);
- ut_a(0 == ut_strcmp((void*) "NAME",
+ ut_a(0 == ut_strcmp((char*) "NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 4))->name));
@@ -515,7 +515,7 @@ dict_load_indexes(
&& ((type & DICT_CLUSTERED)
|| ((table == dict_sys->sys_tables)
&& (name_len == ut_strlen("ID_IND"))
- && (0 == ut_memcmp(name_buf, (void*) "ID_IND",
+ && (0 == ut_memcmp(name_buf, (char*) "ID_IND",
name_len))))) {
/* The index was created in memory already in
@@ -566,6 +566,7 @@ dict_load_table(
char* buf;
ulint space;
ulint n_cols;
+ ulint err;
mtr_t mtr;
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -674,8 +675,25 @@ dict_load_table(
dict_load_indexes(table, heap);
- ut_a(DB_SUCCESS == dict_load_foreigns(table->name));
+ err = dict_load_foreigns(table->name);
+/*
+ if (err != DB_SUCCESS) {
+
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_print_timestamp(stderr);
+
+ fprintf(stderr,
+" InnoDB: Error: could not make a foreign key definition to match\n"
+"InnoDB: the foreign key table or the referenced table!\n"
+"InnoDB: The data dictionary of InnoDB is corrupt. You may need to drop\n"
+"InnoDB: and recreate the foreign key table or the referenced table.\n"
+"InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n"
+"InnoDB: Latest foreign key error printout:\n%s\n", dict_foreign_err_buf);
+
+ mutex_exit(&dict_foreign_err_mutex);
+ }
+*/
mem_heap_free(heap);
return(table);
@@ -978,8 +996,8 @@ dict_load_foreign(
field = rec_get_nth_field(rec, 4, &len);
- foreign->referenced_table_name = mem_heap_alloc(foreign->heap, 1 + len);
-
+ foreign->referenced_table_name = mem_heap_alloc(foreign->heap,
+ 1 + len);
ut_memcpy(foreign->referenced_table_name, field, len);
foreign->referenced_table_name[len] = '\0';
@@ -988,10 +1006,19 @@ dict_load_foreign(
dict_load_foreign_cols(id, foreign);
+ /* If the foreign table is not yet in the dictionary cache, we
+ have to load it so that we are able to make type comparisons
+ in the next function call. */
+
+ dict_table_get_low(foreign->foreign_table_name);
+
/* Note that there may already be a foreign constraint object in
the dictionary cache for this constraint: then the following
call only sets the pointers in it to point to the appropriate table
- and index objects and frees the newly created object foreign. */
+ and index objects and frees the newly created object foreign.
+ Adding to the cache should always succeed since we are not creating
+ a new foreign key constraint but loading one from the data
+ dictionary. */
err = dict_foreign_add_to_cache(foreign);
diff --git a/innobase/dyn/Makefile.am b/innobase/dyn/Makefile.am
index 79c0000868c..ec33a3c18a9 100644
--- a/innobase/dyn/Makefile.am
+++ b/innobase/dyn/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libdyn.a
+noinst_LIBRARIES = libdyn.a
libdyn_a_SOURCES = dyn0dyn.c
diff --git a/innobase/eval/Makefile.am b/innobase/eval/Makefile.am
index 5dd0eab4c9b..aebffb91be3 100644
--- a/innobase/eval/Makefile.am
+++ b/innobase/eval/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libeval.a
+noinst_LIBRARIES = libeval.a
libeval_a_SOURCES = eval0eval.c eval0proc.c
diff --git a/innobase/fil/Makefile.am b/innobase/fil/Makefile.am
index a9473fdb762..dc0baff7d1a 100644
--- a/innobase/fil/Makefile.am
+++ b/innobase/fil/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libfil.a
+noinst_LIBRARIES = libfil.a
libfil_a_SOURCES = fil0fil.c
diff --git a/innobase/fsp/Makefile.am b/innobase/fsp/Makefile.am
index b3e9ab44d9b..edf06bda0d6 100644
--- a/innobase/fsp/Makefile.am
+++ b/innobase/fsp/Makefile.am
@@ -18,7 +18,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libfsp.a
+noinst_LIBRARIES = libfsp.a
libfsp_a_SOURCES = fsp0fsp.c
diff --git a/innobase/fut/Makefile.am b/innobase/fut/Makefile.am
index a4b1e30e03c..839fdb1580e 100644
--- a/innobase/fut/Makefile.am
+++ b/innobase/fut/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libfut.a
+noinst_LIBRARIES = libfut.a
libfut_a_SOURCES = fut0fut.c fut0lst.c
diff --git a/innobase/ha/Makefile.am b/innobase/ha/Makefile.am
index ce846d37622..121bafe167d 100644
--- a/innobase/ha/Makefile.am
+++ b/innobase/ha/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libha.a
+noinst_LIBRARIES = libha.a
libha_a_SOURCES = ha0ha.c hash0hash.c
diff --git a/innobase/ibuf/Makefile.am b/innobase/ibuf/Makefile.am
index 1c1d196c40c..fb813d38ee5 100644
--- a/innobase/ibuf/Makefile.am
+++ b/innobase/ibuf/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libibuf.a
+noinst_LIBRARIES = libibuf.a
libibuf_a_SOURCES = ibuf0ibuf.c
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index 5cd066afc27..187afa17047 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -2391,7 +2391,7 @@ ibuf_delete_rec(
ut_ad(ibuf_inside());
- success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
+ success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
if (success) {
#ifdef UNIV_IBUF_DEBUG
@@ -2401,7 +2401,7 @@ ibuf_delete_rec(
return(FALSE);
}
- /* We have to resort to a pessimistic delete from ibuf */
+ /* We have to resort to a pessimistic delete from ibuf */
btr_pcur_store_position(pcur, mtr);
btr_pcur_commit_specify_mtr(pcur, mtr);
@@ -2420,17 +2420,22 @@ ibuf_delete_rec(
fprintf(stderr, "InnoDB: ibuf cursor restoration fails!\n");
fprintf(stderr, "InnoDB: ibuf record inserted to page %lu\n",
page_no);
+ fflush(stderr);
+
rec_print(btr_pcur_get_rec(pcur));
rec_print(pcur->old_rec);
dtuple_print(search_tuple);
rec_print(page_rec_get_next(btr_pcur_get_rec(pcur)));
+ fflush(stdout);
mtr_commit(mtr);
fprintf(stderr, "InnoDB: Validating insert buffer tree:\n");
- ut_a(btr_validate_tree(ibuf_data->index->tree));
- fprintf(stderr, "InnoDB: Ibuf tree ok\n");
+ ut_a(btr_validate_tree(ibuf_data->index->tree));
+
+ fprintf(stderr, "InnoDB: ibuf tree ok\n");
+ fflush(stderr);
}
ut_a(success);
diff --git a/innobase/include/Makefile.i b/innobase/include/Makefile.i
index 985ec525950..f3e3fbe989e 100644
--- a/innobase/include/Makefile.i
+++ b/innobase/include/Makefile.i
@@ -1,7 +1,5 @@
# Makefile included in Makefile.am in every subdirectory
-libsdir = ../libs
-
INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../../include -I../../include
# Don't update the files from bitkeeper
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index 81eeb7fced8..b613d60ebf7 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -496,6 +496,13 @@ buf_print_io(
/*=========*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
+/*************************************************************************
+Returns the ratio in percents of modified pages in the buffer pool /
+database pages in the buffer pool. */
+
+ulint
+buf_get_modified_ratio_pct(void);
+/*============================*/
/**************************************************************************
Refreshes the statistics used to print per-second averages. */
diff --git a/innobase/include/buf0lru.h b/innobase/include/buf0lru.h
index 6a3c948507d..5c995b259bf 100644
--- a/innobase/include/buf0lru.h
+++ b/innobase/include/buf0lru.h
@@ -46,6 +46,20 @@ buf_LRU_get_recent_limit(void);
/*==========================*/
/* out: the limit; zero if could not determine it */
/**********************************************************************
+Look for a replaceable block from the end of the LRU list and put it to
+the free list if found. */
+
+ibool
+buf_LRU_search_and_free_block(
+/*==========================*/
+ /* out: TRUE if freed */
+ ulint n_iterations); /* in: how many times this has been called
+ repeatedly without result: a high value means
+ that we should search farther; if value is
+ k < 10, then we only search k/10 * number
+ of pages in the buffer pool from the end
+ of the LRU list */
+/**********************************************************************
Returns a free block from the buf_pool. The block is taken off the
free list. If it is empty, blocks are moved from the end of the
LRU list to the free list. */
@@ -88,17 +102,6 @@ void
buf_LRU_make_block_old(
/*===================*/
buf_block_t* block); /* in: control block */
-/**********************************************************************
-Look for a replaceable block from the end of the LRU list and put it to
-the free list if found. */
-
-ibool
-buf_LRU_search_and_free_block(
-/*==========================*/
- /* out: TRUE if freed */
- ulint n_iterations); /* in: how many times this has been called
- repeatedly without result: a high value
- means that we should search farther */
/**************************************************************************
Validates the LRU list. */
diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h
index c67c09bad27..ab7d0caa35c 100644
--- a/innobase/include/db0err.h
+++ b/innobase/include/db0err.h
@@ -44,6 +44,8 @@ Created 5/24/1996 Heikki Tuuri
#define DB_CORRUPTION 39 /* data structure corruption noticed */
#define DB_COL_APPEARS_TWICE_IN_INDEX 40 /* InnoDB cannot handle an index
where same column appears twice */
+#define DB_CANNOT_DROP_CONSTRAINT 40 /* dropping a foreign key constraint
+ from a table failed */
/* The following are partial failure codes */
#define DB_FAIL 1000
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index b5e6e04a1de..97486a7c2f6 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -219,6 +219,24 @@ dict_create_foreign_constraints(
char* name); /* in: table full name in the normalized form
database_name/table_name */
/**************************************************************************
+Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
+
+ulint
+dict_foreign_parse_drop_constraints(
+/*================================*/
+ /* out: DB_SUCCESS or
+ DB_CANNOT_DROP_CONSTRAINT if
+ syntax error or the constraint
+ id does not match */
+ mem_heap_t* heap, /* in: heap from which we can
+ allocate memory */
+ trx_t* trx, /* in: transaction */
+ dict_table_t* table, /* in: table */
+ ulint* n, /* out: number of constraints
+ to drop */
+ char*** constraints_to_drop); /* out: id's of the
+ constraints to drop */
+/**************************************************************************
Returns a table object and memoryfixes it. NOTE! This is a high-level
function to be used mainly from outside the 'dict' directory. Inside this
directory dict_table_get_low is usually the appropriate function. */
@@ -333,6 +351,16 @@ dict_print_info_on_foreign_keys(
char* str, /* in/out: pointer to a string */
ulint len, /* in: space in str available for info */
dict_table_t* table); /* in: table */
+/**************************************************************************
+Sprintfs to a string info on a foreign key of a table in a format suitable
+for CREATE TABLE. */
+
+char*
+dict_print_info_on_foreign_key_in_create_format(
+/*============================================*/
+ /* out: how far in buf we printed */
+ dict_foreign_t* foreign,/* in: foreign key constraint */
+ char* buf); /* in: buffer of at least 5000 bytes */
/************************************************************************
Gets the first index on the table (the clustered index). */
UNIV_INLINE
@@ -808,6 +836,14 @@ void
dict_mutex_exit_for_mysql(void);
/*===========================*/
+/* The following len must be at least 10000 bytes! */
+#define DICT_FOREIGN_ERR_BUF_LEN 10000
+
+/* Buffers for storing detailed information about the latest foreign key
+and unique key errors */
+extern char* dict_foreign_err_buf;
+extern char* dict_unique_err_buf;
+extern mutex_t dict_foreign_err_mutex; /* mutex protecting the buffers */
extern dict_sys_t* dict_sys; /* the dictionary system */
extern rw_lock_t dict_operation_lock;
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index f200371de9d..4e1404b15fe 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -20,7 +20,7 @@ typedef struct log_group_struct log_group_t;
extern ibool log_do_write;
extern ibool log_debug_writes;
-/* Wait modes for log_flush_up_to */
+/* Wait modes for log_write_up_to */
#define LOG_NO_WAIT 91
#define LOG_WAIT_ONE_GROUP 92
#define LOG_WAIT_ALL_GROUPS 93
@@ -157,26 +157,21 @@ log_io_complete(
/*============*/
log_group_t* group); /* in: log group */
/**********************************************************
-Flushes the log files to the disk, using, for example, the Unix fsync.
-This function does the flush even if the user has set
-srv_flush_log_at_trx_commit = FALSE. */
-
-void
-log_flush_to_disk(void);
-/*===================*/
-/**********************************************************
This function is called, e.g., when a transaction wants to commit. It checks
-that the log has been flushed to disk up to the last log entry written by the
-transaction. If there is a flush running, it waits and checks if the flush
-flushed enough. If not, starts a new flush. */
+that the log has been written to the log file up to the last log entry written
+by the transaction. If there is a flush running, it waits and checks if the
+flush flushed enough. If not, starts a new flush. */
void
-log_flush_up_to(
+log_write_up_to(
/*============*/
dulint lsn, /* in: log sequence number up to which the log should
- be flushed, ut_dulint_max if not specified */
- ulint wait); /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
+ be written, ut_dulint_max if not specified */
+ ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
or LOG_WAIT_ALL_GROUPS */
+ ibool flush_to_disk);
+ /* in: TRUE if we want the written log also to be
+ flushed to disk */
/********************************************************************
Advances the smallest lsn for which there are unflushed dirty blocks in the
buffer pool and also may make a new checkpoint. NOTE: this function may only
@@ -741,27 +736,37 @@ struct log_struct{
be advanced, it is enough that the
write i/o has been completed for all
log groups */
- dulint flush_lsn; /* end lsn for the current flush */
- ulint flush_end_offset;/* the data in buffer has been flushed
+ dulint write_lsn; /* end lsn for the current running
+ write */
+ ulint write_end_offset;/* the data in buffer has been written
up to this offset when the current
- flush ends: this field will then
+ write ends: this field will then
be copied to buf_next_to_write */
- ulint n_pending_writes;/* number of currently pending flush
- writes */
+ dulint current_flush_lsn;/* end lsn for the current running
+ write + flush operation */
+ dulint flushed_to_disk_lsn;
+ /* how far we have written the log
+ AND flushed to disk */
+ ulint n_pending_writes;/* number of currently pending flushes
+ or writes */
+ /* NOTE on the 'flush' in names of the fields below: starting from
+ 4.0.14, we separate the write of the log file and the actual fsync()
+ or other method to flush it to disk. The names below shhould really
+ be 'flush_or_write'! */
os_event_t no_flush_event; /* this event is in the reset state
- when a flush is running; a thread
- should wait for this without owning
- the log mutex, but NOTE that to set or
- reset this event, the thread MUST own
- the log mutex! */
+ when a flush or a write is running;
+ a thread should wait for this without
+ owning the log mutex, but NOTE that
+ to set or reset this event, the
+ thread MUST own the log mutex! */
ibool one_flushed; /* during a flush, this is first FALSE
and becomes TRUE when one log group
- has been flushed */
+ has been written or flushed */
os_event_t one_flushed_event;/* this event is reset when the
- flush has not yet completed for any
- log group; e.g., this means that a
- transaction has been committed when
- this is set; a thread should wait
+ flush or write has not yet completed
+ for any log group; e.g., this means
+ that a transaction has been committed
+ when this is set; a thread should wait
for this without owning the log mutex,
but NOTE that to set or reset this
event, the thread MUST own the log
diff --git a/innobase/include/row0ins.h b/innobase/include/row0ins.h
index cc3b9fa7e9a..a5b4b74e7fc 100644
--- a/innobase/include/row0ins.h
+++ b/innobase/include/row0ins.h
@@ -35,7 +35,6 @@ row_ins_check_foreign_constraint(
dictionary cache if they exist at all */
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
table, else the referenced table */
- dict_index_t* index, /* in: index in table */
dtuple_t* entry, /* in: index entry for index */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 972fabc74cf..1964f53dabb 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -427,13 +427,21 @@ struct row_prebuilt_struct {
index where the ordering column is
the row id: in this case this flag
is set to TRUE */
- dict_index_t* index; /* current index for a search, if any */
+ dict_index_t* index; /* current index for a search, if
+ any */
ulint read_just_key; /* set to 1 when MySQL calls
ha_innobase::extra with the
argument HA_EXTRA_KEYREAD; it is enough
to read just columns defined in
the index (i.e., no read of the
clustered index record necessary) */
+ ibool used_in_HANDLER;/* TRUE if we have been using this
+ handle in a MySQL HANDLER low level
+ index cursor command: then we must
+ store the pcur position even in a
+ unique search from a clustered index,
+ because HANDLER allows NEXT and PREV
+ in such a situation */
ulint template_type; /* ROW_MYSQL_WHOLE_ROW,
ROW_MYSQL_REC_FIELDS,
ROW_MYSQL_DUMMY_TEMPLATE, or
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index bc0960ae023..121e9c44a24 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -75,6 +75,9 @@ extern ulint srv_lock_wait_timeout;
extern char* srv_file_flush_method_str;
extern ulint srv_unix_file_flush_method;
extern ulint srv_win_file_flush_method;
+
+extern ulint srv_max_dirty_pages_pct;
+
extern ulint srv_force_recovery;
extern ulint srv_thread_concurrency;
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 34f820f03e7..39229923375 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -157,6 +157,15 @@ trx_commit_for_mysql(
/* out: 0 or error number */
trx_t* trx); /* in: trx handle */
/**************************************************************************
+If required, flushes the log to disk if we called trx_commit_for_mysql()
+with trx->flush_log_later == TRUE. */
+
+ulint
+trx_commit_complete_for_mysql(
+/*==========================*/
+ /* out: 0 or error number */
+ trx_t* trx); /* in: trx handle */
+/**************************************************************************
Marks the latest SQL statement ended. */
void
@@ -343,6 +352,11 @@ struct trx_struct{
dulint no; /* transaction serialization number ==
max trx id when the transaction is
moved to COMMITTED_IN_MEMORY state */
+ ibool flush_log_later;/* when we commit the transaction
+ in MySQL's binlog write, we will
+ flush the log to disk later in
+ a separate call */
+ dulint commit_lsn; /* lsn at the time of the commit */
ibool dict_operation; /* TRUE if the trx is used to create
a table, create an index, or drop a
table */
@@ -418,10 +432,6 @@ struct trx_struct{
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
the transaction; note that it is also
in the lock list trx_locks */
- ibool ignore_duplicates_in_insert;
- /* in an insert roll back only insert
- of the latest row in case
- of a duplicate key error */
UT_LIST_NODE_T(trx_t)
trx_list; /* list of transactions */
UT_LIST_NODE_T(trx_t)
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index bf606efcf64..e29f3ec92e1 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -100,6 +100,15 @@ memory is read outside the allocated blocks. */
#define YYDEBUG 1
+#ifdef HAVE_purify
+/* The following sets all new allocated memory to zero before use:
+this can be used to eliminate unnecessary Purify warnings, but note that
+it also masks many bugs Purify could detect. For detailed Purify analysis it
+is best to remove the define below and look through the warnings one
+by one. */
+#define UNIV_SET_MEM_TO_ZERO
+#endif
+
/*
#define UNIV_SQL_DEBUG
#define UNIV_LOG_DEBUG
diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h
index 3407483696c..e99dc8c09d6 100644
--- a/innobase/include/ut0dbg.h
+++ b/innobase/include/ut0dbg.h
@@ -20,7 +20,6 @@ extern ibool ut_dbg_stop_threads;
extern ulint* ut_dbg_null_ptr;
-
#define ut_a(EXPR)\
{\
ulint dbg_i;\
@@ -31,8 +30,10 @@ extern ulint* ut_dbg_null_ptr;
" InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
os_thread_pf(os_thread_get_curr_id()), IB__FILE__,\
(ulint)__LINE__);\
+ fprintf(stderr,\
+ "InnoDB: Failing assertion: " #EXPR);\
fprintf(stderr,\
- "InnoDB: We intentionally generate a memory trap.\n");\
+ "\nInnoDB: We intentionally generate a memory trap.\n");\
fprintf(stderr,\
"InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n");\
ut_dbg_stop_threads = TRUE;\
diff --git a/innobase/lock/Makefile.am b/innobase/lock/Makefile.am
index f9e1b227f3c..549eb2604e3 100644
--- a/innobase/lock/Makefile.am
+++ b/innobase/lock/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = liblock.a
+noinst_LIBRARIES = liblock.a
liblock_a_SOURCES = lock0lock.c
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index d4329c4873c..74dc4aea515 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -3092,8 +3092,7 @@ lock_deadlock_recursive(
err_buf += strlen(err_buf);
err_buf += sprintf(err_buf,
- " LATEST DETECTED DEADLOCK:\n"
- "*** (1) TRANSACTION:\n");
+ "\n*** (1) TRANSACTION:\n");
trx_print(err_buf, wait_lock->trx);
err_buf += strlen(err_buf);
@@ -3935,24 +3934,15 @@ lock_print_info(
return;
}
-
- buf += sprintf(buf, "Trx id counter %lu %lu\n",
- ut_dulint_get_high(trx_sys->max_trx_id),
- ut_dulint_get_low(trx_sys->max_trx_id));
-
- buf += sprintf(buf,
- "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
- ut_dulint_get_high(purge_sys->purge_trx_no),
- ut_dulint_get_low(purge_sys->purge_trx_no),
- ut_dulint_get_high(purge_sys->purge_undo_no),
- ut_dulint_get_low(purge_sys->purge_undo_no));
lock_mutex_enter_kernel();
- buf += sprintf(buf,
- "Total number of lock structs in row lock hash table %lu\n",
- lock_get_n_rec_locks());
if (lock_deadlock_found) {
+
+ buf += sprintf(buf,
+"------------------------\n"
+"LATEST DETECTED DEADLOCK\n"
+"------------------------\n");
if ((ulint)(buf_end - buf)
< 100 + strlen(lock_latest_err_buf)) {
@@ -3973,6 +3963,26 @@ lock_print_info(
return;
}
+ buf += sprintf(buf,
+"------------\n"
+"TRANSACTIONS\n"
+"------------\n");
+
+ buf += sprintf(buf, "Trx id counter %lu %lu\n",
+ ut_dulint_get_high(trx_sys->max_trx_id),
+ ut_dulint_get_low(trx_sys->max_trx_id));
+
+ buf += sprintf(buf,
+ "Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
+ ut_dulint_get_high(purge_sys->purge_trx_no),
+ ut_dulint_get_low(purge_sys->purge_trx_no),
+ ut_dulint_get_high(purge_sys->purge_undo_no),
+ ut_dulint_get_low(purge_sys->purge_undo_no));
+
+ buf += sprintf(buf,
+ "Total number of lock structs in row lock hash table %lu\n",
+ lock_get_n_rec_locks());
+
buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
/* First print info on non-active transactions */
diff --git a/innobase/log/Makefile.am b/innobase/log/Makefile.am
index 3910a25ab1a..2dbaf93e6d9 100644
--- a/innobase/log/Makefile.am
+++ b/innobase/log/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = liblog.a
+noinst_LIBRARIES = liblog.a
liblog_a_SOURCES = log0log.c log0recv.c
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index bdfce783a43..e717d897e41 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -178,7 +178,7 @@ loop:
/* Not enough free space, do a syncronous flush of the log
buffer */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ALL_GROUPS);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ALL_GROUPS, TRUE);
count++;
@@ -675,7 +675,9 @@ log_init(void)
log_sys->buf_next_to_write = 0;
- log_sys->flush_lsn = ut_dulint_zero;
+ log_sys->write_lsn = ut_dulint_zero;
+ log_sys->current_flush_lsn = ut_dulint_zero;
+ log_sys->flushed_to_disk_lsn = ut_dulint_zero;
log_sys->written_to_some_lsn = log_sys->lsn;
log_sys->written_to_all_lsn = log_sys->lsn;
@@ -867,7 +869,7 @@ log_group_check_flush_completion(
printf("Log flushed first to group %lu\n", group->id);
}
- log_sys->written_to_some_lsn = log_sys->flush_lsn;
+ log_sys->written_to_some_lsn = log_sys->write_lsn;
log_sys->one_flushed = TRUE;
return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
@@ -896,15 +898,15 @@ log_sys_check_flush_completion(void)
if (log_sys->n_pending_writes == 0) {
- log_sys->written_to_all_lsn = log_sys->flush_lsn;
- log_sys->buf_next_to_write = log_sys->flush_end_offset;
+ log_sys->written_to_all_lsn = log_sys->write_lsn;
+ log_sys->buf_next_to_write = log_sys->write_end_offset;
- if (log_sys->flush_end_offset > log_sys->max_buf_free / 2) {
+ if (log_sys->write_end_offset > log_sys->max_buf_free / 2) {
/* Move the log buffer content to the start of the
buffer */
move_start = ut_calc_align_down(
- log_sys->flush_end_offset,
+ log_sys->write_end_offset,
OS_FILE_LOG_BLOCK_SIZE);
move_end = ut_calc_align(log_sys->buf_free,
OS_FILE_LOG_BLOCK_SIZE);
@@ -982,57 +984,6 @@ log_io_complete(
}
/**********************************************************
-Flushes the log files to the disk, using, for example, the Unix fsync.
-This function does the flush even if the user has set
-srv_flush_log_at_trx_commit = FALSE. */
-
-void
-log_flush_to_disk(void)
-/*===================*/
-{
- log_group_t* group;
-loop:
- mutex_enter(&(log_sys->mutex));
-
- if (log_sys->n_pending_writes > 0) {
- /* A log file write is running */
-
- mutex_exit(&(log_sys->mutex));
-
- /* Wait for the log file write to complete and try again */
-
- os_event_wait(log_sys->no_flush_event);
-
- goto loop;
- }
-
- group = UT_LIST_GET_FIRST(log_sys->log_groups);
-
- log_sys->n_pending_writes++;
- group->n_pending_writes++;
-
- os_event_reset(log_sys->no_flush_event);
- os_event_reset(log_sys->one_flushed_event);
-
- mutex_exit(&(log_sys->mutex));
-
- fil_flush(group->space_id);
-
- mutex_enter(&(log_sys->mutex));
-
- ut_a(group->n_pending_writes == 1);
- ut_a(log_sys->n_pending_writes == 1);
-
- group->n_pending_writes--;
- log_sys->n_pending_writes--;
-
- os_event_set(log_sys->no_flush_event);
- os_event_set(log_sys->one_flushed_event);
-
- mutex_exit(&(log_sys->mutex));
-}
-
-/**********************************************************
Writes a log file header to a log file space. */
static
void
@@ -1205,12 +1156,15 @@ by the transaction. If there is a flush running, it waits and checks if the
flush flushed enough. If not, starts a new flush. */
void
-log_flush_up_to(
+log_write_up_to(
/*============*/
dulint lsn, /* in: log sequence number up to which the log should
be written, ut_dulint_max if not specified */
- ulint wait) /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
+ ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
or LOG_WAIT_ALL_GROUPS */
+ ibool flush_to_disk)
+ /* in: TRUE if we want the written log also to be
+ flushed to disk */
{
log_group_t* group;
ulint start_offset;
@@ -1239,9 +1193,18 @@ loop:
mutex_enter(&(log_sys->mutex));
- if ((ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0)
- || ((ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) >= 0)
- && (wait != LOG_WAIT_ALL_GROUPS))) {
+ if (flush_to_disk
+ && ut_dulint_cmp(log_sys->flushed_to_disk_lsn, lsn) >= 0) {
+
+ mutex_exit(&(log_sys->mutex));
+
+ return;
+ }
+
+ if (!flush_to_disk
+ && (ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0
+ || (ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) >= 0
+ && wait != LOG_WAIT_ALL_GROUPS))) {
mutex_exit(&(log_sys->mutex));
@@ -1249,10 +1212,19 @@ loop:
}
if (log_sys->n_pending_writes > 0) {
- /* A flush is running */
+ /* A write (+ possibly flush to disk) is running */
+
+ if (flush_to_disk
+ && ut_dulint_cmp(log_sys->current_flush_lsn, lsn) >= 0) {
+ /* The write + flush will write enough: wait for it to
+ complete */
+
+ goto do_waits;
+ }
- if (ut_dulint_cmp(log_sys->flush_lsn, lsn) >= 0) {
- /* The flush will flush enough: wait for it to
+ if (!flush_to_disk
+ && ut_dulint_cmp(log_sys->write_lsn, lsn) >= 0) {
+ /* The write will write enough: wait for it to
complete */
goto do_waits;
@@ -1260,16 +1232,17 @@ loop:
mutex_exit(&(log_sys->mutex));
- /* Wait for the flush to complete and try to start a new
- flush */
+ /* Wait for the write to complete and try to start a new
+ write */
os_event_wait(log_sys->no_flush_event);
goto loop;
}
- if (log_sys->buf_free == log_sys->buf_next_to_write) {
- /* Nothing to flush */
+ if (!flush_to_disk
+ && log_sys->buf_free == log_sys->buf_next_to_write) {
+ /* Nothing to write and no flush to disk requested */
mutex_exit(&(log_sys->mutex));
@@ -1277,7 +1250,7 @@ loop:
}
if (log_debug_writes) {
- printf("Flushing log from %lu %lu up to lsn %lu %lu\n",
+ printf("Writing log from %lu %lu up to lsn %lu %lu\n",
ut_dulint_get_high(log_sys->written_to_all_lsn),
ut_dulint_get_low(log_sys->written_to_all_lsn),
ut_dulint_get_high(log_sys->lsn),
@@ -1301,7 +1274,12 @@ loop:
ut_ad(area_end - area_start > 0);
- log_sys->flush_lsn = log_sys->lsn;
+ log_sys->write_lsn = log_sys->lsn;
+
+ if (flush_to_disk) {
+ log_sys->current_flush_lsn = log_sys->lsn;
+ }
+
log_sys->one_flushed = FALSE;
log_block_set_flush_bit(log_sys->buf + area_start, TRUE);
@@ -1318,10 +1296,12 @@ loop:
OS_FILE_LOG_BLOCK_SIZE);
log_sys->buf_free += OS_FILE_LOG_BLOCK_SIZE;
- log_sys->flush_end_offset = log_sys->buf_free;
+ log_sys->write_end_offset = log_sys->buf_free;
group = UT_LIST_GET_FIRST(log_sys->log_groups);
+ /* Do the write to the log files */
+
while (group) {
log_group_write_buf(LOG_FLUSH, group,
log_sys->buf + area_start,
@@ -1330,20 +1310,25 @@ loop:
OS_FILE_LOG_BLOCK_SIZE),
start_offset - area_start);
- log_group_set_fields(group, log_sys->flush_lsn);
+ log_group_set_fields(group, log_sys->write_lsn);
group = UT_LIST_GET_NEXT(log_groups, group);
}
mutex_exit(&(log_sys->mutex));
- if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
- && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
- && srv_flush_log_at_trx_commit != 2) {
+ if (srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) {
+ /* O_DSYNC means the OS did not buffer the log file at all:
+ so we have also flushed to disk what we have written */
+
+ log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
+
+ } else if (flush_to_disk) {
group = UT_LIST_GET_FIRST(log_sys->log_groups);
fil_flush(group->space_id);
+ log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
}
mutex_enter(&(log_sys->mutex));
@@ -1403,7 +1388,7 @@ log_flush_margin(void)
mutex_exit(&(log->mutex));
if (do_flush) {
- log_flush_up_to(ut_dulint_max, LOG_NO_WAIT);
+ log_write_up_to(ut_dulint_max, LOG_NO_WAIT, FALSE);
}
}
@@ -1555,7 +1540,8 @@ log_group_checkpoint(
buf = group->checkpoint_buf;
mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys->next_checkpoint_no);
- mach_write_to_8(buf + LOG_CHECKPOINT_LSN, log_sys->next_checkpoint_lsn);
+ mach_write_to_8(buf + LOG_CHECKPOINT_LSN,
+ log_sys->next_checkpoint_lsn);
mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
log_group_calc_lsn_offset(
@@ -1664,8 +1650,10 @@ log_reset_first_header_and_checkpoint(
lsn = ut_dulint_add(start, LOG_BLOCK_HDR_SIZE);
/* Write the label of ibbackup --restore */
- 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
+ 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;
@@ -1773,7 +1761,7 @@ log_checkpoint(
write-ahead-logging algorithm ensures that the log has been flushed
up to oldest_lsn. */
- log_flush_up_to(oldest_lsn, LOG_WAIT_ALL_GROUPS);
+ log_write_up_to(oldest_lsn, LOG_WAIT_ALL_GROUPS, TRUE);
mutex_enter(&(log_sys->mutex));
@@ -2466,7 +2454,7 @@ loop:
mutex_exit(&(log_sys->mutex));
- log_flush_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS);
+ log_write_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS, TRUE);
calc_new_limit = FALSE;
@@ -3104,8 +3092,8 @@ log_print(
"Last checkpoint at %lu %lu\n",
ut_dulint_get_high(log_sys->lsn),
ut_dulint_get_low(log_sys->lsn),
- ut_dulint_get_high(log_sys->written_to_some_lsn),
- ut_dulint_get_low(log_sys->written_to_some_lsn),
+ ut_dulint_get_high(log_sys->flushed_to_disk_lsn),
+ ut_dulint_get_low(log_sys->flushed_to_disk_lsn),
ut_dulint_get_high(log_sys->last_checkpoint_lsn),
ut_dulint_get_low(log_sys->last_checkpoint_lsn));
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 3945b47933d..4efe4e7b23d 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -1833,7 +1833,12 @@ recv_report_corrupt_log(
"InnoDB: WARNING: the log file may have been corrupt and it\n"
"InnoDB: is possible that the log scan did not proceed\n"
"InnoDB: far enough in recovery! Please run CHECK TABLE\n"
- "InnoDB: on your InnoDB tables to check that they are ok!\n");
+ "InnoDB: on your InnoDB tables to check that they are ok!\n"
+ "InnoDB: If mysqld crashes after this recovery, look at\n"
+ "InnoDB: section 6.1 of http://www.innodb.com/ibman.html\n"
+ "InnoDB: about forcing recovery.\n");
+
+ fflush(stderr);
}
/***********************************************************
@@ -2470,7 +2475,7 @@ recv_recovery_from_checkpoint_start(
log_hdr_buf, max_cp_group);
if (0 == ut_memcmp(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
- "ibbackup", ut_strlen("ibbackup"))) {
+ (byte*)"ibbackup", ut_strlen((char*)"ibbackup"))) {
/* This log file was created by ibbackup --restore: print
a note to the user about it */
@@ -2481,7 +2486,7 @@ recv_recovery_from_checkpoint_start(
/* Wipe over the label now */
ut_memcpy(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
- " ", 4);
+ (char*)" ", 4);
/* Write to the log file to wipe over the label */
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE,
max_cp_group->space_id,
diff --git a/innobase/mach/Makefile.am b/innobase/mach/Makefile.am
index 8195831e92e..ce827c8033f 100644
--- a/innobase/mach/Makefile.am
+++ b/innobase/mach/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libmach.a
+noinst_LIBRARIES = libmach.a
libmach_a_SOURCES = mach0data.c
diff --git a/innobase/mem/Makefile.am b/innobase/mem/Makefile.am
index 84f642e4469..10b7771b580 100644
--- a/innobase/mem/Makefile.am
+++ b/innobase/mem/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libmem.a
+noinst_LIBRARIES = libmem.a
libmem_a_SOURCES = mem0mem.c mem0pool.c
diff --git a/innobase/mtr/Makefile.am b/innobase/mtr/Makefile.am
index 972dcaca80e..1e93a34ce23 100644
--- a/innobase/mtr/Makefile.am
+++ b/innobase/mtr/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libmtr.a
+noinst_LIBRARIES = libmtr.a
libmtr_a_SOURCES = mtr0mtr.c mtr0log.c
diff --git a/innobase/odbc/Makefile.am b/innobase/odbc/Makefile.am
index d1a47bd8c18..f4282ba3907 100644
--- a/innobase/odbc/Makefile.am
+++ b/innobase/odbc/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libodbc.a
+noinst_LIBRARIES = libodbc.a
libodbc_a_SOURCES = odbc0odbc.c
diff --git a/innobase/os/Makefile.am b/innobase/os/Makefile.am
index b06670bc703..132ce07c83b 100644
--- a/innobase/os/Makefile.am
+++ b/innobase/os/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libos.a
+noinst_LIBRARIES = libos.a
libos_a_SOURCES = os0proc.c os0shm.c os0sync.c os0thread.c os0file.c
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 5ffcabf6fe6..53224eb59c5 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -214,9 +214,14 @@ os_file_get_last_error(void)
"InnoDB: the directory. It may also be you have created a subdirectory\n"
"InnoDB: of the same name as a data file.\n");
} else {
- fprintf(stderr,
- "InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
- "InnoDB: what the error number means.\n");
+ if (strerror((int)err) != NULL) {
+ fprintf(stderr,
+ "InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err));
+ }
+
+ fprintf(stderr,
+ "InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n"
+ "InnoDB: about operating system error numbers.\n");
}
}
@@ -252,9 +257,14 @@ os_file_get_last_error(void)
"InnoDB: The error means mysqld does not have the access rights to\n"
"InnoDB: the directory.\n");
} else {
- fprintf(stderr,
- "InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
- "InnoDB: what the error number means or use the perror program of MySQL.\n");
+ if (strerror((int)err) != NULL) {
+ fprintf(stderr,
+ "InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err));
+ }
+
+ fprintf(stderr,
+ "InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n"
+ "InnoDB: about operating system error numbers.\n");
}
}
@@ -511,10 +521,11 @@ try_again:
}
#endif
#ifdef UNIV_NON_BUFFERED_IO
- if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
+ if (type == OS_LOG_FILE) {
/* Do not use unbuffered i/o to log files because
- value 2 denotes that we do not flush the log at every
- commit, but only once per second */
+ to allow group commit to work when MySQL binlogging
+ is used we must separate log file write and log
+ file flush to disk. */
} else {
if (srv_win_file_flush_method ==
SRV_WIN_IO_UNBUFFERED) {
@@ -741,7 +752,12 @@ os_file_set_size(
offset = 0;
low = (ib_longlong)size + (((ib_longlong)size_high) << 32);
+
+ if (low >= (ib_longlong)(100 * 1024 * 1024)) {
+ fprintf(stderr, "InnoDB: Progress in MB:");
+ }
+
while (offset < low) {
if (low - offset < UNIV_PAGE_SIZE * 512) {
n_bytes = (ulint)(low - offset);
@@ -757,9 +773,24 @@ os_file_set_size(
ut_free(buf2);
goto error_handling;
}
+
+ /* Print about progress for each 100 MB written */
+ if ((offset + n_bytes) / (ib_longlong)(100 * 1024 * 1024)
+ != offset / (ib_longlong)(100 * 1024 * 1024)) {
+
+ fprintf(stderr, " %lu00",
+ (ulint)((offset + n_bytes)
+ / (ib_longlong)(100 * 1024 * 1024)));
+ }
+
offset += n_bytes;
}
+ if (low >= (ib_longlong)(100 * 1024 * 1024)) {
+
+ fprintf(stderr, "\n");
+ }
+
ut_free(buf2);
ret = os_file_flush(file);
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index a9127e6310a..407b280f805 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -68,9 +68,10 @@ os_event_create(
os_fast_mutex_init(&(event->os_mutex));
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
- pthread_cond_init(&(event->cond_var), pthread_condattr_default);
+ ut_a(0 == pthread_cond_init(&(event->cond_var),
+ pthread_condattr_default));
#else
- pthread_cond_init(&(event->cond_var), NULL);
+ ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
#endif
event->is_set = FALSE;
@@ -130,7 +131,7 @@ os_event_set(
/* Do nothing */
} else {
event->is_set = TRUE;
- pthread_cond_broadcast(&(event->cond_var));
+ ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
}
os_fast_mutex_unlock(&(event->os_mutex));
@@ -182,7 +183,7 @@ os_event_free(
ut_a(event);
os_fast_mutex_free(&(event->os_mutex));
- pthread_cond_destroy(&(event->cond_var));
+ ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
ut_free(event);
#endif
@@ -446,9 +447,9 @@ 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);
+ ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default));
#else
- pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
+ ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
#endif
#endif
}
@@ -495,10 +496,7 @@ os_fast_mutex_free(
ut_a(fast_mutex);
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
-#elif defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
- pthread_mutex_destroy(fast_mutex);
#else
- UT_NOT_USED(fast_mutex);
-
+ ut_a(0 == pthread_mutex_destroy(fast_mutex));
#endif
}
diff --git a/innobase/page/Makefile.am b/innobase/page/Makefile.am
index 85fe585a633..2e260787438 100644
--- a/innobase/page/Makefile.am
+++ b/innobase/page/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libpage.a
+noinst_LIBRARIES = libpage.a
libpage_a_SOURCES = page0page.c page0cur.c
diff --git a/innobase/pars/Makefile.am b/innobase/pars/Makefile.am
index e5611f9dfc6..2356f330486 100644
--- a/innobase/pars/Makefile.am
+++ b/innobase/pars/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libpars.a
+noinst_LIBRARIES = libpars.a
noinst_HEADERS = pars0grm.h
diff --git a/innobase/que/Makefile.am b/innobase/que/Makefile.am
index b74d4dbf6a0..d9c046b4f4c 100644
--- a/innobase/que/Makefile.am
+++ b/innobase/que/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libque.a
+noinst_LIBRARIES = libque.a
libque_a_SOURCES = que0que.c
diff --git a/innobase/read/Makefile.am b/innobase/read/Makefile.am
index 16224f4f7f4..7edf2a5a2e1 100644
--- a/innobase/read/Makefile.am
+++ b/innobase/read/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libread.a
+noinst_LIBRARIES = libread.a
libread_a_SOURCES = read0read.c
diff --git a/innobase/rem/Makefile.am b/innobase/rem/Makefile.am
index ef0cde9bd7a..e2b2fdaf669 100644
--- a/innobase/rem/Makefile.am
+++ b/innobase/rem/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = librem.a
+noinst_LIBRARIES = librem.a
librem_a_SOURCES = rem0rec.c rem0cmp.c
diff --git a/innobase/row/Makefile.am b/innobase/row/Makefile.am
index e4fcbe8f715..bd09f9a237d 100644
--- a/innobase/row/Makefile.am
+++ b/innobase/row/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = librow.a
+noinst_LIBRARIES = librow.a
librow_a_SOURCES = row0ins.c row0mysql.c row0purge.c row0row.c row0sel.c\
row0uins.c row0umod.c row0undo.c row0upd.c row0vers.c
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 990ef99b2a4..3af9e1b752b 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -323,7 +323,7 @@ row_ins_clust_index_entry_by_modify(
/*************************************************************************
Returns TRUE if in a cascaded update/delete an ancestor node of node
-updates table. */
+updates (not DELETE, but UPDATE) table. */
static
ibool
row_ins_cascade_ancestor_updates_table(
@@ -341,7 +341,7 @@ row_ins_cascade_ancestor_updates_table(
upd_node = parent;
- if (upd_node->table == table) {
+ if (upd_node->table == table && upd_node->is_delete == FALSE) {
return(TRUE);
}
@@ -438,6 +438,111 @@ row_ins_cascade_calc_update_vec(
}
/*************************************************************************
+Reports a foreign key error associated with an update or a delete of a
+parent table index entry. */
+static
+void
+row_ins_foreign_report_err(
+/*=======================*/
+ char* errstr, /* in: error string from the viewpoint
+ of the parent table */
+ que_thr_t* thr, /* in: query thread whose run_node
+ is an update node */
+ dict_foreign_t* foreign, /* in: foreign key constraint */
+ rec_t* rec, /* in: a matching index record in the
+ child table */
+ dtuple_t* entry) /* in: index entry in the parent
+ table */
+{
+ char* buf = dict_foreign_err_buf;
+
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf), " Transaction:\n");
+ trx_print(buf + strlen(buf), thr_get_trx(thr));
+
+ sprintf(buf + strlen(buf),
+"Foreign key constraint fails for table %.500s:\n",
+ foreign->foreign_table_name);
+ dict_print_info_on_foreign_key_in_create_format(
+ foreign, buf + strlen(buf));
+ sprintf(buf + strlen(buf), "\n%s", errstr);
+ sprintf(buf + strlen(buf),
+" in parent table, in index %.500s tuple:\n",
+ foreign->referenced_index->name);
+ if (entry) {
+ dtuple_sprintf(buf + strlen(buf), 1000, entry);
+ }
+ sprintf(buf + strlen(buf),
+"\nBut in child table %.500s, in index %.500s, there is a record:\n",
+ foreign->foreign_table_name, foreign->foreign_index->name);
+ if (rec) {
+ rec_sprintf(buf + strlen(buf), 1000, rec);
+ }
+ sprintf(buf + strlen(buf), "\n");
+
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+
+ mutex_exit(&dict_foreign_err_mutex);
+}
+
+/*************************************************************************
+Reports a foreign key error to dict_foreign_err_buf when we are trying
+to add an index entry to a child table. Note that the adding may be the result
+of an update, too. */
+static
+void
+row_ins_foreign_report_add_err(
+/*===========================*/
+ que_thr_t* thr, /* in: query thread whose run_node
+ is an insert node */
+ dict_foreign_t* foreign, /* in: foreign key constraint */
+ rec_t* rec, /* in: a record in the parent table:
+ it does not match entry because we
+ have an error! */
+ dtuple_t* entry) /* in: index entry to insert in the
+ child table */
+{
+ char* buf = dict_foreign_err_buf;
+
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf), " Transaction:\n");
+ trx_print(buf + strlen(buf), thr_get_trx(thr));
+ sprintf(buf + strlen(buf),
+"Foreign key constraint fails for table %.500s:\n",
+ foreign->foreign_table_name);
+ dict_print_info_on_foreign_key_in_create_format(
+ foreign, buf + strlen(buf));
+ sprintf(buf + strlen(buf),
+"\nTrying to add in child table, in index %.500s tuple:\n",
+ foreign->foreign_index->name);
+ if (entry) {
+ dtuple_sprintf(buf + strlen(buf), 1000, entry);
+ }
+ sprintf(buf + strlen(buf),
+"\nBut in parent table %.500s, in index %.500s,\n"
+"the closest match we can find is record:\n",
+ foreign->referenced_table_name,
+ foreign->referenced_index->name);
+ if (rec && page_rec_is_supremum(rec)) {
+ /* If the cursor ended on a supremum record, it is better
+ to report the previous record in the error message, so that
+ the user gets a more descriptive error message. */
+ rec = page_rec_get_prev(rec);
+ }
+
+ if (rec) {
+ rec_sprintf(buf + strlen(buf), 1000, rec);
+ }
+ sprintf(buf + strlen(buf), "\n");
+
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+
+ mutex_exit(&dict_foreign_err_mutex);
+}
+
+/*************************************************************************
Perform referential actions or checks when a parent row is deleted or updated
and the constraint had an ON DELETE or ON UPDATE condition which was not
RESTRICT. */
@@ -453,6 +558,8 @@ row_ins_foreign_check_on_constraint(
type is != 0 */
btr_pcur_t* pcur, /* in: cursor placed on a matching
index record in the child table */
+ dtuple_t* entry, /* in: index entry in the parent
+ table */
mtr_t* mtr) /* in: mtr holding the latch of pcur
page */
{
@@ -506,6 +613,10 @@ row_ins_foreign_check_on_constraint(
return(DB_SUCCESS);
}
+ row_ins_foreign_report_err((char*)"Trying to delete",
+ thr, foreign,
+ btr_pcur_get_rec(pcur), entry);
+
return(DB_ROW_IS_REFERENCED);
}
@@ -523,6 +634,10 @@ row_ins_foreign_check_on_constraint(
return(DB_SUCCESS);
}
+ row_ins_foreign_report_err((char*)"Trying to update",
+ thr, foreign,
+ btr_pcur_get_rec(pcur), entry);
+
return(DB_ROW_IS_REFERENCED);
}
@@ -563,14 +678,13 @@ row_ins_foreign_check_on_constraint(
}
}
- /* We do not allow cyclic cascaded updating of the same
- table. Check that we are not updating the same table which
- is already being modified in this cascade chain. We have to
- check this because the modification of the indexes of a
- 'parent' table may still be incomplete, and we must avoid
- seeing the indexes of the parent table in an inconsistent
- state! In this way we also prevent possible infinite
- update loops caused by cyclic cascaded updates. */
+ /* We do not allow cyclic cascaded updating (DELETE is allowed,
+ but not UPDATE) of the same table, as this can lead to an infinite
+ cycle. Check that we are not updating the same table which is
+ already being modified in this cascade chain. We have to check
+ this also because the modification of the indexes of a 'parent'
+ table may still be incomplete, and we must avoid seeing the indexes
+ of the parent table in an inconsistent state! */
if (!cascade->is_delete
&& row_ins_cascade_ancestor_updates_table(cascade, table)) {
@@ -580,6 +694,10 @@ row_ins_foreign_check_on_constraint(
err = DB_ROW_IS_REFERENCED;
+ row_ins_foreign_report_err(
+(char*)"Trying an update, possibly causing a cyclic cascaded update\n"
+"in the child table,", thr, foreign, btr_pcur_get_rec(pcur), entry);
+
goto nonstandard_exit_func;
}
@@ -809,11 +927,10 @@ row_ins_check_foreign_constraint(
dictionary cache if they exist at all */
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
table, else the referenced table */
- dict_index_t* index __attribute__((unused)),/* in: index in table */
dtuple_t* entry, /* in: index entry for index */
que_thr_t* thr) /* in: query thread */
{
- upd_node_t* upd_node;
+ upd_node_t* upd_node;
dict_table_t* check_table;
dict_index_t* check_index;
ulint n_fields_cmp;
@@ -824,6 +941,7 @@ row_ins_check_foreign_constraint(
int cmp;
ulint err;
ulint i;
+ char* buf = dict_foreign_err_buf;
mtr_t mtr;
run_again:
@@ -884,6 +1002,25 @@ run_again:
if (check_table == NULL) {
if (check_ref) {
+ mutex_enter(&dict_foreign_err_mutex);
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf), " Transaction:\n");
+ trx_print(buf + strlen(buf), thr_get_trx(thr));
+ sprintf(buf + strlen(buf),
+"Foreign key constraint fails for table %.500s:\n",
+ foreign->foreign_table_name);
+ dict_print_info_on_foreign_key_in_create_format(
+ foreign, buf + strlen(buf));
+ sprintf(buf + strlen(buf),
+"\nTrying to add to index %.500s tuple:\n", foreign->foreign_index->name);
+ dtuple_sprintf(buf + strlen(buf), 1000, entry);
+ sprintf(buf + strlen(buf),
+"\nBut the parent table %.500s does not currently exist!\n",
+ foreign->referenced_table_name);
+
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+ mutex_exit(&dict_foreign_err_mutex);
+
return(DB_NO_REFERENCED_ROW);
}
@@ -949,7 +1086,8 @@ run_again:
if (cmp == 0) {
if (rec_get_deleted_flag(rec)) {
- err = row_ins_set_shared_rec_lock(LOCK_ORDINARY,
+ err = row_ins_set_shared_rec_lock(
+ LOCK_ORDINARY,
rec, check_index, thr);
if (err != DB_SUCCESS) {
@@ -989,13 +1127,17 @@ run_again:
err =
row_ins_foreign_check_on_constraint(
- thr, foreign, &pcur, &mtr);
-
+ thr, foreign, &pcur, entry,
+ &mtr);
if (err != DB_SUCCESS) {
break;
}
} else {
+ row_ins_foreign_report_err(
+ (char*)"Trying to delete or update",
+ thr, foreign, rec, entry);
+
err = DB_ROW_IS_REFERENCED;
break;
}
@@ -1012,6 +1154,8 @@ run_again:
if (check_ref) {
err = DB_NO_REFERENCED_ROW;
+ row_ins_foreign_report_add_err(
+ thr, foreign, rec, entry);
} else {
err = DB_SUCCESS;
}
@@ -1025,6 +1169,9 @@ next_rec:
if (!moved) {
if (check_ref) {
+ rec = btr_pcur_get_rec(&pcur);
+ row_ins_foreign_report_add_err(
+ thr, foreign, rec, entry);
err = DB_NO_REFERENCED_ROW;
} else {
err = DB_SUCCESS;
@@ -1100,7 +1247,7 @@ row_ins_check_foreign_constraints(
}
err = row_ins_check_foreign_constraint(TRUE, foreign,
- table, index, entry, thr);
+ table, entry, thr);
if (got_s_lock) {
row_mysql_unfreeze_data_dictionary(trx);
}
@@ -1116,6 +1263,48 @@ row_ins_check_foreign_constraints(
return(DB_SUCCESS);
}
+/*************************************************************************
+Reports a UNIQUE key error to dict_unique_err_buf so that SHOW INNODB
+STATUS can print it. */
+static
+void
+row_ins_unique_report_err(
+/*======================*/
+ que_thr_t* thr, /* in: query thread */
+ rec_t* rec, /* in: a record in the index */
+ dtuple_t* entry, /* in: index entry to insert in the index */
+ dict_index_t* index) /* in: index */
+{
+ char* buf = dict_unique_err_buf;
+
+ /* The foreign err mutex protects also dict_unique_err_buf */
+
+ mutex_enter(&dict_foreign_err_mutex);
+
+ ut_sprintf_timestamp(buf);
+ sprintf(buf + strlen(buf), " Transaction:\n");
+ trx_print(buf + strlen(buf), thr_get_trx(thr));
+
+ sprintf(buf + strlen(buf),
+"Unique key constraint fails for table %.500s.\n", index->table_name);
+ sprintf(buf + strlen(buf),
+"Trying to add in index %.500s (%lu fields unique) tuple:\n", index->name,
+ dict_index_get_n_unique(index));
+
+ dtuple_sprintf(buf + strlen(buf), 1000, entry);
+
+ sprintf(buf + strlen(buf),
+"\nBut there is already a record:\n");
+
+ rec_sprintf(buf + strlen(buf), 1000, rec);
+
+ sprintf(buf + strlen(buf), "\n");
+
+ ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
+
+ mutex_exit(&dict_foreign_err_mutex);
+}
+
/*******************************************************************
Checks if a unique key violation to rec would occur at the index entry
insert. */
@@ -1246,10 +1435,8 @@ row_ins_scan_sec_index_for_duplicate(
if (cmp == 0) {
if (row_ins_dupl_error_with_rec(rec, entry, index)) {
- /* printf("Duplicate key in index %s\n",
- index->name);
- dtuple_print(entry); */
-
+ row_ins_unique_report_err(thr, rec, entry,
+ index);
err = DB_DUPLICATE_KEY;
thr_get_trx(thr)->error_info = index;
@@ -1344,7 +1531,8 @@ row_ins_duplicate_error_in_clust(
if (row_ins_dupl_error_with_rec(rec, entry,
cursor->index)) {
trx->error_info = cursor->index;
-
+ row_ins_unique_report_err(thr, rec, entry,
+ cursor->index);
return(DB_DUPLICATE_KEY);
}
}
@@ -1368,6 +1556,8 @@ row_ins_duplicate_error_in_clust(
cursor->index)) {
trx->error_info = cursor->index;
+ row_ins_unique_report_err(thr, rec, entry,
+ cursor->index);
return(DB_DUPLICATE_KEY);
}
}
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 1bb33551da8..6d1f6f6e40e 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -6,7 +6,7 @@ Contains also create table and other data dictionary operations.
Created 9/17/2000 Heikki Tuuri
*******************************************************/
-
+
#include "row0mysql.h"
#ifdef UNIV_NONINL
@@ -289,6 +289,17 @@ handle_new_error:
"InnoDB: my.cnf and restart the database.\n");
exit(1);
+ } else if (err == DB_CORRUPTION) {
+
+ fprintf(stderr,
+ "InnoDB: We detected index corruption in an InnoDB type table.\n"
+ "InnoDB: You have to dump + drop + reimport the table or, in\n"
+ "InnoDB: a case of widespread corruption, dump all InnoDB\n"
+ "InnoDB: tables and recreate the whole InnoDB tablespace.\n"
+ "InnoDB: If the mysqld server crashes after the startup or when\n"
+ "InnoDB: you dump the tables, look at section 6.1 of\n"
+ "InnoDB: http://www.innodb.com/ibman.html for help.\n");
+
} else {
fprintf(stderr, "InnoDB: unknown error code %lu\n", err);
ut_a(0);
@@ -337,6 +348,9 @@ row_create_prebuilt(
prebuilt->mysql_has_locked = FALSE;
prebuilt->index = NULL;
+
+ prebuilt->used_in_HANDLER = FALSE;
+
prebuilt->n_template = 0;
prebuilt->mysql_template = NULL;
@@ -1169,7 +1183,7 @@ row_mysql_recover_tmp_table(
return(DB_ERROR);
}
- if (0 == ut_memcmp(ptr, "/rsql", 5)) {
+ if (0 == ut_memcmp(ptr, (char*)"/rsql", 5)) {
ptr++;
*ptr = '#';
@@ -1293,10 +1307,10 @@ row_create_table_for_mysql(
}
trx->op_info = (char *) "creating table";
-
- if (0 == ut_strcmp(table->name, "mysql/host")
- || 0 == ut_strcmp(table->name, "mysql/user")
- || 0 == ut_strcmp(table->name, "mysql/db")) {
+
+ if (0 == ut_strcmp(table->name, (char*)"mysql/host")
+ || 0 == ut_strcmp(table->name, (char*)"mysql/user")
+ || 0 == ut_strcmp(table->name, (char*)"mysql/db")) {
fprintf(stderr,
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
@@ -1316,7 +1330,7 @@ row_create_table_for_mysql(
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
- "_recover_innodb_tmp_table", keywordlen)) {
+ (char*)"_recover_innodb_tmp_table", keywordlen)) {
/* MySQL prevents accessing of tables whose name begins
with #sql, that is temporary tables. If mysqld crashes in
@@ -1384,7 +1398,7 @@ row_create_table_for_mysql(
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
- "innodb_mem_validate", keywordlen)) {
+ (char*)"innodb_mem_validate", keywordlen)) {
/* We define here a debugging feature intended for
developers */
@@ -1494,7 +1508,7 @@ row_create_index_for_mysql(
if (namelen >= keywordlen
&& 0 == ut_memcmp(
index->table_name + namelen - keywordlen,
- "_recover_innodb_tmp_table", keywordlen)) {
+ (char*)"_recover_innodb_tmp_table", keywordlen)) {
return(DB_SUCCESS);
}
@@ -1599,7 +1613,7 @@ row_table_add_foreign_constraints(
if (namelen >= keywordlen
&& 0 == ut_memcmp(
name + namelen - keywordlen,
- "_recover_innodb_tmp_table", keywordlen)) {
+ (char*)"_recover_innodb_tmp_table", keywordlen)) {
return(DB_SUCCESS);
}
@@ -1663,7 +1677,7 @@ row_drop_table_for_mysql_in_background(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
trx_commit_for_mysql(trx);
@@ -1821,7 +1835,6 @@ row_drop_table_for_mysql(
ulint len;
ulint namelen;
ulint keywordlen;
- ulint rounds = 0;
ibool locked_dictionary = FALSE;
char buf[10000];
@@ -2168,7 +2181,7 @@ row_is_mysql_tmp_table_name(
ulint i;
for (i = 0; i <= ut_strlen(name) - 5; i++) {
- if (ut_memcmp(name + i, "/#sql", 5) == 0) {
+ if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) {
return(TRUE);
}
@@ -2190,12 +2203,16 @@ row_rename_table_for_mysql(
{
dict_table_t* table;
que_thr_t* thr;
- que_t* graph;
+ que_t* graph = NULL;
ulint err;
char* str1;
char* str2;
char* str3;
+ mem_heap_t* heap = NULL;
+ char** constraints_to_drop = NULL;
+ ulint n_constraints_to_drop = 0;
ulint len;
+ ulint i;
char buf[10000];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -2213,10 +2230,10 @@ row_rename_table_for_mysql(
trx_commit_for_mysql(trx);
return(DB_ERROR);
}
-
- if (0 == ut_strcmp(new_name, "mysql/host")
- || 0 == ut_strcmp(new_name, "mysql/user")
- || 0 == ut_strcmp(new_name, "mysql/db")) {
+
+ if (0 == ut_strcmp(new_name, (char*)"mysql/host")
+ || 0 == ut_strcmp(new_name, (char*)"mysql/user")
+ || 0 == ut_strcmp(new_name, (char*)"mysql/db")) {
fprintf(stderr,
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
@@ -2230,6 +2247,19 @@ row_rename_table_for_mysql(
trx->op_info = (char *) "renaming table";
trx_start_if_not_started(trx);
+ /* Serialize data dictionary operations with dictionary mutex:
+ no deadlocks can occur then in these operations */
+
+ row_mysql_lock_data_dictionary(trx);
+
+ table = dict_table_get_low(old_name);
+
+ if (!table) {
+ err = DB_TABLE_NOT_FOUND;
+
+ goto funct_exit;
+ }
+
str1 = (char *)
"PROCEDURE RENAME_TABLE_PROC () IS\n"
"new_table_name CHAR;\n"
@@ -2242,14 +2272,43 @@ row_rename_table_for_mysql(
if (row_is_mysql_tmp_table_name(new_name)) {
- /* We want to preserve the original foreign key
- constraint definitions despite the name change */
+ /* MySQL is doing an ALTER TABLE command and it renames the
+ original table to a temporary table name. We want to preserve
+ the original foreign key constraint definitions despite the
+ name change. An exception is those constraints for which
+ the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/
- str3 = (char*)
- "';\n"
- "UPDATE SYS_TABLES SET NAME = new_table_name\n"
- "WHERE NAME = old_table_name;\n"
- "END;\n";
+ heap = mem_heap_create(100);
+
+ err = dict_foreign_parse_drop_constraints(heap, trx,
+ table,
+ &n_constraints_to_drop,
+ &constraints_to_drop);
+ if (err != DB_SUCCESS) {
+
+ goto funct_exit;
+ }
+
+ str3 = mem_heap_alloc(heap,
+ 1000 + 500 * n_constraints_to_drop);
+ *str3 = '\0';
+ sprintf(str3,
+ "';\n"
+ "UPDATE SYS_TABLES SET NAME = new_table_name\n"
+ "WHERE NAME = old_table_name;\n");
+
+ for (i = 0; i < n_constraints_to_drop; i++) {
+ sprintf(str3 + strlen(str3),
+ "DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n"
+ "DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n",
+ constraints_to_drop[i],
+ constraints_to_drop[i]);
+ }
+
+ sprintf(str3 + strlen(str3),
+ "END;\n");
+
+ ut_a(strlen(str3) < 1000 + 500 * n_constraints_to_drop);
} else {
str3 = (char*)
"';\n"
@@ -2280,13 +2339,6 @@ row_rename_table_for_mysql(
ut_memcpy(buf + len, str3, ut_strlen(str3) + 1);
- /* Serialize data dictionary operations with dictionary mutex:
- no deadlocks can occur then in these operations */
-
- row_mysql_lock_data_dictionary(trx);
-
- table = dict_table_get_low(old_name);
-
graph = pars_sql(buf);
ut_a(graph);
@@ -2296,12 +2348,6 @@ row_rename_table_for_mysql(
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
- if (!table) {
- err = DB_TABLE_NOT_FOUND;
-
- goto funct_exit;
- }
-
ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
que_run_threads(thr);
@@ -2342,6 +2388,13 @@ row_rename_table_for_mysql(
if (row_is_mysql_tmp_table_name(old_name)) {
+ /* MySQL is doing an ALTER TABLE command and it
+ renames the created temporary table to the name
+ of the original table. In the ALTER TABLE we maybe
+ created some FOREIGN KEY constraints for the temporary
+ table. But we want to load also the foreign key
+ constraint definitions for the original table name. */
+
err = dict_load_foreigns(new_name);
if (err != DB_SUCCESS) {
@@ -2367,7 +2420,13 @@ row_rename_table_for_mysql(
funct_exit:
row_mysql_unlock_data_dictionary(trx);
- que_graph_free(graph);
+ if (graph) {
+ que_graph_free(graph);
+ }
+
+ if (heap) {
+ mem_heap_free(heap);
+ }
trx_commit_for_mysql(trx);
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index fb508e7b1da..97a69f76eaa 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2620,6 +2620,24 @@ row_search_for_mysql(
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
*/
/*-------------------------------------------------------------*/
+ /* PHASE 0: Release a possible s-latch we are holding on the
+ adaptive hash index latch if there is someone waiting behind */
+
+ if (trx->has_search_latch
+ && btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
+
+ /* There is an x-latch request on the adaptive hash index:
+ release the s-latch to reduce starvation and wait for
+ BTR_SEA_TIMEOUT rounds before trying to keep it again over
+ calls from MySQL */
+
+ rw_lock_s_unlock(&btr_search_latch);
+ trx->has_search_latch = FALSE;
+
+ trx->search_latch_timeout = BTR_SEA_TIMEOUT;
+ }
+
+ /*-------------------------------------------------------------*/
/* PHASE 1: Try to pop the row from the prefetch cache */
if (direction == 0) {
@@ -2685,16 +2703,31 @@ row_search_for_mysql(
mode = pcur->search_mode;
}
+ if ((direction == ROW_SEL_NEXT || direction == ROW_SEL_PREV)
+ && pcur->old_stored != BTR_PCUR_OLD_STORED) {
+
+ /* MySQL sometimes seems to do fetch next or fetch prev even
+ if the search condition is unique; this can, for example,
+ happen with the HANDLER commands; we do not always store the
+ pcur position in this case, so we cannot restore cursor
+ position, and must return immediately */
+
+ /* printf("%s record not found 1\n", index->name); */
+
+ trx->op_info = (char *) "";
+ return(DB_RECORD_NOT_FOUND);
+ }
+
mtr_start(&mtr);
/* 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
+ 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
+ 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. */
+ delete-marked records. */
if (match_mode == ROW_SEL_EXACT
&& index->type & DICT_UNIQUE
@@ -2715,25 +2748,9 @@ row_search_for_mysql(
if (unique_search
&& index->type & DICT_CLUSTERED
&& !prebuilt->templ_contains_blob
+ && !prebuilt->used_in_HANDLER
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
- if (direction == ROW_SEL_NEXT) {
- /* MySQL sometimes seems to do fetch next even
- if the search condition is unique; we do not store
- pcur position in this case, so we cannot
- restore cursor position, and must return
- immediately */
-
- mtr_commit(&mtr);
-
- /* printf("%s record not found 1\n", index->name); */
-
- trx->op_info = (char *) "";
- return(DB_RECORD_NOT_FOUND);
- }
-
- ut_a(direction == 0); /* We cannot do fetch prev, as we have
- not stored the cursor position */
mode = PAGE_CUR_GE;
unique_search_from_clust_index = TRUE;
@@ -2754,23 +2771,7 @@ row_search_for_mysql(
NOT prepared to inserts interleaved with the SELECT,
and if we try that, we can deadlock on the adaptive
hash index semaphore! */
-
- if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
- /* There is an x-latch request: release
- a possible s-latch to reduce starvation
- and wait for BTR_SEA_TIMEOUT rounds before
- trying to keep it again over calls from
- MySQL */
-
- if (trx->has_search_latch) {
- rw_lock_s_unlock(&btr_search_latch);
- trx->has_search_latch = FALSE;
- }
- trx->search_latch_timeout = BTR_SEA_TIMEOUT;
-
- goto no_shortcut;
- }
#ifndef UNIV_SEARCH_DEBUG
if (!trx->has_search_latch) {
rw_lock_s_lock(&btr_search_latch);
@@ -2806,6 +2807,10 @@ row_search_for_mysql(
}
trx->op_info = (char *) "";
+
+ /* NOTE that we do NOT store the cursor
+ position */
+
return(DB_SUCCESS);
} else if (shortcut == SEL_EXHAUSTED) {
@@ -2825,6 +2830,10 @@ row_search_for_mysql(
}
trx->op_info = (char *) "";
+
+ /* NOTE that we do NOT store the cursor
+ position */
+
return(DB_RECORD_NOT_FOUND);
}
@@ -2833,7 +2842,6 @@ row_search_for_mysql(
}
}
-no_shortcut:
/*-------------------------------------------------------------*/
/* PHASE 3: Open or restore index cursor position */
@@ -3206,6 +3214,7 @@ rec_loop:
&& prebuilt->select_lock_type == LOCK_NONE
&& !prebuilt->templ_contains_blob
&& !prebuilt->clust_index_was_generated
+ && !prebuilt->used_in_HANDLER
&& prebuilt->template_type
!= ROW_MYSQL_DUMMY_TEMPLATE) {
@@ -3214,7 +3223,9 @@ rec_loop:
update, that is why we require ...lock_type == LOCK_NONE.
Since we keep space in prebuilt only for the BLOBs of
a single row, we cannot cache rows in the case there
- are BLOBs in the fields to be fetched. */
+ are BLOBs in the fields to be fetched. In HANDLER we do
+ not cache rows because there the cursor is a scrollable
+ cursor. */
row_sel_push_cache_row_for_mysql(prebuilt, rec);
@@ -3243,11 +3254,16 @@ rec_loop:
}
}
got_row:
- /* TODO: should we in every case store the cursor position, even
- if this is just a join, for example? */
+ /* We have an optimization to save CPU time: if this is a consistent
+ read on a unique condition on the clustered index, then we do not
+ store the pcur position, because any fetch next or prev will anyway
+ return 'end of file'. An exception is the MySQL HANDLER command
+ where the user can move the cursor with PREV or NEXT even after
+ a unique search. */
if (!unique_search_from_clust_index
- || prebuilt->select_lock_type == LOCK_X) {
+ || prebuilt->select_lock_type == LOCK_X
+ || prebuilt->used_in_HANDLER) {
/* Inside an update always store the cursor position */
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 64569bf3f96..5fce1c1861b 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -218,7 +218,7 @@ row_upd_check_references_constraints(
being dropped while the check is running. */
err = row_ins_check_foreign_constraint(FALSE, foreign,
- table, index, entry, thr);
+ table, entry, thr);
if (foreign->foreign_table) {
mutex_enter(&(dict_sys->mutex));
diff --git a/innobase/srv/Makefile.am b/innobase/srv/Makefile.am
index b4bdeb7c03b..752683b82b8 100644
--- a/innobase/srv/Makefile.am
+++ b/innobase/srv/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libsrv.a
+noinst_LIBRARIES = libsrv.a
libsrv_a_SOURCES = srv0srv.c srv0que.c srv0start.c
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index af11516e9f0..7cd831fe239 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -162,6 +162,13 @@ 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;
+/* The InnoDB main thread tries to keep the ratio of modified pages
+in the buffer pool to all database pages in the buffer pool smaller than
+the following number. But it is not guaranteed that the value stays below
+that during a time of heavy update/insert activity. */
+
+ulint srv_max_buf_pool_modified_pct = 90;
+
/* 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 */
@@ -1881,11 +1888,11 @@ retry:
/* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */
- trx->op_info = "waiting in InnoDB queue";
+ trx->op_info = (char*)"waiting in InnoDB queue";
os_event_wait(slot->event);
- trx->op_info = "";
+ trx->op_info = (char*)"";
os_fast_mutex_lock(&srv_conc_mutex);
@@ -2368,12 +2375,35 @@ srv_sprintf_innodb_monitor(
buf = buf + strlen(buf);
ut_a(buf < buf_end + 1500);
- buf += sprintf(buf, "------------\n"
- "TRANSACTIONS\n"
- "------------\n");
+ if (*dict_foreign_err_buf != '\0') {
+ buf += sprintf(buf,
+ "------------------------\n"
+ "LATEST FOREIGN KEY ERROR\n"
+ "------------------------\n");
+
+ if (buf_end - buf > 6000) {
+ buf+= sprintf(buf, "%.4000s", dict_foreign_err_buf);
+ }
+ }
+
+ ut_a(buf < buf_end + 1500);
+
+ if (*dict_unique_err_buf != '\0') {
+ buf += sprintf(buf,
+"---------------------------------------------------------------\n"
+"LATEST UNIQUE KEY ERROR (is masked in REPLACE or INSERT IGNORE)\n"
+"---------------------------------------------------------------\n");
+
+ if (buf_end - buf > 6000) {
+ buf+= sprintf(buf, "%.4000s", dict_unique_err_buf);
+ }
+ }
+
+ ut_a(buf < buf_end + 1500);
+
lock_print_info(buf, buf_end);
buf = buf + strlen(buf);
-
+
buf += sprintf(buf, "--------\n"
"FILE I/O\n"
"--------\n");
@@ -2777,6 +2807,7 @@ srv_master_thread(
ulint n_ios_old;
ulint n_ios_very_old;
ulint n_pend_ios;
+ ibool skip_sleep = FALSE;
ulint i;
UT_NOT_USED(arg);
@@ -2794,24 +2825,42 @@ srv_master_thread(
os_event_set(srv_sys->operational);
loop:
+ /*****************************************************************/
+ /* ---- When there is database activity by users, we cycle in this
+ loop */
+
srv_main_thread_op_info = (char*) "reserving kernel mutex";
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
mutex_enter(&kernel_mutex);
+ /* Store the user activity counter at the start of this loop */
old_activity_count = srv_activity_count;
mutex_exit(&kernel_mutex);
- /* We run purge and a batch of ibuf_contract every 10 seconds, even
- if the server were active: */
+ if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
+
+ goto suspend_thread;
+ }
+
+ /* ---- We run the following loop approximately once per second
+ when there is database activity */
+
+ skip_sleep = FALSE;
for (i = 0; i < 10; i++) {
n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
srv_main_thread_op_info = (char*)"sleeping";
- os_thread_sleep(1000000);
+
+ if (!skip_sleep) {
+
+ os_thread_sleep(1000000);
+ }
+
+ skip_sleep = FALSE;
/* ALTER TABLE in MySQL requires on Unix that the table handler
can drop tables lazily after there no longer are SELECT
@@ -2824,9 +2873,9 @@ loop:
srv_main_thread_op_info = (char*)"";
- if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
+ if (srv_fast_shutdown && srv_shutdown_state > 0) {
- goto suspend_thread;
+ goto background_loop;
}
/* We flush the log once in a second even if no commit
@@ -2834,10 +2883,9 @@ loop:
at transaction commit */
srv_main_thread_op_info = (char*)"flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
- /* If there were less than 10 i/os during the
+ /* If there were less than 5 i/os during the
one second sleep, we assume that there is free
disk i/o capacity available, and it makes sense to
do an insert buffer merge. */
@@ -2846,35 +2894,45 @@ loop:
+ log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
- if (n_pend_ios < 3 && (n_ios - n_ios_old < 10)) {
+ if (n_pend_ios < 3 && (n_ios - n_ios_old < 5)) {
srv_main_thread_op_info =
(char*)"doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5);
srv_main_thread_op_info =
(char*)"flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP,
+ TRUE);
}
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
- goto background_loop;
+ if (buf_get_modified_ratio_pct() >
+ srv_max_buf_pool_modified_pct) {
+
+ /* Try to keep the number of modified pages in the
+ buffer pool under the limit wished by the user */
+
+ n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
+ ut_dulint_max);
+
+ /* If we had to do the flush, it may have taken
+ even more than 1 second, and also, there may be more
+ to flush. Do not sleep 1 second during the next
+ iteration of this loop. */
+
+ skip_sleep = TRUE;
}
if (srv_activity_count == old_activity_count) {
- if (srv_print_thread_releases) {
- printf("Master thread wakes up!\n");
- }
+ /* There is no user activity at the moment, go to
+ the background loop */
goto background_loop;
}
}
- if (srv_print_thread_releases) {
- printf("Master thread wakes up!\n");
- }
+ /* ---- We perform the following code approximately once per
+ 10 seconds when there is database activity */
#ifdef MEM_PERIODIC_CHECK
/* Check magic numbers of every allocated mem block once in 10
@@ -2883,7 +2941,7 @@ loop:
#endif
/* If there were less than 200 i/os during the 10 second period,
we assume that there is free disk i/o capacity available, and it
- makes sense to do a buffer pool flush. */
+ makes sense to flush 100 pages. */
n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
@@ -2891,11 +2949,10 @@ loop:
if (n_pend_ios < 3 && (n_ios - n_ios_very_old < 200)) {
srv_main_thread_op_info = (char*) "flushing buffer pool pages";
- buf_flush_batch(BUF_FLUSH_LIST, 50, ut_dulint_max);
+ buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
srv_main_thread_op_info = (char*) "flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
}
/* We run a batch of insert buffer merge every 10 seconds,
@@ -2905,8 +2962,7 @@ loop:
ibuf_contract_for_n_pages(TRUE, 5);
srv_main_thread_op_info = (char*)"flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* We run a full purge every 10 seconds, even if the server
were active */
@@ -2930,27 +2986,32 @@ loop:
if (difftime(current_time, last_flush_time) > 1) {
srv_main_thread_op_info = (char*) "flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP,
+ TRUE);
last_flush_time = current_time;
}
}
+
+ srv_main_thread_op_info = (char*)"flushing buffer pool pages";
-background_loop:
- /* In this loop we run background operations when the server
- is quiet and we also come here about once in 10 seconds */
+ /* Flush a few oldest pages to make a new checkpoint younger */
- srv_main_thread_op_info = (char*)"doing background drop tables";
+ if (buf_get_modified_ratio_pct() > 70) {
- n_tables_to_drop = row_drop_tables_for_mysql_in_background();
+ /* If there are lots of modified pages in the buffer pool
+ (> 70 %), we assume we can afford reserving the disk(s) for
+ the time it requires to flush 100 pages */
- srv_main_thread_op_info = (char*)"";
-
- srv_main_thread_op_info = (char*)"flushing buffer pool pages";
-
- /* Flush a few oldest pages to make the checkpoint younger */
+ n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
+ ut_dulint_max);
+ } else {
+ /* Otherwise, we only flush a small number of pages so that
+ we do not unnecessarily use much disk i/o capacity from
+ other work */
- n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, ut_dulint_max);
+ n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10,
+ ut_dulint_max);
+ }
srv_main_thread_op_info = (char*)"making checkpoint";
@@ -2961,16 +3022,31 @@ background_loop:
srv_main_thread_op_info = (char*)"reserving kernel mutex";
mutex_enter(&kernel_mutex);
+
+ /* ---- When there is database activity, we jump from here back to
+ the start of loop */
+
if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex);
goto loop;
}
- old_activity_count = srv_activity_count;
+
mutex_exit(&kernel_mutex);
+ /* If the database is quiet, we enter the background loop */
+
+ /*****************************************************************/
+background_loop:
+ /* ---- In this loop we run background operations when the server
+ is quiet from user activity */
+
/* The server has been quiet for a while: start running background
operations */
+ srv_main_thread_op_info = (char*)"doing background drop tables";
+
+ n_tables_to_drop = row_drop_tables_for_mysql_in_background();
+
srv_main_thread_op_info = (char*)"purging";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
@@ -3005,6 +3081,7 @@ background_loop:
}
mutex_exit(&kernel_mutex);
+flush_loop:
srv_main_thread_op_info = (char*)"flushing buffer pool pages";
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
@@ -3017,13 +3094,22 @@ background_loop:
}
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = (char*) "waiting for buffer pool flush to end";
+ srv_main_thread_op_info =
+ (char*) "waiting for buffer pool flush to end";
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
srv_main_thread_op_info = (char*)"making checkpoint";
log_checkpoint(TRUE, FALSE);
+ if (buf_get_modified_ratio_pct() > srv_max_buf_pool_modified_pct) {
+
+ /* Try to keep the number of modified pages in the
+ buffer pool under the limit wished by the user */
+
+ goto flush_loop;
+ }
+
srv_main_thread_op_info = (char*)"reserving kernel mutex";
mutex_enter(&kernel_mutex);
@@ -3038,15 +3124,24 @@ background_loop:
log_archive_do(FALSE, &n_bytes_archived);
+ /* Keep looping in the background loop if still work to do */
+
if (srv_fast_shutdown && srv_shutdown_state > 0) {
if (n_tables_to_drop + n_pages_flushed
+ n_bytes_archived != 0) {
+ /* If we are doing a fast shutdown (= the default)
+ we do not do purge or insert buffer merge. But we
+ flush the buffer pool completely to disk. */
+
goto background_loop;
}
} else if (n_tables_to_drop +
- n_pages_purged + n_bytes_merged + n_pages_flushed
+ n_pages_purged + n_bytes_merged + n_pages_flushed
+ n_bytes_archived != 0) {
+ /* In a 'slow' shutdown we run purge and the insert buffer
+ merge to completion */
+
goto background_loop;
}
@@ -3078,6 +3173,9 @@ suspend_thread:
os_event_wait(event);
+ /* When there is user activity, InnoDB will set the event and the main
+ thread goes back to loop: */
+
goto loop;
#ifndef __WIN__
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 33d4a30e227..536aa5b67e4 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -161,13 +161,13 @@ srv_parse_data_file_paths_and_sizes(
}
if (strlen(str) >= ut_strlen(":autoextend")
- && 0 == ut_memcmp(str, ":autoextend",
+ && 0 == ut_memcmp(str, (char*)":autoextend",
ut_strlen(":autoextend"))) {
str += ut_strlen(":autoextend");
if (strlen(str) >= ut_strlen(":max:")
- && 0 == ut_memcmp(str, ":max:",
+ && 0 == ut_memcmp(str, (char*)":max:",
ut_strlen(":max:"))) {
str += ut_strlen(":max:");
@@ -265,7 +265,7 @@ srv_parse_data_file_paths_and_sizes(
(*data_file_sizes)[i] = size;
if (strlen(str) >= ut_strlen(":autoextend")
- && 0 == ut_memcmp(str, ":autoextend",
+ && 0 == ut_memcmp(str, (char*)":autoextend",
ut_strlen(":autoextend"))) {
*is_auto_extending = TRUE;
@@ -273,7 +273,7 @@ srv_parse_data_file_paths_and_sizes(
str += ut_strlen(":autoextend");
if (strlen(str) >= ut_strlen(":max:")
- && 0 == ut_memcmp(str, ":max:",
+ && 0 == ut_memcmp(str, (char*)":max:",
ut_strlen(":max:"))) {
str += ut_strlen(":max:");
@@ -864,6 +864,7 @@ open_or_create_data_files(
return(DB_SUCCESS);
}
+#ifdef notdefined
/*********************************************************************
This thread is used to measure contention of latches. */
static
@@ -935,6 +936,7 @@ test_measure_cont(
return(0);
}
+#endif
/********************************************************************
Starts InnoDB and creates a new database if database files
@@ -1053,20 +1055,24 @@ innobase_start_or_create_for_mysql(void)
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
#ifndef __WIN__
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ (char*)"fdatasync")) {
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ (char*)"O_DSYNC")) {
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
} else if (0 == ut_strcmp(srv_file_flush_method_str,
- "littlesync")) {
+ (char*)"littlesync")) {
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ (char*)"nosync")) {
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
#else
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ (char*)"normal")) {
srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
os_aio_use_native_aio = FALSE;
@@ -1196,7 +1202,14 @@ innobase_start_or_create_for_mysql(void)
&max_flushed_lsn, &max_arch_log_no,
&sum_of_new_sizes);
if (err != DB_SUCCESS) {
- fprintf(stderr, "InnoDB: Could not open data files\n");
+ fprintf(stderr,
+"InnoDB: Could not open or create data files.\n"
+"InnoDB: If you tried to add new data files, and it failed here,\n"
+"InnoDB: you should now edit innodb_data_file_path in my.cnf back\n"
+"InnoDB: to what it was, and remove the new ibdata files InnoDB created\n"
+"InnoDB: in this failed attempt. InnoDB only wrote those files full of\n"
+"InnoDB: zeros, but did not yet use them in any way. But be careful: do not\n"
+"InnoDB: remove old data files which contain your precious data!\n");
return((int) err);
}
@@ -1207,7 +1220,10 @@ innobase_start_or_create_for_mysql(void)
and restore them from the doublewrite buffer if
possible */
- trx_sys_doublewrite_restore_corrupt_pages();
+ if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
+
+ trx_sys_doublewrite_restore_corrupt_pages();
+ }
}
srv_normalize_path_for_win(srv_arch_dir);
@@ -1478,7 +1494,9 @@ innobase_start_or_create_for_mysql(void)
fprintf(stderr,
"InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
srv_force_recovery);
- }
+ }
+
+ fflush(stderr);
return((int) DB_SUCCESS);
}
diff --git a/innobase/sync/Makefile.am b/innobase/sync/Makefile.am
index 7504525bf84..4acd4516e35 100644
--- a/innobase/sync/Makefile.am
+++ b/innobase/sync/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libsync.a
+noinst_LIBRARIES = libsync.a
libsync_a_SOURCES = sync0arr.c sync0ipm.c sync0rw.c sync0sync.c
diff --git a/innobase/thr/Makefile.am b/innobase/thr/Makefile.am
index 5f42138e734..62c39492c07 100644
--- a/innobase/thr/Makefile.am
+++ b/innobase/thr/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libthr.a
+noinst_LIBRARIES = libthr.a
libthr_a_SOURCES = thr0loc.c
diff --git a/innobase/trx/Makefile.am b/innobase/trx/Makefile.am
index 63b2c52da33..9e2b3c398e3 100644
--- a/innobase/trx/Makefile.am
+++ b/innobase/trx/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libtrx.a
+noinst_LIBRARIES = libtrx.a
libtrx_a_SOURCES = trx0purge.c trx0rec.c trx0roll.c trx0rseg.c\
trx0sys.c trx0trx.c trx0undo.c
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 1ae9f00ae1f..b9e4a9fea4b 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -340,7 +340,6 @@ trx_sys_doublewrite_restore_corrupt_pages(void)
/* It is an unwritten doublewrite buffer page:
do nothing */
-
} else {
/* Read in the actual page from the data files */
@@ -357,9 +356,19 @@ trx_sys_doublewrite_restore_corrupt_pages(void)
"InnoDB: Trying to recover it from the doublewrite buffer.\n");
if (buf_page_is_corrupted(page)) {
+ fprintf(stderr,
+ "InnoDB: Dump of the page:\n");
+ buf_page_print(read_buf);
+ fprintf(stderr,
+ "InnoDB: Dump of corresponding page in doublewrite buffer:\n");
+ buf_page_print(page);
+
fprintf(stderr,
"InnoDB: Also the page in the doublewrite buffer is corrupt.\n"
- "InnoDB: Cannot continue operation.\n");
+ "InnoDB: Cannot continue operation.\n"
+ "InnoDB: You can try to recover the database with the my.cnf\n"
+ "InnoDB: option:\n"
+ "InnoDB: set-variable=innodb_force_recovery=6\n");
exit(1);
}
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 5ac49397c90..5753b5b338e 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -89,6 +89,8 @@ trx_create(
trx->check_foreigns = TRUE;
trx->check_unique_secondary = TRUE;
+ trx->flush_log_later = FALSE;
+
trx->dict_operation = FALSE;
trx->mysql_thd = NULL;
@@ -102,8 +104,6 @@ trx_create(
trx->mysql_master_log_file_name = "";
trx->mysql_master_log_pos = 0;
- trx->ignore_duplicates_in_insert = FALSE;
-
mutex_create(&(trx->undo_mutex));
mutex_set_level(&(trx->undo_mutex), SYNC_TRX_UNDO);
@@ -782,13 +782,26 @@ trx_commit_off_kernel(
/*-------------------------------------*/
- /* Most MySQL users run with srv_flush_.. set to FALSE: */
+ /* Most MySQL users run with srv_flush_.. set to 0: */
- if (srv_flush_log_at_trx_commit) {
-
- log_flush_up_to(lsn, LOG_WAIT_ONE_GROUP);
+ if (srv_flush_log_at_trx_commit != 0) {
+ if (srv_unix_file_flush_method != SRV_UNIX_NOSYNC
+ && srv_flush_log_at_trx_commit != 2
+ && !trx->flush_log_later) {
+
+ /* Write the log to the log files AND flush
+ them to disk */
+
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
+ } else {
+ /* Write the log but do not flush it to disk */
+
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
+ }
}
+ trx->commit_lsn = lsn;
+
/*-------------------------------------*/
mutex_enter(&kernel_mutex);
@@ -1470,6 +1483,33 @@ trx_commit_for_mysql(
}
/**************************************************************************
+If required, flushes the log to disk if we called trx_commit_for_mysql()
+with trx->flush_log_later == TRUE. */
+
+ulint
+trx_commit_complete_for_mysql(
+/*==========================*/
+ /* out: 0 or error number */
+ trx_t* trx) /* in: trx handle */
+{
+ ut_a(trx);
+
+ if (srv_flush_log_at_trx_commit == 1
+ && srv_unix_file_flush_method != SRV_UNIX_NOSYNC) {
+
+ trx->op_info = (char *) "flushing log";
+
+ /* Flush the log files to disk */
+
+ log_write_up_to(trx->commit_lsn, LOG_WAIT_ONE_GROUP, TRUE);
+
+ trx->op_info = (char *) "";
+ }
+
+ return(0);
+}
+
+/**************************************************************************
Marks the latest SQL statement ended. */
void
diff --git a/innobase/usr/Makefile.am b/innobase/usr/Makefile.am
index a71d0d41ac0..bdcc832a76e 100644
--- a/innobase/usr/Makefile.am
+++ b/innobase/usr/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libusr.a
+noinst_LIBRARIES = libusr.a
libusr_a_SOURCES = usr0sess.c
diff --git a/innobase/ut/Makefile.am b/innobase/ut/Makefile.am
index de3cf41b767..2fdbb99e0f3 100644
--- a/innobase/ut/Makefile.am
+++ b/innobase/ut/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libut.a
+noinst_LIBRARIES = libut.a
libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c
diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c
index 31a137b5fac..c503cda54b9 100644
--- a/innobase/ut/ut0ut.c
+++ b/innobase/ut/ut0ut.c
@@ -206,7 +206,7 @@ ut_get_year_month_day(
cal_tm_ptr = localtime(&tm);
- *year = (ulint)cal_tm_ptr->tm_year;
+ *year = (ulint)cal_tm_ptr->tm_year + 1900;
*month = (ulint)cal_tm_ptr->tm_mon + 1;
*day = (ulint)cal_tm_ptr->tm_mday;
#endif
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index 5a333c51867..4cae03e3f2d 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -124,12 +124,7 @@ EXPORTS
mysql_autocommit
load_defaults
free_defaults
-
-
-
-
-
-
+ my_path
diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c
index 8cf4e2fbe7e..e6166f6bbe5 100644
--- a/libmysqld/libmysqld.c
+++ b/libmysqld/libmysqld.c
@@ -66,7 +66,7 @@ TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
#define closesocket(A) close(A)
#endif
-void mysql_once_init(void);
+void mysqld_once_init(void);
static void end_server(MYSQL *mysql);
static void append_wild(char *to,char *end,const char *wild);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
@@ -373,7 +373,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
MYSQL * STDCALL
mysql_init(MYSQL *mysql)
{
- mysql_once_init();
+ mysqld_once_init();
if (!mysql)
{
if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
@@ -386,7 +386,7 @@ mysql_init(MYSQL *mysql)
}
-void mysql_once_init()
+void mysqld_once_init()
{
if (!mysql_client_init)
{
diff --git a/man/Makefile.am b/man/Makefile.am
index 7019d2aa865..9f919e77b8f 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -19,7 +19,7 @@
man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \
mysqladmin.1 mysqld.1 mysqld_multi.1 mysqldump.1 mysqlshow.1 \
- perror.1 replace.1 mysqld_safe.1
+ perror.1 replace.1 mysqld_safe.1 mysql_fix_privilege_tables.1
EXTRA_DIST = $(man_MANS)
diff --git a/man/isamchk.1 b/man/isamchk.1
index bfc4ccd9c08..341e968a131 100644
--- a/man/isamchk.1
+++ b/man/isamchk.1
@@ -1,4 +1,4 @@
-.TH isamchk 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH isamchk 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
.BR isamchk
\- Description, check and repair of ISAM tables.
diff --git a/man/isamlog.1 b/man/isamlog.1
index a386f11c010..402c3052ad8 100644
--- a/man/isamlog.1
+++ b/man/isamlog.1
@@ -1,4 +1,4 @@
-.TH isamlog 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH isamlog 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
isamlog - Write info about whats in a nisam log file.
.SH USAGE
diff --git a/man/mysql.1 b/man/mysql.1
index 6664581072f..c0c37716b14 100644
--- a/man/mysql.1
+++ b/man/mysql.1
@@ -1,4 +1,4 @@
-.TH mysql 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH mysql 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysql \- text-based client for mysqld, a SQL-based relational database daemon
.SH SYNOPSIS
diff --git a/man/mysql_fix_privilege_tables.1 b/man/mysql_fix_privilege_tables.1
new file mode 100644
index 00000000000..bf4e0e15dfa
--- /dev/null
+++ b/man/mysql_fix_privilege_tables.1
@@ -0,0 +1,23 @@
+.TH mysql 1 "17 March 2003" "MySQL 4.0" "MySQL database"
+.SH NAME
+mysql_fix_privilege_tables \- Fixes MySQL privilege tables.
+.SH SYNOPSIS
+mysql_fix_privilege_tables [options]
+.SH DESCRIPTION
+This scripts updates the mysql.user, mysql.db, mysql.host and the
+mysql.func tables to MySQL 3.22.14 and above.
+
+This is needed if you want to use the new GRANT functions,
+CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23
+
+If you get 'Access denied' errors, you should run this script again
+and give the MySQL root user password as an argument!
+
+For more information start the program with '--help'.
+.SH "SEE ALSO"
+mysql (1), mysqld (1)
+.SH AUTHOR
+This manpage was written by Christian Hammers <ch@debian.org>.
+
+MySQL is available at http://www.mysql.com/.
+.\" end of man page
diff --git a/man/mysql_zap.1 b/man/mysql_zap.1
index 144fc212372..71931c03db6 100644
--- a/man/mysql_zap.1
+++ b/man/mysql_zap.1
@@ -1,4 +1,4 @@
-.TH zap 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH zap 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
zap - a perl script used to kill processes
.SH USAGE
diff --git a/man/mysqlaccess.1 b/man/mysqlaccess.1
index c1c61d4a8a7..fc7c185e050 100644
--- a/man/mysqlaccess.1
+++ b/man/mysqlaccess.1
@@ -1,4 +1,4 @@
-.TH mysqlaccess 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH mysqlaccess 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
.BR mysqlaccess
\- Create new users to mysql.
diff --git a/man/mysqladmin.1 b/man/mysqladmin.1
index 9d7d73aad21..693e8aa5a72 100644
--- a/man/mysqladmin.1
+++ b/man/mysqladmin.1
@@ -1,4 +1,4 @@
-.TH mysqladmin 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH mysqladmin 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysqladmin [OPTIONS] command command.... \- A utility for performing administrative operations
.SH OPTION SYNOPSIS
diff --git a/man/mysqld.1 b/man/mysqld.1
index 0a6fcccbef2..98247cd9445 100644
--- a/man/mysqld.1
+++ b/man/mysqld.1
@@ -1,4 +1,4 @@
-.TH mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH mysqld 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
.BR mysqld
\- Starts the MySQL server demon
diff --git a/man/mysqld_multi.1 b/man/mysqld_multi.1
index 68b9d1e876f..47418835939 100644
--- a/man/mysqld_multi.1
+++ b/man/mysqld_multi.1
@@ -1,4 +1,4 @@
-.TH mysqld_multi 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH mysqld_multi 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysqld_multi - is meant for managing several mysqld processes running in different UNIX sockets and TCP/IP ports.
.SH USAGE
diff --git a/man/mysqld_safe.1 b/man/mysqld_safe.1
index b8271c848cc..3679346d7db 100644
--- a/man/mysqld_safe.1
+++ b/man/mysqld_safe.1
@@ -1,4 +1,4 @@
-.TH safe_mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH safe_mysqld 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysqld_safe \- start the mysqld daemon on Unix.
.SH SYNOPSIS
diff --git a/man/mysqldump.1 b/man/mysqldump.1
index b4aba2ade13..af50366f24c 100644
--- a/man/mysqldump.1
+++ b/man/mysqldump.1
@@ -1,4 +1,4 @@
-.TH mysqldump 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH mysqldump 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysqldump \- text-based client for dumping or backing up mysql databases , tables and or data.
diff --git a/man/mysqlshow.1 b/man/mysqlshow.1
index b6aceec82e3..39590b54375 100644
--- a/man/mysqlshow.1
+++ b/man/mysqlshow.1
@@ -1,4 +1,4 @@
-.TH mysqlshow 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH mysqlshow 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
.BR mysqlshow
\- Shows the structure of a mysql database (databases,tables and columns)
diff --git a/man/perror.1 b/man/perror.1
index 2c5dd9a295f..b8eec8af318 100644
--- a/man/perror.1
+++ b/man/perror.1
@@ -1,4 +1,4 @@
-.TH perror 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH perror 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
perror \- describes a system or MySQL error code.
.SH SYNOPSIS
diff --git a/man/replace.1 b/man/replace.1
index 7c3b79f605b..46d542d57f4 100644
--- a/man/replace.1
+++ b/man/replace.1
@@ -1,4 +1,4 @@
-.TH replace 1 "19 December 2000" "MySQL 3.23" "MySQL database"
+.TH replace 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
.TP
replace - A utility program that is used by msql2mysql, but that has more general applicability as well. replace changes strings in place in files or on the standard input. Uses a finite state machine to match longer strings first. Can be used to swap strings.
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 6fa71348002..c59d140da85 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -321,10 +321,10 @@ static void _ftb_init_index_search(FT_INFO *ftb)
else /* 3 */
{
if (!is_tree_inited(& ftb->no_dupes))
- {
init_tree(&ftb->no_dupes,0,0,sizeof(my_off_t),
_ftb_no_dupes_cmp, 0, NULL, NULL);
- }
+ else
+ reset_tree(& ftb->no_dupes);
}
}
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 75f2a6c83c4..019222fdf22 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -858,15 +858,19 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
{
if (b_type & BLOCK_LAST)
{
- mi_check_print_error(param,"Record link to short for record at %s",
- llstr(start_recpos,llbuff));
+ mi_check_print_error(param,
+ "Wrong record length %s of %s at %s",
+ llstr(block_info.rec_len-left_length,llbuff),
+ llstr(block_info.rec_len, llbuff2),
+ llstr(start_recpos,llbuff3));
got_error=1;
break;
}
if (info->state->data_file_length < block_info.next_filepos)
{
- mi_check_print_error(param,"Found next-recordlink that points outside datafile at %s",
- llstr(block_info.filepos,llbuff));
+ mi_check_print_error(param,
+ "Found next-recordlink that points outside datafile at %s",
+ llstr(block_info.filepos,llbuff));
got_error=1;
break;
}
@@ -2233,7 +2237,17 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
else
rec_length=share->base.pack_reclength;
sort_info.max_records=
- ((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records :
+ /* +1 below is required hack for parallel repair mode.
+ The info->state->records value, that is compared later
+ to sort_info.max_records and cannot exceed it, is
+ increased in sort_key_write. In mi_repair_by_sort, sort_key_write
+ is called after sort_key_read, where the comparison is performed,
+ but in parallel mode master thread can call sort_key_write
+ before some other repair thread calls sort_key_read.
+ Furthermore I'm not even sure +1 would be enough.
+ May be sort_info.max_records shold be always set to max value in
+ parallel mode. */
+ ((param->testflag & T_CREATE_MISSING_KEYS) ? info->state->records + 1:
(ha_rows) (sort_info.filelength/rec_length+1));
del=info->state->del;
@@ -3681,12 +3695,14 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
}
if (update & UPDATE_STAT)
{
- uint key_parts= mi_uint2korr(share->state.header.key_parts);
+ uint i, key_parts= mi_uint2korr(share->state.header.key_parts);
share->state.rec_per_key_rows=info->state->records;
- memcpy((char*) share->state.rec_per_key_part,
- (char*) param->rec_per_key_part,
- sizeof(*param->rec_per_key_part)*key_parts);
share->state.changed&= ~STATE_NOT_ANALYZED;
+ for (i=0; i<key_parts; i++)
+ {
+ if (!(share->state.rec_per_key_part[i]=param->rec_per_key_part[i]))
+ share->state.changed|= STATE_NOT_ANALYZED;
+ }
}
if (update & (UPDATE_STAT | UPDATE_SORT | UPDATE_TIME | UPDATE_AUTO_INC))
{
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index dc51269ac35..faf86c3ffbd 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -485,7 +485,7 @@ int _mi_write_part_record(MI_INFO *info,
{
info->update&= ~HA_STATE_EXTEND_BLOCK;
if (my_block_write(&info->rec_cache,(byte*) *record-head_length,
- length+extra_length+del_length,filepos))
+ length+extra_length+del_length,filepos))
goto err;
}
else if (my_b_write(&info->rec_cache,(byte*) *record-head_length,
@@ -1412,10 +1412,7 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos)
VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
if (my_read(file,(char*) header,sizeof(info->header),MYF(0)) !=
sizeof(info->header))
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- return BLOCK_FATAL_ERROR;
- }
+ goto err;
}
DBUG_DUMP("header",(byte*) header,MI_BLOCK_INFO_HEADER_LENGTH);
if (info->second_read)
@@ -1435,10 +1432,7 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos)
if ((info->block_len=(uint) mi_uint3korr(header+1)) <
MI_MIN_BLOCK_LENGTH ||
(info->block_len & (MI_DYN_ALIGN_SIZE -1)))
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- return BLOCK_ERROR;
- }
+ goto err;
info->filepos=filepos;
info->next_filepos=mi_sizekorr(header+4);
info->prev_filepos=mi_sizekorr(header+12);
@@ -1449,7 +1443,7 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos)
(mi_uint4korr(header+12) != 0 &&
(mi_uint4korr(header+12) != (ulong) ~0 ||
info->prev_filepos != (ulong) ~0)))
- return BLOCK_FATAL_ERROR;
+ goto err;
#endif
return return_val | BLOCK_DELETED; /* Deleted block */
@@ -1529,8 +1523,9 @@ uint _mi_get_block_info(MI_BLOCK_INFO *info, File file, my_off_t filepos)
info->second_read=1;
info->filepos=filepos+12;
return return_val;
- default:
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */
- return BLOCK_ERROR;
}
+
+err:
+ my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */
+ return BLOCK_ERROR;
}
diff --git a/myisam/mi_info.c b/myisam/mi_info.c
index 0be3cc44d80..32767e73bb1 100644
--- a/myisam/mi_info.c
+++ b/myisam/mi_info.c
@@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Ger tillbaka en struct med information om isam-filen */
+/* Return useful base information for an open table */
#include "myisamdef.h"
#ifdef __WIN__
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 00a64bca269..37708a399b0 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -145,11 +145,26 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
} /* _mi_make_key */
- /* Pack a key to intern format from given format (c_rkey) */
- /* returns length of packed key */
+/*
+ Pack a key to intern format from given format (c_rkey)
+
+ SYNOPSIS
+ _mi_pack_key()
+ info MyISAM handler
+ uint keynr key number
+ key Store packed key here
+ old Not packed key
+ k_length Length of 'old' to use
+ last_used_keyseg out parameter. May be NULL
+
+ RETURN
+ length of packed key
+
+ last_use_keyseg Store pointer to the keyseg after the last used one
+*/
uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
- uint k_length)
+ uint k_length, MI_KEYSEG **last_used_keyseg)
{
uint length;
uchar *pos,*end,*start_key=key;
@@ -220,6 +235,8 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
key+= length;
k_length-=length;
}
+ if (last_used_keyseg)
+ *last_used_keyseg= keyseg;
#ifdef NOT_USED
if (keyseg->type)
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index a1ce135f02f..6da1a0395c0 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -116,8 +116,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
errpos=1;
if (my_read(kfile,(char*) share->state.header.file_version,head_length,
MYF(MY_NABP)))
+ {
+ my_errno= HA_ERR_NOT_A_TABLE;
goto err;
-
+ }
if (memcmp((byte*) share->state.header.file_version,
(byte*) myisam_file_magic, 4))
{
@@ -166,7 +168,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
}
errpos=3;
if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
+ {
+ my_errno=HA_ERR_CRASHED;
goto err;
+ }
len=mi_uint2korr(share->state.header.state_info_length);
keys= (uint) share->state.header.keys;
uniques= (uint) share->state.header.uniques;
@@ -181,6 +186,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
}
share->state_diff_length=len-MI_STATE_INFO_SIZE;
+ if (share->state.header.fulltext_keys)
+ {
+ /* Not supported in this version */
+ my_errno= HA_ERR_UNSUPPORTED;
+ goto err;
+ }
mi_state_info_read(disk_cache, &share->state);
len= mi_uint2korr(share->state.header.base_info_length);
if (len != MI_BASE_INFO_SIZE)
diff --git a/myisam/mi_range.c b/myisam/mi_range.c
index 4b98b48199a..d5a786438cd 100644
--- a/myisam/mi_range.c
+++ b/myisam/mi_range.c
@@ -103,7 +103,8 @@ static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len,
if (key_len == 0)
key_len=USE_WHOLE_KEY;
key_buff=info->lastkey+info->s->base.max_key_length;
- key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len);
+ key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len,
+ (MI_KEYSEG**) 0);
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,
(uchar*) key_buff,key_len););
nextflag=myisam_read_vec[search_flag];
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index 4a3c76809e8..a702f78b926 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -23,10 +23,12 @@
/* Ordinary search_flag is 0 ; Give error if no record with key */
int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
- enum ha_rkey_function search_flag)
+ enum ha_rkey_function search_flag)
{
uchar *key_buff;
MYISAM_SHARE *share=info->s;
+ MI_KEYDEF *keyinfo;
+ MI_KEYSEG *last_used_keyseg;
uint pack_key_length, use_key_length, nextflag;
DBUG_ENTER("mi_rkey");
DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d",
@@ -36,25 +38,29 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
DBUG_RETURN(my_errno);
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- info->last_key_func=search_flag;
+ info->last_key_func= search_flag;
+ keyinfo= share->keyinfo + inx;
if (info->once_flags & USE_PACKED_KEYS)
{
- /* key is already packed! */
+ info->once_flags&= ~USE_PACKED_KEYS; /* Reset flag */
+ /*
+ key is already packed!; This happens when we are using a MERGE TABLE
+ */
key_buff=info->lastkey+info->s->base.max_key_length;
- info->last_rkey_length=pack_key_length=key_len;
+ pack_key_length= key_len;
bmove(key_buff,key,key_len);
- info->once_flags&= ~USE_PACKED_KEYS;
+ last_used_keyseg= 0;
}
else
{
if (key_len == 0)
key_len=USE_WHOLE_KEY;
key_buff=info->lastkey+info->s->base.max_key_length;
- pack_key_length=_mi_pack_key(info,(uint) inx,key_buff,(uchar*) key,key_len);
- info->last_rkey_length=pack_key_length;
- DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,share->keyinfo[inx].seg,
- key_buff,pack_key_length););
+ pack_key_length=_mi_pack_key(info,(uint) inx, key_buff, (uchar*) key,
+ key_len, &last_used_keyseg);
+ DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg,
+ key_buff, pack_key_length););
}
if (fast_mi_readinfo(info))
@@ -67,9 +73,9 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
use_key_length=USE_WHOLE_KEY;
- switch(info->s->keyinfo[inx].key_alg){
+ switch (info->s->keyinfo[inx].key_alg) {
case HA_KEY_ALG_RTREE:
- if(rtree_find_first(info,inx,key_buff,use_key_length,nextflag)<0)
+ if (rtree_find_first(info,inx,key_buff,use_key_length,nextflag) < 0)
{
my_errno=HA_ERR_CRASHED;
goto err;
@@ -77,8 +83,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
break;
case HA_KEY_ALG_BTREE:
default:
- if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length,
- myisam_read_vec[search_flag],info->s->state.key_root[inx]))
+ if (!_mi_search(info, keyinfo, key_buff, use_key_length,
+ myisam_read_vec[search_flag], info->s->state.key_root[inx]))
{
while (info->lastpos >= info->state->data_file_length)
{
@@ -88,7 +94,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
exact key, because the keys are sorted according to position
*/
- if (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey,
+ if (_mi_search_next(info, keyinfo, info->lastkey,
info->lastkey_length,
myisam_readnext_vec[search_flag],
info->s->state.key_root[inx]))
@@ -99,8 +105,17 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
if (share->concurrent_insert)
rw_unlock(&share->key_root_lock[inx]);
+ /* Calculate length of the found key; Used by mi_rnext_same */
+ if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg &&
+ info->lastpos != HA_OFFSET_ERROR)
+ info->last_rkey_length= _mi_keylength_part(keyinfo, info->lastkey,
+ last_used_keyseg);
+ else
+ info->last_rkey_length= pack_key_length;
+
+ /* Check if we don't want to have record back, only error message */
if (!buf)
- DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0);
+ DBUG_RETURN(info->lastpos == HA_OFFSET_ERROR ? my_errno : 0);
if (!(*info->read_record)(info,info->lastpos,buf))
{
@@ -110,8 +125,9 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
info->lastpos = HA_OFFSET_ERROR; /* Didn't find key */
- /* Store key for read next */
+ /* Store last used key as a base for read next */
memcpy(info->lastkey,key_buff,pack_key_length);
+ info->last_rkey_length= pack_key_length;
bzero((char*) info->lastkey+pack_key_length,info->s->base.rec_reflength);
info->lastkey_length=pack_key_length+info->s->base.rec_reflength;
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index 04803d7a901..340d8ec2db6 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -1033,6 +1033,37 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
} /* _mi_keylength */
+/*
+ Calculate length of part key.
+
+ Used in mi_rkey() to find the key found for the key-part that was used.
+ This is needed in case of multi-byte character sets where we may search
+ after '0xDF' but find 'ss'
+*/
+
+uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
+ MI_KEYSEG *end)
+{
+ reg1 MI_KEYSEG *keyseg;
+ uchar *start= key;
+
+ for (keyseg=keyinfo->seg ; keyseg != end ; keyseg++)
+ {
+ if (keyseg->flag & HA_NULL_PART)
+ if (!*key++)
+ continue;
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
+ {
+ uint length;
+ get_key_length(length,key);
+ key+=length;
+ }
+ else
+ key+= keyseg->length;
+ }
+ return (uint) (key-start);
+}
+
/* Move a key */
uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from)
diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c
index 8c7713c4b4d..75adf74294f 100644
--- a/myisam/mi_test2.c
+++ b/myisam/mi_test2.c
@@ -645,14 +645,14 @@ int main(int argc, char *argv[])
if ((long) range_records < (long) records*7/10-2 ||
(long) range_records > (long) records*14/10+2)
{
- printf("mi_records_range for key: %d returned %ld; Should be about %ld\n",
- i, (long) range_records, (long) records);
+ printf("mi_records_range for key: %d returned %lu; Should be about %lu\n",
+ i, (ulong) range_records, (ulong) records);
goto end;
}
if (verbose && records)
{
- printf("mi_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
- (long) range_records, (long) records,
+ printf("mi_records_range returned %lu; Exact is %lu (diff: %4.2g %%)\n",
+ (ulong) range_records, (ulong) records,
labs((long) range_records-(long) records)*100.0/records);
}
@@ -666,8 +666,8 @@ int main(int argc, char *argv[])
|| info.keys != keys)
{
puts("Wrong info from mi_info");
- printf("Got: records: %ld delete: %ld i_keys: %d\n",
- (long) info.records, (long) info.deleted,info.keys);
+ printf("Got: records: %lu delete: %lu i_keys: %d\n",
+ (ulong) info.records, (ulong) info.deleted, info.keys);
}
if (verbose)
{
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 104b344a9e2..834ad818972 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -44,6 +44,8 @@ static const char *load_default_groups[]= { "myisamchk", 0 };
static const char *set_charset_name, *opt_tmpdir;
static CHARSET_INFO *set_charset;
static long opt_myisam_block_size;
+static const char *my_progname_short;
+static int stopwords_inited= 0;
static MY_TMPDIR myisamchk_tmpdir;
static const char *type_names[]=
@@ -86,6 +88,7 @@ int main(int argc, char **argv)
{
int error;
MY_INIT(argv[0]);
+ my_progname_short= my_progname+dirname_length(my_progname);
#ifdef __EMX__
_wildcard (&argc, &argv);
@@ -332,7 +335,7 @@ static void usage(void)
puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
puts("Description, check and repair of MyISAM tables.");
puts("Used without options all tables on the command will be checked for errors");
- printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname);
+ printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname_short);
puts("\nGlobal options:\n\
-#, --debug=... Output debug log. Often this is 'd:t:o,filename'\n\
-?, --help Display this help and exit.\n\
@@ -689,7 +692,7 @@ static void get_options(register int *argc,register char ***argv)
{
VOID(fprintf(stderr,
"%s: --unpack can't be used with --quick or --sort-records\n",
- my_progname));
+ my_progname_short));
exit(1);
}
if ((check_param.testflag & T_READONLY) &&
@@ -699,7 +702,7 @@ static void get_options(register int *argc,register char ***argv)
{
VOID(fprintf(stderr,
"%s: Can't use --readonly when repairing or sorting\n",
- my_progname));
+ my_progname_short));
exit(1);
}
@@ -874,7 +877,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
}
else
{
- if (share->state.header.fulltext_keys)
+ if (share->state.header.fulltext_keys && !stopwords_inited++)
ft_init_stopwords();
if (!(param->testflag & T_READONLY))
@@ -1674,13 +1677,13 @@ void mi_check_print_warning(MI_CHECK *param, const char *fmt,...)
if (!param->warning_printed && !param->error_printed)
{
if (param->testflag & T_SILENT)
- fprintf(stderr,"%s: MyISAM file %s\n",my_progname,
+ fprintf(stderr,"%s: MyISAM file %s\n",my_progname_short,
param->isam_file_name);
param->out_flag|= O_DATA_LOST;
}
param->warning_printed=1;
va_start(args,fmt);
- fprintf(stderr,"%s: warning: ",my_progname);
+ fprintf(stderr,"%s: warning: ",my_progname_short);
VOID(vfprintf(stderr, fmt, args));
VOID(fputc('\n',stderr));
fflush(stderr);
@@ -1700,12 +1703,12 @@ void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
if (!param->warning_printed && !param->error_printed)
{
if (param->testflag & T_SILENT)
- fprintf(stderr,"%s: MyISAM file %s\n",my_progname,param->isam_file_name);
+ fprintf(stderr,"%s: MyISAM file %s\n",my_progname_short,param->isam_file_name);
param->out_flag|= O_DATA_LOST;
}
param->error_printed|=1;
va_start(args,fmt);
- fprintf(stderr,"%s: error: ",my_progname);
+ fprintf(stderr,"%s: error: ",my_progname_short);
VOID(vfprintf(stderr, fmt, args));
VOID(fputc('\n',stderr));
fflush(stderr);
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 50320f1ecbd..0d9d7d43438 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -537,6 +537,8 @@ extern uchar *_mi_get_last_key(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *keypos,
extern uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
uchar *key, uchar *keypos, uint *return_key_length);
extern uint _mi_keylength(MI_KEYDEF *keyinfo,uchar *key);
+extern uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
+ MI_KEYSEG *end);
extern uchar *_mi_move_key(MI_KEYDEF *keyinfo,uchar *to,uchar *from);
extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key,
uint key_length,uint nextflag,my_off_t pos);
@@ -551,7 +553,7 @@ extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo);
extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key,
const byte *record,my_off_t filepos);
extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old,
- uint key_length);
+ uint key_length, MI_KEYSEG **last_used_keyseg);
extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf);
extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos,
uint length,int re_read_if_possibly);
diff --git a/myisam/sort.c b/myisam/sort.c
index 09e487e1165..a41713f750f 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -185,8 +185,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
if (maxbuffer == 0)
{
if (!no_messages)
- printf(" - Dumping %lu keys\n",records);
- if (write_index(info,sort_keys,(uint) records))
+ printf(" - Dumping %lu keys\n", (ulong) records);
+ if (write_index(info,sort_keys, (uint) records))
goto err; /* purecov: inspected */
}
else
@@ -195,7 +195,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages,
if (maxbuffer >= MERGEBUFF2)
{
if (!no_messages)
- printf(" - Merging %lu keys\n",records); /* purecov: tested */
+ printf(" - Merging %lu keys\n", (ulong) records); /* purecov: tested */
if (merge_many_buff(info,keys,sort_keys,
dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile))
goto err; /* purecov: inspected */
@@ -308,6 +308,8 @@ pthread_handler_decl(thr_find_all_keys,arg)
uint idx, maxbuffer;
uchar **sort_keys=0;
+ LINT_INIT(keys);
+
error=1;
if (my_thread_init())
diff --git a/myisammrg/myrg_extra.c b/myisammrg/myrg_extra.c
index d375b45df99..62cf5f01aba 100644
--- a/myisammrg/myrg_extra.c
+++ b/myisammrg/myrg_extra.c
@@ -33,7 +33,7 @@ int myrg_extra(MYRG_INFO *info,enum ha_extra_function function,
if (function == HA_EXTRA_CACHE)
{
info->cache_in_use=1;
- info->cache_size= (extra_arg ? *(long*) extra_arg :
+ info->cache_size= (extra_arg ? *(ulong*) extra_arg :
my_default_record_cache_size);
}
else
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index a3343b8e019..81e3f866709 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -110,11 +110,11 @@ GREP=grep
if test $? != 0; then exit 1; fi
PRINTF=printf
RM=rm
-TIME=`which time`
if test $? != 0; then exit 1; fi
TR=tr
XARGS=`which xargs`
if test $? != 0; then exit 1; fi
+SORT=sort
# Are we using a source or a binary distribution?
@@ -413,7 +413,7 @@ fi
if test ${COLUMNS:-0} -lt 80 ; then COLUMNS=80 ; fi
E=`$EXPR $COLUMNS - 8`
-DASH72=`$ECHO '------------------------------------------------------------------------'|$CUT -c 1-$E`
+DASH72=`$ECHO '------------------------------------------'|$CUT -c 1-$E`
# on source dist, we pick up freshly build executables
# on binary, use what is installed
@@ -592,9 +592,8 @@ skip_test() {
USERT=" ...."
SYST=" ...."
REALT=" ...."
- timestr="$USERT $SYST $REALT"
pname=`$ECHO "$1 "|$CUT -c 1-24`
- RES="$pname $timestr"
+ RES="$pname"
skip_inc
$ECHO "$RES$RES_SPACE [ skipped ]"
}
@@ -1221,31 +1220,15 @@ run_testcase ()
$RM -f r/$tname.*reject
mysql_test_args="-R r/$tname.result $EXTRA_MYSQL_TEST_OPT"
if [ -z "$DO_CLIENT_GDB" ] ; then
- mytime=`$TIME -p $MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`
+ `$MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`;
else
do_gdb_test "$mysql_test_args" "$tf"
fi
res=$?
- if [ $res = 0 ]; then
- mytime=`$CAT $TIMEFILE | $TAIL -3 | $TR '\n' ':'`
-
- USERT=`$ECHO $mytime | $CUT -d : -f 2 | $CUT -d ' ' -f 2`
- USERT=`prefix_to_8 $USERT`
- SYST=`$ECHO $mytime | $CUT -d : -f 3 | $CUT -d ' ' -f 2`
- SYST=`prefix_to_8 $SYST`
- REALT=`$ECHO $mytime | $CUT -d : -f 1 | $CUT -d ' ' -f 2`
- REALT=`prefix_to_8 $REALT`
- else
- USERT=" ...."
- SYST=" ...."
- REALT=" ...."
- fi
-
- timestr="$USERT $SYST $REALT"
pname=`$ECHO "$tname "|$CUT -c 1-24`
- RES="$pname $timestr"
+ RES="$pname"
if [ x$many_slaves = x1 ] ; then
stop_slave 1
@@ -1380,7 +1363,7 @@ then
fi
$ECHO
-$ECHO " TEST USER SYSTEM ELAPSED RESULT"
+$ECHO " TEST RESULT"
$ECHO $DASH72
if [ -z "$1" ] ;
@@ -1389,7 +1372,7 @@ then
$ECHO "Will not run in record mode without a specific test case."
else
if [ x$TEST_REPLICATION = x1 ]; then
- for tf in $TESTDIR/rpl*.$TESTSUFFIX
+ for tf in `ls -1 $TESTDIR/*.$TESTSUFFIX | $SORT`
do
run_testcase $tf
done
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index aadb35c32e8..1fe874a211c 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -92,6 +92,25 @@ key (n2, n3, n4, n1),
key (n3, n4, n1, n2),
key (n4, n1, n2, n3) );
alter table t1 disable keys;
+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 n1 1 n1 A 0 NULL NULL BTREE
+t1 1 n1_2 1 n1 A NULL NULL NULL BTREE disabled
+t1 1 n1_2 2 n2 A NULL NULL NULL YES BTREE disabled
+t1 1 n1_2 3 n3 A NULL NULL NULL YES BTREE disabled
+t1 1 n1_2 4 n4 A NULL NULL NULL YES BTREE disabled
+t1 1 n2 1 n2 A NULL NULL NULL YES BTREE disabled
+t1 1 n2 2 n3 A NULL NULL NULL YES BTREE disabled
+t1 1 n2 3 n4 A NULL NULL NULL YES BTREE disabled
+t1 1 n2 4 n1 A NULL NULL NULL BTREE disabled
+t1 1 n3 1 n3 A NULL NULL NULL YES BTREE disabled
+t1 1 n3 2 n4 A NULL NULL NULL YES BTREE disabled
+t1 1 n3 3 n1 A NULL NULL NULL BTREE disabled
+t1 1 n3 4 n2 A NULL NULL NULL YES BTREE disabled
+t1 1 n4 1 n4 A NULL NULL NULL YES BTREE disabled
+t1 1 n4 2 n1 A NULL NULL NULL BTREE disabled
+t1 1 n4 3 n2 A NULL NULL NULL YES BTREE disabled
+t1 1 n4 4 n3 A NULL NULL NULL YES BTREE disabled
insert into t1 values(10,RAND()*1000,RAND()*1000,RAND());
insert into t1 values(9,RAND()*1000,RAND()*1000,RAND());
insert into t1 values(8,RAND()*1000,RAND()*1000,RAND());
@@ -103,6 +122,25 @@ insert into t1 values(3,RAND()*1000,RAND()*1000,RAND());
insert into t1 values(2,RAND()*1000,RAND()*1000,RAND());
insert into t1 values(1,RAND()*1000,RAND()*1000,RAND());
alter table t1 enable keys;
+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 n1 1 n1 A 10 NULL NULL BTREE
+t1 1 n1_2 1 n1 A 10 NULL NULL BTREE
+t1 1 n1_2 2 n2 A 10 NULL NULL YES BTREE
+t1 1 n1_2 3 n3 A 10 NULL NULL YES BTREE
+t1 1 n1_2 4 n4 A 10 NULL NULL YES BTREE
+t1 1 n2 1 n2 A 10 NULL NULL YES BTREE
+t1 1 n2 2 n3 A 10 NULL NULL YES BTREE
+t1 1 n2 3 n4 A 10 NULL NULL YES BTREE
+t1 1 n2 4 n1 A 10 NULL NULL BTREE
+t1 1 n3 1 n3 A 10 NULL NULL YES BTREE
+t1 1 n3 2 n4 A 10 NULL NULL YES BTREE
+t1 1 n3 3 n1 A 10 NULL NULL BTREE
+t1 1 n3 4 n2 A 10 NULL NULL YES BTREE
+t1 1 n4 1 n4 A 10 NULL NULL YES BTREE
+t1 1 n4 2 n1 A 10 NULL NULL BTREE
+t1 1 n4 3 n2 A 10 NULL NULL YES BTREE
+t1 1 n4 4 n3 A 10 NULL NULL YES BTREE
drop table t1;
create table t1 (i int unsigned not null auto_increment primary key);
insert into t1 values (null),(null),(null),(null);
@@ -120,5 +158,121 @@ alter table t2 rename t1, add c char(10) comment "no comment";
show columns from t1;
Field Type Collation Null Key Default Extra
i int(10) unsigned binary PRI NULL auto_increment
-c char(10) latin1_swedish_ci YES NULL
+c char(10) latin1_swedish_ci YES NULL
+drop table t1;
+create table t1 (a int, b int);
+insert into t1 values(1,100), (2,100), (3, 100);
+insert into t1 values(1,99), (2,99), (3, 99);
+insert into t1 values(1,98), (2,98), (3, 98);
+insert into t1 values(1,97), (2,97), (3, 97);
+insert into t1 values(1,96), (2,96), (3, 96);
+insert into t1 values(1,95), (2,95), (3, 95);
+insert into t1 values(1,94), (2,94), (3, 94);
+insert into t1 values(1,93), (2,93), (3, 93);
+insert into t1 values(1,92), (2,92), (3, 92);
+insert into t1 values(1,91), (2,91), (3, 91);
+insert into t1 values(1,90), (2,90), (3, 90);
+insert into t1 values(1,89), (2,89), (3, 89);
+insert into t1 values(1,88), (2,88), (3, 88);
+insert into t1 values(1,87), (2,87), (3, 87);
+insert into t1 values(1,86), (2,86), (3, 86);
+insert into t1 values(1,85), (2,85), (3, 85);
+insert into t1 values(1,84), (2,84), (3, 84);
+insert into t1 values(1,83), (2,83), (3, 83);
+insert into t1 values(1,82), (2,82), (3, 82);
+insert into t1 values(1,81), (2,81), (3, 81);
+insert into t1 values(1,80), (2,80), (3, 80);
+insert into t1 values(1,79), (2,79), (3, 79);
+insert into t1 values(1,78), (2,78), (3, 78);
+insert into t1 values(1,77), (2,77), (3, 77);
+insert into t1 values(1,76), (2,76), (3, 76);
+insert into t1 values(1,75), (2,75), (3, 75);
+insert into t1 values(1,74), (2,74), (3, 74);
+insert into t1 values(1,73), (2,73), (3, 73);
+insert into t1 values(1,72), (2,72), (3, 72);
+insert into t1 values(1,71), (2,71), (3, 71);
+insert into t1 values(1,70), (2,70), (3, 70);
+insert into t1 values(1,69), (2,69), (3, 69);
+insert into t1 values(1,68), (2,68), (3, 68);
+insert into t1 values(1,67), (2,67), (3, 67);
+insert into t1 values(1,66), (2,66), (3, 66);
+insert into t1 values(1,65), (2,65), (3, 65);
+insert into t1 values(1,64), (2,64), (3, 64);
+insert into t1 values(1,63), (2,63), (3, 63);
+insert into t1 values(1,62), (2,62), (3, 62);
+insert into t1 values(1,61), (2,61), (3, 61);
+insert into t1 values(1,60), (2,60), (3, 60);
+insert into t1 values(1,59), (2,59), (3, 59);
+insert into t1 values(1,58), (2,58), (3, 58);
+insert into t1 values(1,57), (2,57), (3, 57);
+insert into t1 values(1,56), (2,56), (3, 56);
+insert into t1 values(1,55), (2,55), (3, 55);
+insert into t1 values(1,54), (2,54), (3, 54);
+insert into t1 values(1,53), (2,53), (3, 53);
+insert into t1 values(1,52), (2,52), (3, 52);
+insert into t1 values(1,51), (2,51), (3, 51);
+insert into t1 values(1,50), (2,50), (3, 50);
+insert into t1 values(1,49), (2,49), (3, 49);
+insert into t1 values(1,48), (2,48), (3, 48);
+insert into t1 values(1,47), (2,47), (3, 47);
+insert into t1 values(1,46), (2,46), (3, 46);
+insert into t1 values(1,45), (2,45), (3, 45);
+insert into t1 values(1,44), (2,44), (3, 44);
+insert into t1 values(1,43), (2,43), (3, 43);
+insert into t1 values(1,42), (2,42), (3, 42);
+insert into t1 values(1,41), (2,41), (3, 41);
+insert into t1 values(1,40), (2,40), (3, 40);
+insert into t1 values(1,39), (2,39), (3, 39);
+insert into t1 values(1,38), (2,38), (3, 38);
+insert into t1 values(1,37), (2,37), (3, 37);
+insert into t1 values(1,36), (2,36), (3, 36);
+insert into t1 values(1,35), (2,35), (3, 35);
+insert into t1 values(1,34), (2,34), (3, 34);
+insert into t1 values(1,33), (2,33), (3, 33);
+insert into t1 values(1,32), (2,32), (3, 32);
+insert into t1 values(1,31), (2,31), (3, 31);
+insert into t1 values(1,30), (2,30), (3, 30);
+insert into t1 values(1,29), (2,29), (3, 29);
+insert into t1 values(1,28), (2,28), (3, 28);
+insert into t1 values(1,27), (2,27), (3, 27);
+insert into t1 values(1,26), (2,26), (3, 26);
+insert into t1 values(1,25), (2,25), (3, 25);
+insert into t1 values(1,24), (2,24), (3, 24);
+insert into t1 values(1,23), (2,23), (3, 23);
+insert into t1 values(1,22), (2,22), (3, 22);
+insert into t1 values(1,21), (2,21), (3, 21);
+insert into t1 values(1,20), (2,20), (3, 20);
+insert into t1 values(1,19), (2,19), (3, 19);
+insert into t1 values(1,18), (2,18), (3, 18);
+insert into t1 values(1,17), (2,17), (3, 17);
+insert into t1 values(1,16), (2,16), (3, 16);
+insert into t1 values(1,15), (2,15), (3, 15);
+insert into t1 values(1,14), (2,14), (3, 14);
+insert into t1 values(1,13), (2,13), (3, 13);
+insert into t1 values(1,12), (2,12), (3, 12);
+insert into t1 values(1,11), (2,11), (3, 11);
+insert into t1 values(1,10), (2,10), (3, 10);
+insert into t1 values(1,9), (2,9), (3, 9);
+insert into t1 values(1,8), (2,8), (3, 8);
+insert into t1 values(1,7), (2,7), (3, 7);
+insert into t1 values(1,6), (2,6), (3, 6);
+insert into t1 values(1,5), (2,5), (3, 5);
+insert into t1 values(1,4), (2,4), (3, 4);
+insert into t1 values(1,3), (2,3), (3, 3);
+insert into t1 values(1,2), (2,2), (3, 2);
+insert into t1 values(1,1), (2,1), (3, 1);
+alter table t1 add unique (a,b), add key (b);
+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 a 1 a A NULL NULL NULL YES BTREE
+t1 0 a 2 b A NULL NULL NULL YES BTREE
+t1 1 b 1 b A 100 NULL NULL YES BTREE
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+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 a 1 a A 3 NULL NULL YES BTREE
+t1 0 a 2 b A 300 NULL NULL YES BTREE
+t1 1 b 1 b A 100 NULL NULL YES BTREE
drop table t1;
diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result
new file mode 100644
index 00000000000..f9f96310b73
--- /dev/null
+++ b/mysql-test/r/ansi.result
@@ -0,0 +1,10 @@
+drop table if exists t1;
+SELECT 'A' || 'B';
+'A' || 'B'
+AB
+CREATE TABLE t1 (id INT, id2 int);
+SELECT id,NULL,1,1.1,'a' FROM t1 GROUP BY id;
+id NULL 1 1.1 a
+SELECT id FROM t1 GROUP BY id2;
+'t1.id' isn't in GROUP BY
+drop table t1;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 76e749ab6e7..520227c0fba 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -27,13 +27,9 @@ The used storage engine can't index column 'b'
create table t1 (a int not null auto_increment,primary key (a)) type=heap;
create table t1 (a int not null,b text) type=heap;
The used table type doesn't support BLOB/TEXT columns
-create table t1 (a int ,primary key(a)) type=heap;
-All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
drop table if exists t1;
create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
Incorrect table definition; There can only be one auto column and it must be defined as a key
-create table t1 (ordid int(8), primary key (ordid));
-All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
create table not_existing_database.test (a int);
Got one of the listed errors
create table `a/a` (a int);
@@ -178,6 +174,38 @@ select * from t1;
if('2002'='2002','Y','N')
Y
drop table if exists t1;
+SET SESSION table_type="heap";
+SELECT @@table_type;
+@@table_type
+HEAP
+CREATE TABLE t1 (a int not null);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0'
+) TYPE=HEAP
+drop table t1;
+SET SESSION table_type="gemini";
+SELECT @@table_type;
+@@table_type
+GEMINI
+CREATE TABLE t1 (a int not null);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0'
+) TYPE=MyISAM
+SET SESSION table_type=default;
+drop table t1;
+create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2));
+insert into t1 values ("a", 1), ("b", 2);
+insert into t1 values ("c", NULL);
+Column 'k2' cannot be null
+insert into t1 values (NULL, 3);
+Column 'k1' cannot be null
+insert into t1 values (NULL, NULL);
+Column 'k1' cannot be null
+drop table t1;
create table t1 (a int, key(a));
create table t2 (b int, foreign key(b) references t1(a), key(b));
drop table if exists t1,t2;
diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result
index b79bc67138c..630fef9b679 100644
--- a/mysql-test/r/ctype_latin1_de.result
+++ b/mysql-test/r/ctype_latin1_de.result
@@ -212,3 +212,55 @@ select * from t1 where match a against ("te*" in boolean mode)+0;
a
test
drop table t1;
+create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
+insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
+update t1 set word2=word;
+select word, word=0xdf as t from t1 having t > 0;
+word t
+ß 1
+select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
+word t
+ss 1
+ß 1
+select * from t1 where word=0xDF;
+word word2
+ß ß
+select * from t1 where word=CAST(0xDF as CHAR);
+word word2
+ss ss
+ß ß
+select * from t1 where word2=0xDF;
+word word2
+ß ß
+select * from t1 where word2=CAST(0xDF as CHAR);
+word word2
+ss ss
+ß ß
+select * from t1 where word='ae';
+word word2
+ä ä
+ae ae
+select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
+word word2
+ä ä
+ae ae
+select * from t1 where word between 0xDF and 0xDF;
+word word2
+ß ß
+select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
+word word2
+ss ss
+ß ß
+select * from t1 where word like 'ae';
+word word2
+ae ae
+select * from t1 where word like 'AE';
+word word2
+ae ae
+select * from t1 where word like 0xDF;
+word word2
+ß ß
+select * from t1 where word like CAST(0xDF as CHAR);
+word word2
+ß ß
+drop table t1;
diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result
new file mode 100644
index 00000000000..223a18f19e9
--- /dev/null
+++ b/mysql-test/r/ctype_ujis.result
@@ -0,0 +1,8 @@
+drop table if exists t1;
+create table t1 (c text);
+insert into t1 values (0xa4a2),(0xa4a3);
+select hex(left(c,1)) from t1 group by c;
+hex(left(c,1))
+A4A2
+A4A3
+drop table t1;
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index ae216f9b380..c87fa8fb927 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -46,4 +46,15 @@ NULL d 7
delete from t1 where misc > 5 and bool is null;
select * from t1 where misc > 5 and bool is null;
bool not_null misc
+select count(*) from t1;
+count(*)
+2
+delete from t1 where 1 > 2;
+select count(*) from t1;
+count(*)
+2
+delete from t1 where 3 > 2;
+select count(*) from t1;
+count(*)
+0
drop table t1;
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index c40e9d9bfa2..d87b00dd4d7 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -216,3 +216,14 @@ test.t1 repair status OK
select * from t1 where match (a) against ('aaaa');
a
drop table t1;
+drop table if exists t1;
+create table t1 ( ref_mag text not null, fulltext (ref_mag));
+insert into t1 values ('test');
+select ref_mag from t1 where match ref_mag against ('+test' in boolean mode);
+ref_mag
+test
+alter table t1 change ref_mag ref_mag char (255) not null;
+select ref_mag from t1 where match ref_mag against ('+test' in boolean mode);
+ref_mag
+test
+drop table t1;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index b7bf3a5cd80..e9fb56a77d6 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -42,6 +42,16 @@ insert into t1 values (null,null,'');
select count(distinct a),count(distinct grp) from t1;
count(distinct a) count(distinct grp)
6 3
+select sum(all a),count(all a),avg(all a),std(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
+sum(all a) count(all a) avg(all a) std(all a) bit_or(all a) bit_and(all a) min(all a) max(all a) min(all c) max(all c)
+21 6 3.5000 1.7078 7 0 1 6 E
+select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
+grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
+NULL NULL 0 NULL NULL 0 0 NULL NULL
+1 1 1 1.0000 0.0000 1 1 1 1 a a
+2 5 2 2.5000 0.5000 3 2 2 3 b c
+3 15 3 5.0000 0.8165 7 4 4 6 C E
+select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
select sum(all a),count(all a),avg(all a),std(all a),variance(all a),bit_or(all a),bit_and(all a),min(all a),max(all a),min(all c),max(all c) from t1;
sum(all a) count(all a) avg(all a) std(all a) variance(all a) bit_or(all a) bit_and(all a) min(all a) max(all a) min(all c) max(all c)
21 6 3.5000 1.7078 2.9167 7 0 1 6 E
@@ -221,6 +231,47 @@ select max(t1.a2),max(t2.a1) from t1 left outer join t2 on t1.a1=10;
max(t1.a2) max(t2.a1)
zzz BBB
drop table t1,t2;
+CREATE TABLE t1 (a int, b int);
+select count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1;
+count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+0 NULL NULL NULL NULL NULL -1 0
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+insert into t1 values (1,null);
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+1 0 NULL NULL NULL NULL NULL -1 0
+insert into t1 values (1,null);
+insert into t1 values (2,null);
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+1 0 NULL NULL NULL NULL NULL 0 0
+2 0 NULL NULL NULL NULL NULL 0 0
+select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+1 0 NULL NULL NULL NULL NULL -1 0
+2 0 NULL NULL NULL NULL NULL -1 0
+insert into t1 values (2,1);
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+1 0 NULL NULL NULL NULL NULL 0 0
+2 1 1 1.0000 0.0000 1 1 0 1
+select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+1 0 NULL NULL NULL NULL NULL -1 0
+2 1 1 1.0000 0.0000 1 1 1 1
+insert into t1 values (3,1);
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+1 0 NULL NULL NULL NULL NULL 0 0
+2 1 1 1.0000 0.0000 1 1 0 1
+3 1 1 1.0000 0.0000 1 1 1 1
+select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+a count(b) sum(b) avg(b) std(b) min(b) max(b) bit_and(b) bit_or(b)
+1 0 NULL NULL NULL NULL NULL -1 0
+2 1 1 1.0000 0.0000 1 1 1 1
+3 1 1 1.0000 0.0000 1 1 1 1
+drop table t1;
create table t1(
a1 char(3) primary key,
a2 smallint,
@@ -561,4 +612,4 @@ select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 3 NULL 14 Using index
1 SIMPLE t2 index NULL k2 4 NULL 6 Using where; Using index
-drop table if exists t1, t2;
+drop table t1, t2;
diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
index 4eed80c4cc9..8d05adcc1ba 100644
--- a/mysql-test/r/func_misc.result
+++ b/mysql-test/r/func_misc.result
@@ -10,3 +10,6 @@ inet_aton("255.255.255.255.255") inet_aton("255.255.1.255") inet_aton("0.1.255")
select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511);
inet_ntoa(1099511627775) inet_ntoa(4294902271) inet_ntoa(511)
NULL 255.255.1.255 0.0.1.255
+select length(format('nan', 2)) > 0;
+length(format('nan', 2)) > 0
+1
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 337d5639056..5a5689f0185 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -29,6 +29,8 @@ PRIMARY KEY (userID)
INSERT INTO t2 VALUES (1,'name','pass','mail','Y','v','n','adr','1','1','1');
INSERT INTO t2 VALUES (2,'name','pass','mail','Y','v','n','adr','1','1','1');
INSERT INTO t2 VALUES (3,'name','pass','mail','Y','v','n','adr','1','1','1');
+INSERT INTO t2 VALUES (4,'name','pass','mail','Y','v','n','adr','1','1','1');
+INSERT INTO t2 VALUES (5,'name','pass','mail','Y','v','n','adr','1','1','1');
SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid;
userid MIN(t1.score)
1 1
@@ -49,8 +51,12 @@ userid MIN(t1.score+0.0)
2 2.0
SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL;
userid MIN(t1.score+0.0)
-1 1.0
2 2.0
+1 1.0
+EXPLAIN SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL;
+table type possible_keys key key_len ref rows Extra
+t1 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+t2 eq_ref PRIMARY PRIMARY 4 t1.userID 1 Using index
drop table t1,t2;
CREATE TABLE t1 (
PID int(10) unsigned NOT NULL auto_increment,
@@ -244,7 +250,7 @@ score smallint(5) unsigned,
key (spid),
key (score)
);
-INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3);
+INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3),(6,3,3),(7,3,3);
explain select userid,count(*) from t1 group by userid desc;
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
@@ -253,16 +259,14 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary
select userid,count(*) from t1 group by userid desc;
userid count(*)
-3 3
+3 5
2 1
1 2
select userid,count(*) from t1 group by userid desc having (count(*)+1) IN (4,3);
userid count(*)
-3 3
1 2
select userid,count(*) from t1 group by userid desc having 3 IN (1,COUNT(*));
userid count(*)
-3 3
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 Using where; Using index
@@ -282,12 +286,14 @@ spid count(*)
1 1
explain select sql_big_result spid,sum(userid) from t1 group by spid desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using filesort
+1 SIMPLE t1 ALL NULL NULL NULL NULL 8 Using filesort
explain select sql_big_result spid,sum(userid) from t1 group by spid desc order by null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 6
+1 SIMPLE t1 ALL NULL NULL NULL NULL 8
select sql_big_result spid,sum(userid) from t1 group by spid desc;
spid sum(userid)
+7 3
+6 3
5 3
4 3
3 3
@@ -295,13 +301,13 @@ spid sum(userid)
1 1
explain select sql_big_result score,count(*) from t1 group by score desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL score 3 NULL 6 Using index
+1 SIMPLE t1 index NULL score 3 NULL 8 Using index
explain select sql_big_result score,count(*) from t1 group by score desc order by null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL score 3 NULL 6 Using index
+1 SIMPLE t1 index NULL score 3 NULL 8 Using index
select sql_big_result score,count(*) from t1 group by score desc;
score count(*)
-3 3
+3 5
2 1
1 2
drop table t1;
@@ -536,15 +542,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL a NULL NULL NULL 4 Using where
drop table t1,t2;
create table t1 (a int, b int);
-insert into t1 values (1, 4);
-insert into t1 values (10, 40);
-insert into t1 values (1, 4);
-insert into t1 values (10, 43);
-insert into t1 values (1, 4);
-insert into t1 values (10, 41);
-insert into t1 values (1, 4);
-insert into t1 values (10, 43);
-insert into t1 values (1, 4);
+insert into t1 values (1, 4),(10, 40),(1, 4),(10, 43),(1, 4),(10, 41),(1, 4),(10, 43),(1, 4);
select a, MAX(b), INTERVAL (MAX(b), 1,3,10,30,39,40,50,60,100,1000) from t1 group by a;
a MAX(b) INTERVAL (MAX(b), 1,3,10,30,39,40,50,60,100,1000)
1 4 2
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index bd1bd523964..fc0b3c652ef 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -67,3 +67,18 @@ Fld1 max(Fld2)
1 20
3 50
drop table t1;
+create table t1 (id int not null, qty int not null);
+insert into t1 values (1,2),(1,3),(2,4),(2,5);
+select id, sum(qty) as sqty from t1 group by id having sqty>2;
+id sqty
+1 5
+2 9
+select sum(qty) as sqty from t1 group by id having count(id) > 0;
+sqty
+5
+9
+select sum(qty) as sqty from t1 group by id having count(distinct id) > 0;
+sqty
+5
+9
+drop table t1;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 51669f563de..922f4816e90 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -138,15 +138,6 @@ id parent_id level
1008 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 # 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 # 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 # Using where
select level,id from t1 where level=1;
level id
1 1002
@@ -208,7 +199,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 storage enginge for the table doesn't support analyze
+test.t1 analyze status OK
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
@@ -595,9 +586,6 @@ id parent_id level
1009 102 2
1025 102 2
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 Using where; Using index
select level,id from t1 where level=1;
level id
1 1004
@@ -1141,7 +1129,7 @@ a b
drop table t1;
CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) type=innodb;
CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) type=innodb;
-INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12);
INSERT INTO t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
update t1,t2 set t1.a=t1.a+100;
select * from t1;
@@ -1155,6 +1143,9 @@ a b
107 7
108 8
109 9
+110 10
+111 11
+112 12
update t1,t2 set t1.a=t1.a+100 where t1.a=101;
select * from t1;
a b
@@ -1167,6 +1158,9 @@ a b
107 7
108 8
109 9
+110 10
+111 11
+112 12
update t1,t2 set t1.b=t1.b+10 where t1.b=2;
select * from t1;
a b
@@ -1178,8 +1172,11 @@ a b
107 7
108 8
109 9
+110 10
+111 11
102 12
-update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5;
+112 12
+update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t1.a=t2.a+100;
select * from t1;
a b
201 1
@@ -1190,19 +1187,105 @@ a b
107 7
108 8
109 9
+110 10
+111 11
102 12
+112 12
select * from t2;
a b
-1 5
-2 5
-3 5
-4 5
-5 5
-6 5
-7 5
-8 5
-9 5
+1 1
+2 2
+6 6
+7 7
+8 8
+9 9
+3 13
+4 14
+5 15
drop table t1,t2;
+CREATE TABLE t2 ( NEXT_T BIGINT NOT NULL PRIMARY KEY) TYPE=MyISAM;
+CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) TYPE=InnoDB;
+SET AUTOCOMMIT=0;
+INSERT INTO t1 ( B_ID ) VALUES ( 1 );
+INSERT INTO t2 ( NEXT_T ) VALUES ( 1 );
+ROLLBACK;
+Warning: Some non-transactional changed tables couldn't be rolled back
+SELECT * FROM t1;
+B_ID
+drop table t1,t2;
+create table t1 ( pk int primary key, parent int not null, child int not null, index (parent) ) type = innodb;
+insert into t1 values (1,0,4), (2,1,3), (3,2,1), (4,1,2);
+select distinct parent,child from t1 order by parent;
+parent child
+0 4
+1 2
+1 3
+2 1
+drop table t1;
+create table t1 (a int not null auto_increment primary key, b int, c int, key(c)) type=innodb;
+create table t2 (a int not null auto_increment primary key, b int);
+insert into t1 (b) values (null),(null),(null),(null),(null),(null),(null);
+insert into t2 (a) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+select count(*) from t1;
+count(*)
+29267
+explain select * from t1 where c between 1 and 10000;
+table type possible_keys key key_len ref rows Extra
+t1 range c c 5 NULL 1 Using where
+update t1 set c=a;
+explain select * from t1 where c between 1 and 10000;
+table type possible_keys key key_len ref rows Extra
+t1 ALL c NULL NULL NULL 29537 Using where
+drop table t1,t2;
+create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) type=innodb;
+insert into t1 (id) values (null),(null),(null),(null),(null);
+update t1 set fk=69 where fk is null order by id limit 1;
+SELECT * from t1;
+id fk
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+1 69
+drop table t1;
+create table t1 (a int not null, b int not null, key (a));
+insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3);
+SET @tmp=0;
+update t1 set b=(@tmp:=@tmp+1) order by a;
+update t1 set b=99 where a=1 order by b asc limit 1;
+update t1 set b=100 where a=1 order by b desc limit 2;
+update t1 set a=a+10+b where a=1 order by b;
+select * from t1 order by a,b;
+a b
+2 4
+2 5
+2 6
+3 7
+3 8
+3 9
+3 10
+3 11
+3 12
+13 2
+111 100
+111 100
CREATE TABLE t1 (col1 int(1))TYPE=InnoDB;
CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP(+0),INDEX stamp_idx
(stamp))TYPE=InnoDB;
diff --git a/mysql-test/r/innodb_handler.result b/mysql-test/r/innodb_handler.result
index 4ce104506f1..38c39e2936f 100644
--- a/mysql-test/r/innodb_handler.result
+++ b/mysql-test/r/innodb_handler.result
@@ -139,4 +139,13 @@ a b
alter table t1 type=innodb;
handler t2 read first;
Unknown table 't2' in HANDLER
-drop table if exists t1;
+drop table t1;
+CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2)) TYPE=InnoDB;
+INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2);
+HANDLER t1 OPEN;
+HANDLER t1 READ `primary` = (1, 1000);
+no1 no2
+HANDLER t1 READ `primary` PREV;
+no1 no2
+1 275
+DROP TABLE t1;
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index 09b819888eb..4bc045aa2f7 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -274,3 +274,101 @@ SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (site
rate_code base_rate
cust 20
drop table t1,t2;
+CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, Value1 VARCHAR(255));
+CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255));
+INSERT INTO t1 VALUES (1, 'A');
+INSERT INTO t2 VALUES (1, 'B');
+SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND (Value1 = 'A' AND Value2 <> 'B');
+ID Value1 ID Value2
+SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND Value1 = 'A' AND Value2 <> 'B';
+ID Value1 ID Value2
+SELECT * FROM t1 NATURAL JOIN t2 WHERE (Value1 = 'A' AND Value2 <> 'B') AND 1;
+ID Value1 ID Value2
+drop table t1,t2;
+create table t1 (i int);
+create table t2 (i int);
+create table t3 (i int);
+insert into t1 values(1),(2);
+insert into t2 values(2),(3);
+insert into t3 values (2),(4);
+select * from t1 natural left join t2;
+i i
+1 NULL
+2 2
+select * from t1 left join t2 on (t1.i=t2.i);
+i i
+1 NULL
+2 2
+select * from t1 natural left join t2 natural left join t3;
+i i i
+1 NULL NULL
+2 2 2
+select * from t1 left join t2 on (t1.i=t2.i) left join t3 on (t2.i=t3.i);
+i i i
+1 NULL NULL
+2 2 2
+select * from t3 natural right join t2;
+i i
+2 2
+NULL 3
+select * from t3 right join t2 on (t3.i=t2.i);
+i i
+2 2
+NULL 3
+select * from t3 natural right join t2 natural right join t1;
+i i i
+NULL NULL 1
+2 2 2
+select * from t3 right join t2 on (t3.i=t2.i) right join t1 on (t2.i=t1.i);
+i i i
+NULL NULL 1
+2 2 2
+select * from t1,t2 natural left join t3 order by t1.i,t2.i,t3.i;
+i i i
+1 2 2
+1 3 NULL
+2 2 2
+2 3 NULL
+select * from t1,t2 left join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i;
+i i i
+1 2 2
+1 3 NULL
+2 2 2
+2 3 NULL
+select t1.i,t2.i,t3.i from t2 natural left join t3,t1 order by t1.i,t2.i,t3.i;
+i i i
+1 2 2
+1 3 NULL
+2 2 2
+2 3 NULL
+select t1.i,t2.i,t3.i from t2 left join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i;
+i i i
+1 2 2
+1 3 NULL
+2 2 2
+2 3 NULL
+select * from t1,t2 natural right join t3 order by t1.i,t2.i,t3.i;
+i i i
+1 NULL 4
+1 2 2
+2 NULL 4
+2 2 2
+select * from t1,t2 right join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i;
+i i i
+1 NULL 4
+1 2 2
+2 NULL 4
+2 2 2
+select t1.i,t2.i,t3.i from t2 natural right join t3,t1 order by t1.i,t2.i,t3.i;
+i i i
+1 NULL 4
+1 2 2
+2 NULL 4
+2 2 2
+select t1.i,t2.i,t3.i from t2 right join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i;
+i i i
+1 NULL 4
+1 2 2
+2 NULL 4
+2 2 2
+drop table t1,t2,t3;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 9ac44bec377..1412c5e7d10 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -350,12 +350,7 @@ select t1.name, t2.name, t2.id,t3.id from t1 right join t2 on (t1.id = t2.owner)
name name id id
Antonio Paz El Gato 1 1
Antonio Paz Perrito 2 1
-NULL Happy 3 1
-NULL El Gato 1 2
-NULL Perrito 2 2
-NULL Happy 3 2
-NULL El Gato 1 3
-NULL Perrito 2 3
+NULL NULL NULL 2
Thimble Smith Happy 3 3
select t1.name, t2.name, t2.id, t2.owner, t3.id from t1 left join t2 on (t1.id = t2.owner) right join t1 as t3 on t3.id=t2.owner;
name name id owner id
@@ -372,10 +367,10 @@ Thimble Smith Happy 3 3 3
drop table t1,t2;
create table t1 (id int not null, str char(10), index(str));
insert into t1 values (1, null), (2, null), (3, "foo"), (4, "bar");
-select * from t1 where str is not null;
+select * from t1 where str is not null order by id;
id str
-4 bar
3 foo
+4 bar
select * from t1 where str is null;
id str
1 NULL
@@ -651,3 +646,15 @@ fooID barID fooID
20 2 NULL
30 3 30
drop table t1,t2;
+drop table if exists t3;
+create table t1 (i int);
+create table t2 (i int);
+create table t3 (i int);
+insert into t1 values(1),(2);
+insert into t2 values(2),(3);
+insert into t3 values(2),(4);
+select * from t1 natural left join t2 natural left join t3;
+i i i
+1 NULL NULL
+2 2 2
+drop table t1,t2,t3;
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index 9e1f743d132..7fe7109699c 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -42,7 +42,6 @@ price area type transityes shopsyes schoolsyes petsyes
drop table t1;
CREATE TABLE t1 (program enum('signup','unique','sliding') not null, type enum('basic','sliding','signup'), sites set('mt'), PRIMARY KEY (program));
ALTER TABLE t1 modify program enum('signup','unique','sliding');
-All parts of a PRIMARY KEY must be NOT NULL; If you need NULL in a key, use UNIQUE instead
drop table t1;
CREATE TABLE t1 (
name varchar(50) DEFAULT '' NOT NULL,
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
new file mode 100644
index 00000000000..d121a4e6c40
--- /dev/null
+++ b/mysql-test/r/loaddata.result
@@ -0,0 +1,11 @@
+drop table if exists t1;
+create table t1 (a date, b date, c date not null, d date);
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
+SELECT * from t1;
+a b c d
+0000-00-00 NULL 0000-00-00 0000-00-00
+0000-00-00 0000-00-00 0000-00-00 0000-00-00
+2003-03-03 2003-03-03 2003-03-03 NULL
+2003-03-03 2003-03-03 2003-03-03 NULL
+drop table t1;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index da1c429df63..2aa7db1599e 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -300,7 +300,7 @@ a b
107 7
108 8
109 9
-update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5;
+update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t2.a=t1.a-100;
select * from t1;
a b
201 1
@@ -314,13 +314,21 @@ a b
109 9
select * from t2;
a b
-1 3
-2 3
-3 3
-4 3
-5 3
-6 3
-7 3
-8 3
-9 3
+1 1
+2 2
+3 13
+4 14
+5 15
+6 6
+7 7
+8 8
+9 9
drop table t1,t2;
+CREATE TABLE t3 ( KEY1 varchar(50) NOT NULL default '', PARAM_CORR_DISTANCE_RUSH double default NULL, PARAM_CORR_DISTANCE_GEM double default NULL, PARAM_AVG_TARE double default NULL, PARAM_AVG_NB_DAYS double default NULL, PARAM_DEFAULT_PROP_GEM_SRVC varchar(50) default NULL, PARAM_DEFAULT_PROP_GEM_NO_ETIK varchar(50) default NULL, PARAM_SCENARIO_COSTS varchar(50) default NULL, PARAM_DEFAULT_WAGON_COST double default NULL, tmp int(11) default NULL, PRIMARY KEY (KEY1)) TYPE=MyISAM;
+INSERT INTO t3 VALUES ('A',1,1,22,3.2,'R','R','BASE2',0.24,NULL);
+create table t1 (A varchar(1));
+insert into t1 values ("A") ,("B"),("C"),("D");
+create table t2(Z varchar(15));
+insert into t2(Z) select concat(a.a,b.a,c.a,d.a) from t1 as a, t1 as b, t1 as c, t1 as d;
+update t2,t3 set Z =param_scenario_costs;
+drop table t1,t2,t3;
diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result
index ce3af6c37cd..3248d359546 100644
--- a/mysql-test/r/null_key.result
+++ b/mysql-test/r/null_key.result
@@ -84,7 +84,7 @@ id select_type table type possible_keys key key_len ref rows Extra
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 Using where
+1 SIMPLE t1 range a,b a 5 NULL 12 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 Using where
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index bd5b283f26a..a8a6dd6312d 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -516,6 +516,31 @@ SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,des
titre numeropost auteur icone nbrep 0 date vue ouvert lastauteur dest
test 1 joce 0 0 0 0000-00-00 00:00:00 0 1 bug
drop table t1,t2;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1, 2);
+INSERT INTO t1 VALUES (3, 4);
+INSERT INTO t1 VALUES (5, NULL);
+SELECT * FROM t1 ORDER BY b;
+a b
+5 NULL
+1 2
+3 4
+SELECT * FROM t1 ORDER BY b DESC;
+a b
+3 4
+1 2
+5 NULL
+SELECT * FROM t1 ORDER BY (a + b);
+a b
+5 NULL
+1 2
+3 4
+SELECT * FROM t1 ORDER BY (a + b) DESC;
+a b
+3 4
+1 2
+5 NULL
+DROP TABLE t1;
CREATE TABLE t1 (
FieldKey varchar(36) NOT NULL default '',
LongVal bigint(20) default NULL,
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 46fa12dd9bc..48a2a8a5a21 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -238,13 +238,18 @@ a
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
-select sql_cache * from t1;
+select sql_cache * from t1 union select * from t1;
a
1
2
3
set query_cache_type=2;
-select sql_cache * from t1;
+select sql_cache * from t1 union select * from t1;
+a
+1
+2
+3
+select * from t1 union select sql_cache * from t1;
a
1
2
@@ -254,7 +259,7 @@ Variable_name Value
Qcache_hits 4
show status like "Qcache_queries_in_cache";
Variable_name Value
-Qcache_queries_in_cache 1
+Qcache_queries_in_cache 2
set query_cache_type=on;
reset query cache;
show status like "Qcache_queries_in_cache";
@@ -636,3 +641,21 @@ show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(2);
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 0
+select * from t1;
+a
+1
+2
+SET OPTION SQL_SELECT_LIMIT=1;
+select * from t1;
+a
+1
+show status like "Qcache_queries_in_cache";
+Variable_name Value
+Qcache_queries_in_cache 2
+SET OPTION SQL_SELECT_LIMIT=DEFAULT;
+drop table t1;
diff --git a/mysql-test/r/raid.result b/mysql-test/r/raid.result
index 41af50851e9..fd47a9451f6 100644
--- a/mysql-test/r/raid.result
+++ b/mysql-test/r/raid.result
@@ -1,3 +1,6 @@
+create database test_raid;
+create table test_raid.r1 (i int) raid_type=1;
+drop database test_raid;
DROP TABLE IF EXISTS t1,t2;
CREATE TABLE t1 (
id int unsigned not null auto_increment primary key,
diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result
index 8b50f9a92e8..6c2107b2cf3 100644
--- a/mysql-test/r/repair.result
+++ b/mysql-test/r/repair.result
@@ -4,4 +4,12 @@ repair table t1 use_frm;
Table Op Msg_type Msg_text
test.t1 repair warning Number of rows changed from 0 to 1
test.t1 repair status OK
-drop table if exists t1;
+alter table t1 TYPE=HEAP;
+repair table t1 use_frm;
+Table Op Msg_type Msg_text
+test.t1 repair error The handler for the table doesn't support repair
+drop table t1;
+repair table t1 use_frm;
+Table Op Msg_type Msg_text
+test.t1 repair error Table 'test.t1' doesn't exist
+create table t1 type=myisam SELECT 1,"table 1";
diff --git a/mysql-test/r/repair_part2.result b/mysql-test/r/repair_part2.result
new file mode 100644
index 00000000000..77aa98c3da9
--- /dev/null
+++ b/mysql-test/r/repair_part2.result
@@ -0,0 +1,8 @@
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair error Can't open file: 't1.MYI'. (errno: 130)
+repair table t1 use_frm;
+Table Op Msg_type Msg_text
+test.t1 repair warning Number of rows changed from 0 to 1
+test.t1 repair status OK
+drop table t1;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 0d1743d72b7..825a94c0ebf 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -3411,13 +3411,7 @@ a a a
select * from t1 natural left join (t1 as t2 left join t1 as t3 using (a));
a a a
1 1 1
-2 1 NULL
-3 1 NULL
-1 2 NULL
2 2 2
-3 2 NULL
-1 3 NULL
-2 3 NULL
3 3 3
select * from (t1 as t2 left join t1 as t3 using (a)) right join t1 on t1.a>1;
a a a
@@ -3473,13 +3467,7 @@ a a a
select * from t1 natural join (t1 as t2 left join t1 as t3 using (a));
a a a
1 1 1
-2 1 NULL
-3 1 NULL
-1 2 NULL
2 2 2
-3 2 NULL
-1 3 NULL
-2 3 NULL
3 3 3
select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1;
a a a
diff --git a/mysql-test/r/select_safe.result b/mysql-test/r/select_safe.result
index e225a0e3995..3303f19d9c7 100644
--- a/mysql-test/r/select_safe.result
+++ b/mysql-test/r/select_safe.result
@@ -1,6 +1,6 @@
drop table if exists t1;
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9;
-create table t1 (a int primary key, b char(20));
+create table t1 (a int auto_increment primary key, b char(20));
insert into t1 values(1,"test");
SELECT SQL_BUFFER_RESULT * from t1;
a b
@@ -30,10 +30,34 @@ You are using safe update mode and you tried to update a table without a WHERE t
delete from t1 where a+0=1;
You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5;
-The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok
+The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
update t1 set b="a" limit 1;
update t1 set b="a" where b="b" limit 2;
delete from t1 where b="test" limit 1;
delete from t1 where a+0=1 limit 2;
+SET MAX_JOIN_SIZE=2;
+SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS;
+@@max_join_size @@sql_big_selects
+2 0
+insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a");
+SELECT * from t1;
+The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
+SET SQL_BIG_SELECTS=1;
+SELECT * from t1;
+a b
+3 a
+2 test2
+4 a
+5 a
+SET MAX_JOIN_SIZE=2;
+SELECT * from t1;
+The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok
+SET MAX_JOIN_SIZE=DEFAULT;
+SELECT * from t1;
+a b
+3 a
+2 test2
+4 a
+5 a
drop table t1;
SET SQL_SAFE_UPDATES=0,SQL_SELECT_LIMIT=DEFAULT, SQL_MAX_JOIN_SIZE=DEFAULT;
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index 4c326957c03..b74765696a2 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -357,3 +357,9 @@ select * from t1;
a
99999999999
drop table t1;
+CREATE TABLE t1 (a_dec DECIMAL(-1,0));
+Too big column length for column 'a_dec' (max = 255). Use BLOB instead
+CREATE TABLE t1 (a_dec DECIMAL(-2,1));
+Too big column length for column 'a_dec' (max = 255). Use BLOB instead
+CREATE TABLE t1 (a_dec DECIMAL(-1,1));
+Too big column length for column 'a_dec' (max = 255). Use BLOB instead
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 7b29a8fbcde..d506891b0fb 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2,t3;
+drop table if exists t1,t2,t3,t4,t5,t6;
CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
CREATE TABLE t2 (a int not null, b char (10) not null);
@@ -198,12 +198,68 @@ a
11
set SQL_SELECT_LIMIT=DEFAULT;
drop table t1,t2;
+CREATE TABLE t1 (
+cid smallint(5) unsigned NOT NULL default '0',
+cv varchar(250) NOT NULL default '',
+PRIMARY KEY (cid),
+UNIQUE KEY cv (cv)
+) ;
+INSERT INTO t1 VALUES (8,'dummy');
+CREATE TABLE t2 (
+cid bigint(20) unsigned NOT NULL auto_increment,
+cap varchar(255) NOT NULL default '',
+PRIMARY KEY (cid),
+KEY cap (cap)
+) ;
+CREATE TABLE t3 (
+gid bigint(20) unsigned NOT NULL auto_increment,
+gn varchar(255) NOT NULL default '',
+must tinyint(4) default NULL,
+PRIMARY KEY (gid),
+KEY gn (gn)
+) ;
+INSERT INTO t3 VALUES (1,'V1',NULL);
+CREATE TABLE t4 (
+uid bigint(20) unsigned NOT NULL default '0',
+gid bigint(20) unsigned default NULL,
+rid bigint(20) unsigned default NULL,
+cid bigint(20) unsigned default NULL,
+UNIQUE KEY m (uid,gid,rid,cid),
+KEY uid (uid),
+KEY rid (rid),
+KEY cid (cid),
+KEY container (gid,rid,cid)
+) ;
+INSERT INTO t4 VALUES (1,1,NULL,NULL);
+CREATE TABLE t5 (
+rid bigint(20) unsigned NOT NULL auto_increment,
+rl varchar(255) NOT NULL default '',
+PRIMARY KEY (rid),
+KEY rl (rl)
+) ;
+CREATE TABLE t6 (
+uid bigint(20) unsigned NOT NULL auto_increment,
+un varchar(250) NOT NULL default '',
+uc smallint(5) unsigned NOT NULL default '0',
+PRIMARY KEY (uid),
+UNIQUE KEY nc (un,uc),
+KEY un (un)
+) ;
+INSERT INTO t6 VALUES (1,'test',8);
+SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test";
+uid rl g1 cid gg
+1 NULL V1 NULL 1
+SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t3.must IS NOT NULL AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test";
+uid rl g1 cid gg
+(SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t3.must IS NOT NULL AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test") UNION (SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test");
+uid rl g1 cid gg
+1 NULL V1 NULL 1
+drop table t1,t2,t3,t4,t5,t6;
select * union select 1;
No tables used
select 1 as a,(select a union select a);
a (select a union select a)
1 1
-drop table if exists t1,t2;
CREATE TABLE t1 ( id int(3) unsigned default '0') TYPE=MyISAM;
INSERT INTO t1 (id) VALUES("1");
CREATE TABLE t2 ( id int(3) unsigned default '0', id_master int(5) default '0', text1 varchar(5) default NULL, text2 varchar(5) default NULL) TYPE=MyISAM;
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result
index 9978e3cb29c..c308b8fcbcd 100644
--- a/mysql-test/r/update.result
+++ b/mysql-test/r/update.result
@@ -102,16 +102,67 @@ select status from t1;
status
1
drop table t1;
-create table t1 (a int not null, b int not null);
-insert into t1 values (1,1),(1,2),(1,3);
-update t1 set b=4 where a=1 order by b asc limit 1;
-update t1 set b=4 where a=1 order by b desc limit 1;
-create table t2 (a int not null, b int not null);
-insert into t2 values (1,1),(1,2),(1,3);
-select * from t1;
+create table t1 (a int not null, b int not null, key (a));
+insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3);
+SET @tmp=0;
+update t1 set b=(@tmp:=@tmp+1) order by a;
+update t1 set b=99 where a=1 order by b asc limit 1;
+select * from t1 order by a,b;
a b
-1 4
1 2
-1 4
-update t1 set b=(select distinct 1 from (select * from t2) a);
-drop table t1,t2;
+1 3
+1 99
+2 4
+2 5
+2 6
+3 7
+3 8
+3 9
+3 10
+3 11
+3 12
+update t1 set b=100 where a=1 order by b desc limit 2;
+update t1 set a=a+10+b where a=1 order by b;
+select * from t1 order by a,b;
+a b
+2 4
+2 5
+2 6
+3 7
+3 8
+3 9
+3 10
+3 11
+3 12
+13 2
+111 100
+111 100
+drop table t1;
+CREATE TABLE t1 (
+`id_param` smallint(3) unsigned NOT NULL default '0',
+`nom_option` char(40) NOT NULL default '',
+`valid` tinyint(1) NOT NULL default '0',
+KEY `id_param` (`id_param`,`nom_option`)
+) TYPE=MyISAM;
+INSERT INTO t1 (id_param,nom_option,valid) VALUES (185,'600x1200',1);
+UPDATE t1 SET nom_option='test' WHERE id_param=185 AND nom_option='600x1200' AND valid=1 LIMIT 1;
+select * from t1;
+id_param nom_option valid
+185 test 1
+drop table t1;
+create table t1 (F1 VARCHAR(30), F2 VARCHAR(30), F3 VARCHAR(30), cnt int, groupid int, KEY groupid_index (groupid));
+insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6),
+('0','1','2',1,5), ('0','2','0',1,3), ('1','0','1',1,2),
+('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4),
+('2','2','0',1,7);
+delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3);
+select * from t1;
+F1 F2 F3 cnt groupid
+0 0 0 1 6
+0 1 2 1 5
+0 2 0 1 3
+1 0 1 1 2
+1 2 1 1 1
+2 0 1 2 4
+2 2 0 1 7
+drop table t1;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index 5e613418ea1..8cf0a676b95 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -108,17 +108,14 @@ show global variables like 'table_type';
Variable_name Value
table_type INNODB
set GLOBAL query_cache_size=100000;
-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
-myisam_max_sort_file_size 10000
+set GLOBAL myisam_max_sort_file_size=2000000;
show global variables like 'myisam_max_sort_file_size';
Variable_name Value
-myisam_max_sort_file_size 20000
-set myisam_max_sort_file_size=default;
+myisam_max_sort_file_size 1048576
+set GLOBAL myisam_max_sort_file_size=default;
show variables like 'myisam_max_sort_file_size';
Variable_name Value
-myisam_max_sort_file_size 20000
+myisam_max_sort_file_size FILE_SIZE
set global net_retry_count=10, session net_retry_count=10;
set global net_buffer_length=1024, net_write_timeout=200, net_read_timeout=300;
set session net_buffer_length=2048, net_write_timeout=500, net_read_timeout=600;
@@ -199,6 +196,10 @@ set @@global.sql_auto_is_null=1;
Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL
select @@global.sql_auto_is_null;
Variable 'sql_auto_is_null' is a LOCAL variable and can't be used with SET GLOBAL
+set myisam_max_sort_file_size=100;
+Variable 'myisam_max_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
+set myisam_max_extra_sort_file_size=100;
+Variable 'myisam_max_extra_sort_file_size' is a GLOBAL variable and should be set with SET GLOBAL
set autocommit=1;
set big_tables=1;
select @@autocommit, @@big_tables;
@@ -252,11 +253,11 @@ select @@max_user_connections;
@@max_user_connections
100
set global max_write_lock_count=100;
-set myisam_max_extra_sort_file_size=100;
+set global myisam_max_extra_sort_file_size=100;
select @@myisam_max_extra_sort_file_size;
@@myisam_max_extra_sort_file_size
100
-set myisam_max_sort_file_size=100;
+set global myisam_max_sort_file_size=100;
set myisam_sort_buffer_size=100;
set net_buffer_length=100;
set net_read_timeout=100;
@@ -323,3 +324,8 @@ test.t1 check status OK
test.t2 check status OK
select max(a) +1, max(a) +2 into @xx,@yy from t1;
drop table t1,t2;
+select @@xxxxxxxxxx;
+Unknown system variable 'xxxxxxxxxx'
+select 1;
+1
+1
diff --git a/mysql-test/std_data/loaddata1.dat b/mysql-test/std_data/loaddata1.dat
new file mode 100644
index 00000000000..c9e8549b211
--- /dev/null
+++ b/mysql-test/std_data/loaddata1.dat
@@ -0,0 +1,3 @@
+,\N,NULL,,
+00,0,000000,,
+2003-03-03, 20030303,030303,\N
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index 64b657f1146..fc22bc85aee 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -88,6 +88,7 @@ create table t1 (n1 int not null, n2 int, n3 int, n4 float,
key (n3, n4, n1, n2),
key (n4, n1, n2, n3) );
alter table t1 disable keys;
+show keys from t1;
#let $1=10000;
let $1=10;
while ($1)
@@ -96,6 +97,7 @@ while ($1)
dec $1;
}
alter table t1 enable keys;
+show keys from t1;
drop table t1;
#
@@ -117,3 +119,19 @@ alter table t1 rename t2;
alter table t2 rename t1, add c char(10) comment "no comment";
show columns from t1;
drop table t1;
+
+# implicit analyze
+
+create table t1 (a int, b int);
+let $1=100;
+while ($1)
+{
+ eval insert into t1 values(1,$1), (2,$1), (3, $1);
+ dec $1;
+}
+alter table t1 add unique (a,b), add key (b);
+show keys from t1;
+analyze table t1;
+show keys from t1;
+drop table t1;
+
diff --git a/mysql-test/t/ansi-master.opt b/mysql-test/t/ansi-master.opt
new file mode 100644
index 00000000000..6bf7a4f30e2
--- /dev/null
+++ b/mysql-test/t/ansi-master.opt
@@ -0,0 +1 @@
+--ansi
diff --git a/mysql-test/t/ansi.test b/mysql-test/t/ansi.test
new file mode 100644
index 00000000000..e1ac8ffd4f9
--- /dev/null
+++ b/mysql-test/t/ansi.test
@@ -0,0 +1,17 @@
+#
+# Test of ansi mode
+#
+
+drop table if exists t1;
+
+# Test some functions that works different in ansi mode
+
+SELECT 'A' || 'B';
+
+# Test GROUP BY behaviour
+
+CREATE TABLE t1 (id INT, id2 int);
+SELECT id,NULL,1,1.1,'a' FROM t1 GROUP BY id;
+--error 1055
+SELECT id FROM t1 GROUP BY id2;
+drop table t1;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index cda9307804b..3a02e5d67e8 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -27,11 +27,9 @@ drop table if exists t1,t2;
!$1167 create table t1 (b char(0) not null, index(b));
create table t1 (a int not null auto_increment,primary key (a)) type=heap;
!$1163 create table t1 (a int not null,b text) type=heap;
-!$1171 create table t1 (a int ,primary key(a)) type=heap;
drop table if exists t1;
!$1075 create table t1 (ordid int(8) not null auto_increment, ord varchar(50) not null, primary key (ord,ordid)) type=heap;
-!$1171 create table t1 (ordid int(8), primary key (ordid));
-- error 1044,1
create table not_existing_database.test (a int);
@@ -124,6 +122,37 @@ drop table t1;
create table t1 select if('2002'='2002','Y','N');
select * from t1;
drop table if exists t1;
+
+#
+# Test default table type
+#
+SET SESSION table_type="heap";
+SELECT @@table_type;
+CREATE TABLE t1 (a int not null);
+show create table t1;
+drop table t1;
+# Test what happens when using a non existing table type
+SET SESSION table_type="gemini";
+SELECT @@table_type;
+CREATE TABLE t1 (a int not null);
+show create table t1;
+SET SESSION table_type=default;
+drop table t1;
+
+
+#
+# ISO requires that primary keys are implicitly NOT NULL
+#
+create table t1 ( k1 varchar(2), k2 int, primary key(k1,k2));
+insert into t1 values ("a", 1), ("b", 2);
+!$1048 insert into t1 values ("c", NULL);
+!$1048 insert into t1 values (NULL, 3);
+!$1048 insert into t1 values (NULL, NULL);
+
+#
+# Test create with foreign keys
+#
+
create table t1 (a int, key(a));
create table t2 (b int, foreign key(b) references t1(a), key(b));
drop table if exists t1,t2;
diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test
index e0591913f68..b63af87601b 100644
--- a/mysql-test/t/ctype_latin1_de.test
+++ b/mysql-test/t/ctype_latin1_de.test
@@ -47,3 +47,26 @@ select * from t1 where a like "test%";
select * from t1 where a like "te_t";
select * from t1 where match a against ("te*" in boolean mode)+0;
drop table t1;
+
+#
+# Test bug report #152 (problem with index on latin1_de)
+#
+
+create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word));
+insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae');
+update t1 set word2=word;
+select word, word=0xdf as t from t1 having t > 0;
+select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0;
+select * from t1 where word=0xDF;
+select * from t1 where word=CAST(0xDF as CHAR);
+select * from t1 where word2=0xDF;
+select * from t1 where word2=CAST(0xDF as CHAR);
+select * from t1 where word='ae';
+select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR);
+select * from t1 where word between 0xDF and 0xDF;
+select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR);
+select * from t1 where word like 'ae';
+select * from t1 where word like 'AE';
+select * from t1 where word like 0xDF;
+select * from t1 where word like CAST(0xDF as CHAR);
+drop table t1;
diff --git a/mysql-test/t/ctype_ujis-master.opt b/mysql-test/t/ctype_ujis-master.opt
new file mode 100644
index 00000000000..1f4183d5027
--- /dev/null
+++ b/mysql-test/t/ctype_ujis-master.opt
@@ -0,0 +1 @@
+--default-character-set=ujis
diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test
new file mode 100644
index 00000000000..cd1dc965000
--- /dev/null
+++ b/mysql-test/t/ctype_ujis.test
@@ -0,0 +1,13 @@
+#
+# Tests with the ujis character set
+#
+drop table if exists t1;
+
+#
+# Test problem with LEFT()
+#
+
+create table t1 (c text);
+insert into t1 values (0xa4a2),(0xa4a3);
+select hex(left(c,1)) from t1 group by c;
+drop table t1;
diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test
index 91216ff9c3a..f1f751d728b 100644
--- a/mysql-test/t/delete.test
+++ b/mysql-test/t/delete.test
@@ -64,4 +64,10 @@ select * from t1 where misc > 5 and bool is null;
delete from t1 where misc > 5 and bool is null;
select * from t1 where misc > 5 and bool is null;
+select count(*) from t1;
+delete from t1 where 1 > 2;
+select count(*) from t1;
+delete from t1 where 3 > 2;
+select count(*) from t1;
+
drop table t1;
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 214236268fa..1c579ddcc62 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -175,3 +175,16 @@ repair table t1;
select * from t1 where match (a) against ('aaaa');
drop table t1;
+#
+# bug 283 by jocelyn fournier <joc@presence-pc.com>
+# FULLTEXT index on a TEXT filed converted to a CHAR field doesn't work anymore
+#
+
+drop table if exists t1;
+create table t1 ( ref_mag text not null, fulltext (ref_mag));
+insert into t1 values ('test');
+select ref_mag from t1 where match ref_mag against ('+test' in boolean mode);
+alter table t1 change ref_mag ref_mag char (255) not null;
+select ref_mag from t1 where match ref_mag against ('+test' in boolean mode);
+drop table t1;
+
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index c78509d3869..aca9530ffc3 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -326,6 +326,26 @@ explain
select min(a4) from t1 where (a4 + 0.01) between 0.07 and 0.08;
explain
select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME';
+drop table t1, t2;
-# Clean up
-drop table if exists t1, t2; \ No newline at end of file
+
+#
+# Test of group function and NULL values
+#
+
+CREATE TABLE t1 (a int, b int);
+select count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1;
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+insert into t1 values (1,null);
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+insert into t1 values (1,null);
+insert into t1 values (2,null);
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+insert into t1 values (2,1);
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+insert into t1 values (3,1);
+select a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+select SQL_BIG_RESULT a,count(b), sum(b), avg(b), std(b), min(b), max(b), bit_and(b), bit_or(b) from t1 group by a;
+drop table t1;
diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
index d48b17e87af..be64c170fa1 100644
--- a/mysql-test/t/func_misc.test
+++ b/mysql-test/t/func_misc.test
@@ -7,3 +7,8 @@ select format(1.5555,0),format(123.5555,1),format(1234.5555,2),format(12345.5555
select inet_ntoa(inet_aton("255.255.255.255.255.255.255.255"));
select inet_aton("255.255.255.255.255"),inet_aton("255.255.1.255"),inet_aton("0.1.255");
select inet_ntoa(1099511627775),inet_ntoa(4294902271),inet_ntoa(511);
+
+#
+# Test for core dump with nan
+#
+select length(format('nan', 2)) > 0;
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 912bed1955c..d99c7a87f88 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -44,12 +44,15 @@ CREATE TABLE t2 (
INSERT INTO t2 VALUES (1,'name','pass','mail','Y','v','n','adr','1','1','1');
INSERT INTO t2 VALUES (2,'name','pass','mail','Y','v','n','adr','1','1','1');
INSERT INTO t2 VALUES (3,'name','pass','mail','Y','v','n','adr','1','1','1');
+INSERT INTO t2 VALUES (4,'name','pass','mail','Y','v','n','adr','1','1','1');
+INSERT INTO t2 VALUES (5,'name','pass','mail','Y','v','n','adr','1','1','1');
SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid;
SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID GROUP BY t2.userid ORDER BY NULL;
SELECT t2.userid, MIN(t1.score) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid;
SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid;
SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL;
+EXPLAIN SELECT t2.userid, MIN(t1.score+0.0) FROM t1, t2 WHERE t1.userID=t2.userID AND t1.spID=2 GROUP BY t2.userid ORDER BY NULL;
drop table t1,t2;
#
@@ -246,7 +249,7 @@ CREATE TABLE t1 (
key (score)
);
-INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3);
+INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3),(6,3,3),(7,3,3);
explain select userid,count(*) from t1 group by userid desc;
explain select userid,count(*) from t1 group by userid desc order by null;
select userid,count(*) from t1 group by userid desc;
@@ -265,8 +268,6 @@ explain select sql_big_result score,count(*) from t1 group by score desc order b
select sql_big_result score,count(*) from t1 group by score desc;
drop table t1;
-#
-
# not purely group_by bug, but group_by is involved...
create table t1 (a date default null, b date default null);
@@ -275,7 +276,6 @@ select a,min(b) c,count(distinct rand()) from t1 group by a having c<a + interva
drop table t1;
# Compare with hash keys
-#
CREATE TABLE t1 (a char(1));
INSERT INTO t1 VALUES ('A'),('B'),('A'),('B'),('A'),('B'),(NULL),('a'),('b'),(NULL),('A'),('B'),(NULL);
@@ -410,15 +410,7 @@ drop table t1,t2;
#
create table t1 (a int, b int);
-insert into t1 values (1, 4);
-insert into t1 values (10, 40);
-insert into t1 values (1, 4);
-insert into t1 values (10, 43);
-insert into t1 values (1, 4);
-insert into t1 values (10, 41);
-insert into t1 values (1, 4);
-insert into t1 values (10, 43);
-insert into t1 values (1, 4);
+insert into t1 values (1, 4),(10, 40),(1, 4),(10, 43),(1, 4),(10, 41),(1, 4),(10, 43),(1, 4);
select a, MAX(b), INTERVAL (MAX(b), 1,3,10,30,39,40,50,60,100,1000) from t1 group by a;
select a, MAX(b), CASE MAX(b) when 4 then 4 when 43 then 43 else 0 end from t1 group by a;
select a, MAX(b), FIELD(MAX(b), '43', '4', '5') from t1 group by a;
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 4bd56400f98..7d5fbee011f 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -64,3 +64,13 @@ select Fld1, max(Fld2) from t1 group by Fld1 having avg(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having variance(Fld2) is not null;
drop table t1;
+
+#
+# Test problem with count(distinct) in having
+#
+create table t1 (id int not null, qty int not null);
+insert into t1 values (1,2),(1,3),(2,4),(2,5);
+select id, sum(qty) as sqty from t1 group by id having sqty>2;
+select sum(qty) as sqty from t1 group by id having count(id) > 0;
+select sum(qty) as sqty from t1 group by id having count(distinct id) > 0;
+drop table t1;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index bf1756ede5c..a0cb104df48 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -45,12 +45,9 @@ 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;
---replace_result 12 # 6 #
-explain select level from t1 where level=1;
---replace_result 12 # 6 #
-explain select level,id from t1 where level=1;
---replace_result 12 # 6 # 5 #
-explain select level,id,parent_id from t1 where level=1;
+# 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;
select level,id from t1 where level=1;
select level,id,parent_id from t1 where level=1;
optimize table t1;
@@ -348,7 +345,7 @@ 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;
-explain select level from t1 where level=1;
+# explain select level from t1 where level=1;
select level,id from t1 where level=1;
select level,id,parent_id from t1 where level=1;
select level,id from t1 where level=1 order by id;
@@ -784,7 +781,7 @@ drop table t1;
CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) type=innodb;
CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) type=innodb;
-INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12);
INSERT INTO t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
# Full join, without key
@@ -800,11 +797,77 @@ update t1,t2 set t1.b=t1.b+10 where t1.b=2;
select * from t1;
# Range key (in t1)
-update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5;
+update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t1.a=t2.a+100;
select * from t1;
select * from t2;
drop table t1,t2;
+CREATE TABLE t2 ( NEXT_T BIGINT NOT NULL PRIMARY KEY) TYPE=MyISAM;
+CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) TYPE=InnoDB;
+SET AUTOCOMMIT=0;
+INSERT INTO t1 ( B_ID ) VALUES ( 1 );
+INSERT INTO t2 ( NEXT_T ) VALUES ( 1 );
+-- error 1196
+ROLLBACK;
+SELECT * FROM t1;
+drop table t1,t2;
+create table t1 ( pk int primary key, parent int not null, child int not null, index (parent) ) type = innodb;
+insert into t1 values (1,0,4), (2,1,3), (3,2,1), (4,1,2);
+select distinct parent,child from t1 order by parent;
+drop table t1;
+
+#
+# Test that MySQL priorities clustered indexes
+#
+create table t1 (a int not null auto_increment primary key, b int, c int, key(c)) type=innodb;
+create table t2 (a int not null auto_increment primary key, b int);
+insert into t1 (b) values (null),(null),(null),(null),(null),(null),(null);
+insert into t2 (a) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+select count(*) from t1;
+explain select * from t1 where c between 1 and 10000;
+update t1 set c=a;
+explain select * from t1 where c between 1 and 10000;
+drop table t1,t2;
+
+#
+# Test of UPDATE ... ORDER BY
+#
+
+create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) type=innodb;
+
+insert into t1 (id) values (null),(null),(null),(null),(null);
+update t1 set fk=69 where fk is null order by id limit 1;
+SELECT * from t1;
+drop table t1;
+
+create table t1 (a int not null, b int not null, key (a));
+insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3);
+SET @tmp=0;
+update t1 set b=(@tmp:=@tmp+1) order by a;
+update t1 set b=99 where a=1 order by b asc limit 1;
+update t1 set b=100 where a=1 order by b desc limit 2;
+update t1 set a=a+10+b where a=1 order by b;
+select * from t1 order by a,b;
+drop table t1;
+
+
CREATE TABLE t1 (col1 int(1))TYPE=InnoDB;
CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP(+0),INDEX stamp_idx
(stamp))TYPE=InnoDB;
diff --git a/mysql-test/t/innodb_handler.test b/mysql-test/t/innodb_handler.test
index 32c8741577c..cf6ac9870ce 100644
--- a/mysql-test/t/innodb_handler.test
+++ b/mysql-test/t/innodb_handler.test
@@ -75,5 +75,11 @@ alter table t1 type=innodb;
--error 1109
handler t2 read first;
-drop table if exists t1;
+drop table t1;
+CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2)) TYPE=InnoDB;
+INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2);
+HANDLER t1 OPEN;
+HANDLER t1 READ `primary` = (1, 1000);
+HANDLER t1 READ `primary` PREV;
+DROP TABLE t1;
diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test
index 5fd96d6687c..882aec1006a 100644
--- a/mysql-test/t/join.test
+++ b/mysql-test/t/join.test
@@ -272,3 +272,49 @@ INSERT INTO t2 VALUES ('rivercats','cust',20);
SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE emp.emp_id = 'psmith' AND lr.siteid = 'rivercats';
SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith';
drop table t1,t2;
+
+#
+# Problem with internal list handling when reducing WHERE
+#
+
+CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, Value1 VARCHAR(255));
+CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255));
+INSERT INTO t1 VALUES (1, 'A');
+INSERT INTO t2 VALUES (1, 'B');
+
+SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND (Value1 = 'A' AND Value2 <> 'B');
+SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND Value1 = 'A' AND Value2 <> 'B';
+SELECT * FROM t1 NATURAL JOIN t2 WHERE (Value1 = 'A' AND Value2 <> 'B') AND 1;
+drop table t1,t2;
+
+#
+# Test combination of join methods
+#
+
+create table t1 (i int);
+create table t2 (i int);
+create table t3 (i int);
+insert into t1 values(1),(2);
+insert into t2 values(2),(3);
+insert into t3 values (2),(4);
+
+select * from t1 natural left join t2;
+select * from t1 left join t2 on (t1.i=t2.i);
+select * from t1 natural left join t2 natural left join t3;
+select * from t1 left join t2 on (t1.i=t2.i) left join t3 on (t2.i=t3.i);
+
+select * from t3 natural right join t2;
+select * from t3 right join t2 on (t3.i=t2.i);
+select * from t3 natural right join t2 natural right join t1;
+select * from t3 right join t2 on (t3.i=t2.i) right join t1 on (t2.i=t1.i);
+
+select * from t1,t2 natural left join t3 order by t1.i,t2.i,t3.i;
+select * from t1,t2 left join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i;
+select t1.i,t2.i,t3.i from t2 natural left join t3,t1 order by t1.i,t2.i,t3.i;
+select t1.i,t2.i,t3.i from t2 left join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i;
+
+select * from t1,t2 natural right join t3 order by t1.i,t2.i,t3.i;
+select * from t1,t2 right join t3 on (t2.i=t3.i) order by t1.i,t2.i,t3.i;
+select t1.i,t2.i,t3.i from t2 natural right join t3,t1 order by t1.i,t2.i,t3.i;
+select t1.i,t2.i,t3.i from t2 right join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i,t3.i;
+drop table t1,t2,t3;
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index c57fb8273fe..49f13abe7c2 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -249,7 +249,7 @@ drop table t1,t2;
create table t1 (id int not null, str char(10), index(str));
insert into t1 values (1, null), (2, null), (3, "foo"), (4, "bar");
-select * from t1 where str is not null;
+select * from t1 where str is not null order by id;
select * from t1 where str is null;
drop table t1;
@@ -417,3 +417,12 @@ explain select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30;
select * from t2 left join t1 ignore index(primary) on t1.fooID = t2.fooID and t1.fooID = 30;
drop table t1,t2;
+drop table if exists t3;
+create table t1 (i int);
+create table t2 (i int);
+create table t3 (i int);
+insert into t1 values(1),(2);
+insert into t2 values(2),(3);
+insert into t3 values(2),(4);
+select * from t1 natural left join t2 natural left join t3;
+drop table t1,t2,t3;
diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test
index 4fd8cc86dd5..de97c639812 100644
--- a/mysql-test/t/key.test
+++ b/mysql-test/t/key.test
@@ -57,12 +57,12 @@ INSERT INTO t1 VALUES (900,'Vancouver','Shared/Roomate','Y','Y','Y','Y');
drop table t1;
#
-# problem med primary key
+# No longer a problem with primary key
#
CREATE TABLE t1 (program enum('signup','unique','sliding') not null, type enum('basic','sliding','signup'), sites set('mt'), PRIMARY KEY (program));
-# The following should give an error for wrong primary key
-!$1171 ALTER TABLE t1 modify program enum('signup','unique','sliding');
+# This no longer give an error for wrong primary key
+ALTER TABLE t1 modify program enum('signup','unique','sliding');
drop table t1;
#
diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
new file mode 100644
index 00000000000..ceb5c47af11
--- /dev/null
+++ b/mysql-test/t/loaddata.test
@@ -0,0 +1,11 @@
+#
+# Some simple test of load data
+#
+
+drop table if exists t1;
+
+create table t1 (a date, b date, c date not null, d date);
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
+SELECT * from t1;
+drop table t1;
diff --git a/mysql-test/t/multi_update-master.opt b/mysql-test/t/multi_update-master.opt
new file mode 100644
index 00000000000..9f1a29461ff
--- /dev/null
+++ b/mysql-test/t/multi_update-master.opt
@@ -0,0 +1 @@
+--set-variable=tmp_table_size=1024
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 390dd58d806..8e560cab455 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -255,8 +255,16 @@ update t1,t2 set t1.b=t1.b+10 where t1.b=2;
select * from t1;
# Range key (in t1)
-update t1,t2 set t1.b=t1.b+2,t2.b=t1.b where t1.b between 3 and 5;
+update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t2.a=t1.a-100;
select * from t1;
select * from t2;
drop table t1,t2;
+CREATE TABLE t3 ( KEY1 varchar(50) NOT NULL default '', PARAM_CORR_DISTANCE_RUSH double default NULL, PARAM_CORR_DISTANCE_GEM double default NULL, PARAM_AVG_TARE double default NULL, PARAM_AVG_NB_DAYS double default NULL, PARAM_DEFAULT_PROP_GEM_SRVC varchar(50) default NULL, PARAM_DEFAULT_PROP_GEM_NO_ETIK varchar(50) default NULL, PARAM_SCENARIO_COSTS varchar(50) default NULL, PARAM_DEFAULT_WAGON_COST double default NULL, tmp int(11) default NULL, PRIMARY KEY (KEY1)) TYPE=MyISAM;
+INSERT INTO t3 VALUES ('A',1,1,22,3.2,'R','R','BASE2',0.24,NULL);
+create table t1 (A varchar(1));
+insert into t1 values ("A") ,("B"),("C"),("D");
+create table t2(Z varchar(15));
+insert into t2(Z) select concat(a.a,b.a,c.a,d.a) from t1 as a, t1 as b, t1 as c, t1 as d;
+update t2,t3 set Z =param_scenario_costs;
+drop table t1,t2,t3;
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 8e1f304a5a5..5235eddd671 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -334,9 +334,21 @@ SELECT titre,t1.numeropost,auteur,icone,nbrep,'0',date,vue,ouvert,lastauteur,des
drop table t1,t2;
#
-# Test of test_if_subkey() function
+# Test order by with NULL values
#
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1, 2);
+INSERT INTO t1 VALUES (3, 4);
+INSERT INTO t1 VALUES (5, NULL);
+SELECT * FROM t1 ORDER BY b;
+SELECT * FROM t1 ORDER BY b DESC;
+SELECT * FROM t1 ORDER BY (a + b);
+SELECT * FROM t1 ORDER BY (a + b) DESC;
+DROP TABLE t1;
+#
+# Test of test_if_subkey() function
+#
CREATE TABLE t1 (
FieldKey varchar(36) NOT NULL default '',
LongVal bigint(20) default NULL,
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 56eda7fa104..1078d19533c 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -147,9 +147,10 @@ create table t1 (a int not null);
insert into t1 values (1),(2),(3);
select * from t1;
show status like "Qcache_queries_in_cache";
-select sql_cache * from t1;
+select sql_cache * from t1 union select * from t1;
set query_cache_type=2;
-select sql_cache * from t1;
+select sql_cache * from t1 union select * from t1;
+select * from t1 union select sql_cache * from t1;
show status like "Qcache_hits";
show status like "Qcache_queries_in_cache";
set query_cache_type=on;
@@ -429,7 +430,6 @@ select * from t1 where id=2;
#
# Load data invalidation test
#
-
create table t1 (word char(20) not null);
select * from t1;
show status like "Qcache_queries_in_cache";
@@ -440,7 +440,6 @@ drop table t1;
#
# INTO OUTFILE/DUMPFILE test
#
-
create table t1 (a int);
insert into t1 values (1),(2),(3);
show status like "Qcache_queries_in_cache";
@@ -448,3 +447,16 @@ select * from t1 into outfile "query_caceh.out.file";
select * from t1 limit 1 into dumpfile "query_cache.dump.file";
show status like "Qcache_queries_in_cache";
drop table t1;
+
+#
+# test of SQL_SELECT_LIMIT
+#
+create table t1 (a int);
+insert into t1 values (1),(2);
+show status like "Qcache_queries_in_cache";
+select * from t1;
+SET OPTION SQL_SELECT_LIMIT=1;
+select * from t1;
+show status like "Qcache_queries_in_cache";
+SET OPTION SQL_SELECT_LIMIT=DEFAULT;
+drop table t1;
diff --git a/mysql-test/t/raid.test b/mysql-test/t/raid.test
index 38c740201bc..235add63c22 100644
--- a/mysql-test/t/raid.test
+++ b/mysql-test/t/raid.test
@@ -9,6 +9,14 @@ show variables like "have_raid";
DROP TABLE IF EXISTS t1,t2;
--enable_warnings
+#
+# Test dropping database with raid tables
+#
+
+create database test_$1;
+create table test_$1.r1 (i int) raid_type=1;
+drop database test_$1;
+
CREATE TABLE t1 (
id int unsigned not null auto_increment primary key,
c char(255) not null
diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test
index bdc5a57a07c..2657f91cd02 100644
--- a/mysql-test/t/repair.test
+++ b/mysql-test/t/repair.test
@@ -8,4 +8,15 @@ drop table if exists t1;
create table t1 SELECT 1,"table 1";
repair table t1 use_frm;
-drop table if exists t1;
+alter table t1 TYPE=HEAP;
+repair table t1 use_frm;
+drop table t1;
+
+# non-existent table
+repair table t1 use_frm;
+
+#
+# Create test table for repair2
+# The following must be last in this file
+
+create table t1 type=myisam SELECT 1,"table 1";
diff --git a/mysql-test/t/repair_part2-master.sh b/mysql-test/t/repair_part2-master.sh
new file mode 100644
index 00000000000..964bde06c18
--- /dev/null
+++ b/mysql-test/t/repair_part2-master.sh
@@ -0,0 +1 @@
+echo "1" > $MYSQL_TEST_DIR/var/master-data/test/t1.MYI
diff --git a/mysql-test/t/repair_part2.test b/mysql-test/t/repair_part2.test
new file mode 100644
index 00000000000..8c27e382dff
--- /dev/null
+++ b/mysql-test/t/repair_part2.test
@@ -0,0 +1,7 @@
+#
+# This test starts with a crashed t1.MYI file left over from repair.test
+#
+
+repair table t1;
+repair table t1 use_frm;
+drop table t1;
diff --git a/mysql-test/t/select_safe.test b/mysql-test/t/select_safe.test
index cd8bce6369c..be25c7c05d1 100644
--- a/mysql-test/t/select_safe.test
+++ b/mysql-test/t/select_safe.test
@@ -7,7 +7,7 @@ drop table if exists t1;
--enable_warnings
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=4, SQL_MAX_JOIN_SIZE=9;
-create table t1 (a int primary key, b char(20));
+create table t1 (a int auto_increment primary key, b char(20));
insert into t1 values(1,"test");
SELECT SQL_BUFFER_RESULT * from t1;
update t1 set b="a" where a=1;
@@ -18,18 +18,40 @@ update t1 set b="a" where a=1;
select 1 from t1,t1 as t2,t1 as t3,t1 as t4;
# The following should give errors:
-!$1175 update t1 set b="a";
-!$1175 update t1 set b="a" where b="test";
-!$1175 delete from t1;
-!$1175 delete from t1 where b="test";
-!$1175 delete from t1 where a+0=1;
-!$1104 select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5;
+--error 1175
+update t1 set b="a";
+--error 1175
+update t1 set b="a" where b="test";
+--error 1175
+delete from t1;
+--error 1175
+delete from t1 where b="test";
+--error 1175
+delete from t1 where a+0=1;
+--error 1104
+select 1 from t1,t1 as t2,t1 as t3,t1 as t4,t1 as t5;
# The following should be ok:
update t1 set b="a" limit 1;
update t1 set b="a" where b="b" limit 2;
delete from t1 where b="test" limit 1;
delete from t1 where a+0=1 limit 2;
+
+# Test SQL_BIG_SELECTS
+
+SET MAX_JOIN_SIZE=2;
+SELECT @@MAX_JOIN_SIZE, @@SQL_BIG_SELECTS;
+insert into t1 values (null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a"),(null,"a");
+--error 1104
+SELECT * from t1;
+SET SQL_BIG_SELECTS=1;
+SELECT * from t1;
+SET MAX_JOIN_SIZE=2;
+--error 1104
+SELECT * from t1;
+SET MAX_JOIN_SIZE=DEFAULT;
+SELECT * from t1;
+
drop table t1;
SET SQL_SAFE_UPDATES=0,SQL_SELECT_LIMIT=DEFAULT, SQL_MAX_JOIN_SIZE=DEFAULT;
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index 053d0517904..8653c06a644 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -233,3 +233,13 @@ insert into t1 values("1e4294967297");
select * from t1;
drop table t1;
+#
+# Test of wrong decimal type
+#
+
+--error 1074
+CREATE TABLE t1 (a_dec DECIMAL(-1,0));
+--error 1074
+CREATE TABLE t1 (a_dec DECIMAL(-2,1));
+--error 1074
+CREATE TABLE t1 (a_dec DECIMAL(-1,1));
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 70e770cd2d3..6d857a4b40f 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1,t2,t3;
+drop table if exists t1,t2,t3,t4,t5,t6;
--enable_warnings
CREATE TABLE t1 (a int not null, b char (10) not null);
@@ -19,7 +19,7 @@ select 0,'#' union select a,b from t1 union all select a,b from t2 union select
select a,b from t1 union select a,b from t1;
select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 group by b;
-#test alternate syntax for unions
+# Test alternate syntax for unions
(select a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 4;
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1);
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
@@ -27,7 +27,7 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b;
explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
#(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
-select found_rows();
+#select found_rows();
#
# Test some error conditions with UNION
@@ -73,6 +73,19 @@ replace into t3 select a,b as c from t1 union all select a,b from t2;
drop table t1,t2,t3;
#
+# Test some unions without tables
+#
+--error 1096
+select * union select 1;
+select 1 as a,(select a union select a);
+--error 1054
+(select 1) union (select 2) order by 0;
+SELECT @a:=1 UNION SELECT @a:=@a+1;
+--error 1054
+(SELECT 1) UNION (SELECT 2) ORDER BY (SELECT a);
+(SELECT 1,3) UNION (SELECT 2,1) ORDER BY (SELECT 2);
+
+#
# Test bug reported by joc@presence-pc.com
#
@@ -104,12 +117,67 @@ set SQL_SELECT_LIMIT=2;
set SQL_SELECT_LIMIT=DEFAULT;
drop table t1,t2;
---error 1096
-select * union select 1;
-select 1 as a,(select a union select a);
---disable_warnings
-drop table if exists t1,t2;
---enable_warnings
+#
+# Test error with left join
+#
+
+CREATE TABLE t1 (
+ cid smallint(5) unsigned NOT NULL default '0',
+ cv varchar(250) NOT NULL default '',
+ PRIMARY KEY (cid),
+ UNIQUE KEY cv (cv)
+) ;
+INSERT INTO t1 VALUES (8,'dummy');
+CREATE TABLE t2 (
+ cid bigint(20) unsigned NOT NULL auto_increment,
+ cap varchar(255) NOT NULL default '',
+ PRIMARY KEY (cid),
+ KEY cap (cap)
+) ;
+CREATE TABLE t3 (
+ gid bigint(20) unsigned NOT NULL auto_increment,
+ gn varchar(255) NOT NULL default '',
+ must tinyint(4) default NULL,
+ PRIMARY KEY (gid),
+ KEY gn (gn)
+) ;
+INSERT INTO t3 VALUES (1,'V1',NULL);
+CREATE TABLE t4 (
+ uid bigint(20) unsigned NOT NULL default '0',
+ gid bigint(20) unsigned default NULL,
+ rid bigint(20) unsigned default NULL,
+ cid bigint(20) unsigned default NULL,
+ UNIQUE KEY m (uid,gid,rid,cid),
+ KEY uid (uid),
+ KEY rid (rid),
+ KEY cid (cid),
+ KEY container (gid,rid,cid)
+) ;
+INSERT INTO t4 VALUES (1,1,NULL,NULL);
+CREATE TABLE t5 (
+ rid bigint(20) unsigned NOT NULL auto_increment,
+ rl varchar(255) NOT NULL default '',
+ PRIMARY KEY (rid),
+ KEY rl (rl)
+) ;
+CREATE TABLE t6 (
+ uid bigint(20) unsigned NOT NULL auto_increment,
+ un varchar(250) NOT NULL default '',
+ uc smallint(5) unsigned NOT NULL default '0',
+ PRIMARY KEY (uid),
+ UNIQUE KEY nc (un,uc),
+ KEY un (un)
+) ;
+INSERT INTO t6 VALUES (1,'test',8);
+
+SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test";
+SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t3.must IS NOT NULL AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test";
+(SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t3.must IS NOT NULL AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test") UNION (SELECT t4.uid, t5.rl, t3.gn as g1, t4.cid, t4.gid as gg FROM t3, t6, t1, t4 left join t5 on t5.rid = t4.rid left join t2 on t2.cid = t4.cid WHERE t3.gid=t4.gid AND t6.uid = t4.uid AND t6.uc = t1.cid AND t1.cv = "dummy" AND t6.un = "test");
+drop table t1,t2,t3,t4,t5,t6;
+
+#
+# Test for another bug with UNION and LEFT JOIN
+#
CREATE TABLE t1 ( id int(3) unsigned default '0') TYPE=MyISAM;
INSERT INTO t1 (id) VALUES("1");
CREATE TABLE t2 ( id int(3) unsigned default '0', id_master int(5) default '0', text1 varchar(5) default NULL, text2 varchar(5) default NULL) TYPE=MyISAM;
@@ -124,7 +192,6 @@ INSERT INTO t2 (id, id_master, text1, text2) VALUES("4", "1",
SELECT 1 AS id_master, 1 AS id, NULL AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master;
SELECT 1 AS id_master, 1 AS id, 'ABCDE' AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master;
drop table if exists t1,t2;
-(SELECT 1,3) UNION (SELECT 2,1) ORDER BY (SELECT 2);
#
# Test of bug when using the same table multiple times
@@ -142,9 +209,3 @@ explain (select * from t1 where a=1) union (select * from t2 where a=1);
explain (select * from t1 where a=1 and b=10) union (select t1.a,t2.a from t1,t2 where t1.a=t2.a);
explain (select * from t1 where a=1) union (select * from t1 where b=1);
drop table t1,t2;
---error 1054
-(select 1) union (select 2) order by 0;
-
-SELECT @a:=1 UNION SELECT @a:=@a+1;
---error 1054
-(SELECT 1) UNION (SELECT 2) ORDER BY (SELECT a);
diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test
index 6a7eac41a96..485af981fb4 100644
--- a/mysql-test/t/update.test
+++ b/mysql-test/t/update.test
@@ -84,12 +84,48 @@ drop table t1;
# Test of ORDER BY
#
-create table t1 (a int not null, b int not null);
-insert into t1 values (1,1),(1,2),(1,3);
-update t1 set b=4 where a=1 order by b asc limit 1;
-update t1 set b=4 where a=1 order by b desc limit 1;
+create table t1 (a int not null, b int not null, key (a));
+insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3);
+SET @tmp=0;
+update t1 set b=(@tmp:=@tmp+1) order by a;
+update t1 set b=99 where a=1 order by b asc limit 1;
+select * from t1 order by a,b;
+update t1 set b=100 where a=1 order by b desc limit 2;
+update t1 set a=a+10+b where a=1 order by b;
+select * from t1 order by a,b;
create table t2 (a int not null, b int not null);
insert into t2 values (1,1),(1,2),(1,3);
-select * from t1;
update t1 set b=(select distinct 1 from (select * from t2) a);
drop table t1,t2;
+
+#
+# Test with limit (Bug #393)
+#
+
+CREATE TABLE t1 (
+ `id_param` smallint(3) unsigned NOT NULL default '0',
+ `nom_option` char(40) NOT NULL default '',
+ `valid` tinyint(1) NOT NULL default '0',
+ KEY `id_param` (`id_param`,`nom_option`)
+ ) TYPE=MyISAM;
+
+INSERT INTO t1 (id_param,nom_option,valid) VALUES (185,'600x1200',1);
+
+UPDATE t1 SET nom_option='test' WHERE id_param=185 AND nom_option='600x1200' AND valid=1 LIMIT 1;
+select * from t1;
+drop table t1;
+
+#
+# Multi table update test from bugs
+#
+
+create table t1 (F1 VARCHAR(30), F2 VARCHAR(30), F3 VARCHAR(30), cnt int, groupid int, KEY groupid_index (groupid));
+
+insert into t1 (F1,F2,F3,cnt,groupid) values ('0','0','0',1,6),
+('0','1','2',1,5), ('0','2','0',1,3), ('1','0','1',1,2),
+('1','2','1',1,1), ('1','2','2',1,1), ('2','0','1',2,4),
+('2','2','0',1,7);
+
+delete from t1 using t1 m1,t1 m2 where m1.groupid=m2.groupid and (m1.cnt < m2.cnt or m1.cnt=m2.cnt and m1.F3>m2.F3);
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index d1c8df64be2..4f244311a59 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -72,10 +72,10 @@ show local variables like 'table_type';
show global variables like 'table_type';
set GLOBAL query_cache_size=100000;
-set myisam_max_sort_file_size=10000, GLOBAL myisam_max_sort_file_size=20000;
-show variables like 'myisam_max_sort_file_size';
+set GLOBAL myisam_max_sort_file_size=2000000;
show global variables like 'myisam_max_sort_file_size';
-set myisam_max_sort_file_size=default;
+set GLOBAL myisam_max_sort_file_size=default;
+--replace_result 2147483647 FILE_SIZE 9223372036854775807 FILE_SIZE
show variables like 'myisam_max_sort_file_size';
set global net_retry_count=10, session net_retry_count=10;
@@ -132,6 +132,10 @@ set @@concurrent_insert=1;
set @@global.sql_auto_is_null=1;
--error 1228
select @@global.sql_auto_is_null;
+--error 1229
+set myisam_max_sort_file_size=100;
+--error 1229
+set myisam_max_extra_sort_file_size=100;
# Test setting all variables
@@ -176,9 +180,9 @@ set max_tmp_tables=100;
set global max_user_connections=100;
select @@max_user_connections;
set global max_write_lock_count=100;
-set myisam_max_extra_sort_file_size=100;
+set global myisam_max_extra_sort_file_size=100;
select @@myisam_max_extra_sort_file_size;
-set myisam_max_sort_file_size=100;
+set global myisam_max_sort_file_size=100;
set myisam_sort_buffer_size=100;
set net_buffer_length=100;
set net_read_timeout=100;
@@ -236,3 +240,10 @@ check table t1,t2;
select max(a) +1, max(a) +2 into @xx,@yy from t1;
drop table t1,t2;
+#
+# error conditions
+#
+
+--error 1193
+select @@xxxxxxxxxx;
+select 1;
diff --git a/mysys/default.c b/mysys/default.c
index 9fedfd795a5..17ee1b8c8da 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -251,7 +251,13 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(0)))
return 0;
- if (stat_info.st_mode & S_IWOTH) /* ignore world-writeable files */
+ /*
+ Ignore world-writable regular files.
+ This is mainly done to protect us to not read a file created by
+ the mysqld server, but the check is still valid in most context.
+ */
+ if ((stat_info.st_mode & S_IWOTH) &&
+ (stat_info.st_mode & S_IFMT) == S_IFREG)
{
fprintf(stderr, "warning: World-writeable config file %s is ignored\n",
name);
diff --git a/mysys/mf_path.c b/mysys/mf_path.c
index 23eadd2acce..1ecd5fbb2b1 100644
--- a/mysys/mf_path.c
+++ b/mysys/mf_path.c
@@ -77,6 +77,9 @@ my_string my_path(my_string to, const char *progname,
#define F_OK 0
#define PATH_SEP ';'
#define PROGRAM_EXTENSION ".exe"
+#elif defined(__NETWARE__)
+#define PATH_SEP ';'
+#define PROGRAM_EXTENSION ".nlm"
#else
#define PATH_SEP ':'
#endif
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
index 0ff487afe03..55dd72f5f76 100644
--- a/mysys/my_bit.c
+++ b/mysys/my_bit.c
@@ -29,3 +29,45 @@ uint my_bit_log2(ulong value)
for (bit=0 ; value > 1 ; value>>=1, bit++) ;
return bit;
}
+
+static char nbits[256] = {
+ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+ 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
+};
+
+uint my_count_bits(ulonglong v)
+{
+#if SIZEOF_LONG_LONG > 4
+ /* The following code is a bit faster on 16 bit machines than if we would
+ only shift v */
+ ulong v2=(ulong) (v >> 32);
+ return (uint) (uchar) (nbits[(uchar) v] +
+ nbits[(uchar) (v >> 8)] +
+ nbits[(uchar) (v >> 16)] +
+ nbits[(uchar) (v >> 24)] +
+ nbits[(uchar) (v2)] +
+ nbits[(uchar) (v2 >> 8)] +
+ nbits[(uchar) (v2 >> 16)] +
+ nbits[(uchar) (v2 >> 24)]);
+#else
+ return (uint) (uchar) (nbits[(uchar) v] +
+ nbits[(uchar) (v >> 8)] +
+ nbits[(uchar) (v >> 16)] +
+ nbits[(uchar) (v >> 24)]);
+#endif
+}
+
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index 1eb15d92bc9..4f472f61593 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -90,6 +90,29 @@ void *my_pthread_getspecific_imp(pthread_key_t key)
}
#endif
+#ifdef __NETWARE__
+/*
+don't kill the LibC Reaper thread or the main thread
+*/
+#include <nks/thread.h>
+#undef pthread_exit
+void my_pthread_exit(void *status)
+{
+ NXThreadId_t tid = NXThreadGetId();
+ NXContext_t ctx;
+ char name[PATH_MAX] = "";
+
+ NXThreadGetContext(tid, &ctx);
+ NXContextGetName(ctx, name, PATH_MAX);
+
+ // "MYSQLD.NLM's LibC Reaper" or "MYSQLD.NLM's main thread"
+ // with a debug build of LibC the reaper can have different names
+ if (!strindex(name, "\'s"))
+ {
+ pthread_exit(status);
+ }
+}
+#endif
/* Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7
(and DEC OSF/1 3.2 too) */
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index 177a5cee953..ec24a26b3d9 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -15,6 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
+#include <assert.h>
/* Seek to position in file */
/*ARGSUSED*/
@@ -27,6 +28,8 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d",
fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos,
whence, MyFlags));
+ DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */
+
newpos=lseek(fd, pos, whence);
if (newpos == (os_off_t) -1)
{
diff --git a/mysys/my_semaphore.c b/mysys/my_semaphore.c
index 2dd224cd99e..aa216cbc289 100644
--- a/mysys/my_semaphore.c
+++ b/mysys/my_semaphore.c
@@ -23,7 +23,7 @@
#include <my_semaphore.h>
#include <errno.h>
-#if !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H)
+#if !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) && defined(THREAD)
int sem_init(sem_t * sem, int pshared, uint value)
{
@@ -101,4 +101,4 @@ int sem_getvalue(sem_t * sem, uint *sval)
return 0;
}
-#endif /* !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) */
+#endif /* !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H) && defined(THREAD) */
diff --git a/mysys/raid.cc b/mysys/raid.cc
index d6359dc0f93..0b688464fb3 100644
--- a/mysys/raid.cc
+++ b/mysys/raid.cc
@@ -157,10 +157,10 @@ extern "C" {
DBUG_PRINT("enter",("Fd: %d pos: %lu whence: %d MyFlags: %d",
fd, (ulong) pos, whence, MyFlags));
- assert(pos != MY_FILEPOS_ERROR);
-
if (is_raid(fd))
{
+ assert(pos != MY_FILEPOS_ERROR);
+
RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**));
DBUG_RETURN(raid->Seek(pos,whence,MyFlags));
}
diff --git a/netware/BUILD/compile-AUTOTOOLS b/netware/BUILD/compile-AUTOTOOLS
index 0688ea5aaca..57213b1b3d0 100755
--- a/netware/BUILD/compile-AUTOTOOLS
+++ b/netware/BUILD/compile-AUTOTOOLS
@@ -1,5 +1,11 @@
#! /bin/sh
+# debug
+#set -x
+
+# stop on errors
+set -e
+
for package in . ./innobase
do
(cd $package
diff --git a/netware/BUILD/compile-linux-tools b/netware/BUILD/compile-linux-tools
index 598be96ab66..3590a900338 100755
--- a/netware/BUILD/compile-linux-tools
+++ b/netware/BUILD/compile-linux-tools
@@ -1,8 +1,11 @@
#! /bin/sh
-#debug
+# debug
#set -x
+# stop on errors
+set -e
+
if test ! -r ./sql/mysqld.cc
then
echo "you must start from the top source directory"
diff --git a/netware/BUILD/compile-netware-END b/netware/BUILD/compile-netware-END
index beb15fbeda3..e0097484500 100755
--- a/netware/BUILD/compile-netware-END
+++ b/netware/BUILD/compile-netware-END
@@ -1,5 +1,11 @@
#! /bin/sh
+# debug
+#set -x
+
+# stop on errors
+set -e
+
path=`dirname $0`
# clean
diff --git a/netware/BUILD/compile-netware-START b/netware/BUILD/compile-netware-START
index 2941d8868e4..7eef192a907 100755
--- a/netware/BUILD/compile-netware-START
+++ b/netware/BUILD/compile-netware-START
@@ -1,8 +1,11 @@
#! /bin/sh
-#debug
+# debug
#set -x
+# stop on errors
+set -e
+
if test ! -r ./sql/mysqld.cc
then
echo "you must start from the top source directory"
diff --git a/netware/BUILD/compile-netware-all b/netware/BUILD/compile-netware-all
index f8dea0f7583..35d275f3b42 100755
--- a/netware/BUILD/compile-netware-all
+++ b/netware/BUILD/compile-netware-all
@@ -1,5 +1,11 @@
#! /bin/sh
+# debug
+#set -x
+
+# stop on errors
+set -e
+
path=`dirname $0`
$path/compile-netware-standard
diff --git a/netware/BUILD/compile-netware-debug b/netware/BUILD/compile-netware-debug
index 2cd292c82fd..e44d64e3074 100755
--- a/netware/BUILD/compile-netware-debug
+++ b/netware/BUILD/compile-netware-debug
@@ -1,5 +1,11 @@
#! /bin/sh
+# debug
+#set -x
+
+# stop on errors
+set -e
+
path=`dirname $0`
. $path/compile-netware-START
diff --git a/netware/BUILD/compile-netware-standard b/netware/BUILD/compile-netware-standard
index c09337b5fe0..12cae1f024e 100755
--- a/netware/BUILD/compile-netware-standard
+++ b/netware/BUILD/compile-netware-standard
@@ -1,5 +1,12 @@
#! /bin/sh
+# debug
+#set -x
+
+# stop on errors
+set -e
+
+
path=`dirname $0`
. $path/compile-netware-START
diff --git a/netware/BUILD/cron-build b/netware/BUILD/cron-build
new file mode 100755
index 00000000000..26ccde28e2a
--- /dev/null
+++ b/netware/BUILD/cron-build
@@ -0,0 +1,46 @@
+#! /bin/sh
+
+# debug
+#set -x
+
+# stop on errors
+set -e
+
+# repository direcotry
+repo_dir=`pwd`
+
+# show usage
+show_usage()
+{
+ cat << EOF
+
+usage: cron-patch
+
+EOF
+ exit 0;
+}
+
+echo "starting build..."
+
+# check for bk and repo_dir
+bk help > /dev/null
+repo_dir=`bk root $repo_dir`
+cd $repo_dir
+
+# pull latest code
+echo 'y' | bk pull
+
+# determine version
+version=`grep -e "AM_INIT_AUTOMAKE(mysql, .*)" < configure.in | sed -e "s/AM_INIT_AUTOMAKE(mysql, \(.*\))/\1/"`
+echo "version: $version"
+
+# latest revision
+rev=`bk changes -e -n -d':REV:' | head -1`
+echo "latest revision: $rev"
+
+# run bootstrap
+./netware/BUILD/nwbootstrap --revision=$rev --suffix=$rev --build=all
+
+echo "done"
+
+
diff --git a/netware/BUILD/crontab b/netware/BUILD/crontab
new file mode 100755
index 00000000000..0097f8acaaf
--- /dev/null
+++ b/netware/BUILD/crontab
@@ -0,0 +1,4 @@
+00 23 * * * (export PATH='/usr/local/bin:/usr/bin:/bin'; export DISPLAY=':0'; cd ~/bk/mysqldoc; echo 'y' | bk pull)
+00 00 * * * (export PATH='/usr/local/bin:/usr/bin:/bin'; export DISPLAY=':0'; cd ~/bk/mysql-4.0; ./netware/BUILD/cron-build)
+00 04 * * * (export PATH='/usr/local/bin:/usr/bin:/bin'; export DISPLAY=':0'; cd ~/bk/mysql-4.1; ./netware/BUILD/cron-build)
+
diff --git a/netware/BUILD/mwasmnlm b/netware/BUILD/mwasmnlm
index c3501112aa5..381f84ec0c8 100755
--- a/netware/BUILD/mwasmnlm
+++ b/netware/BUILD/mwasmnlm
@@ -1,5 +1,8 @@
#! /bin/sh
+# stop on errors
+set -e
+
args=" $*"
wine --debugmsg -all -- mwasmnlm $args
diff --git a/netware/BUILD/mwccnlm b/netware/BUILD/mwccnlm
index 9e989485bd9..cb2d62fe8cf 100755
--- a/netware/BUILD/mwccnlm
+++ b/netware/BUILD/mwccnlm
@@ -1,5 +1,8 @@
#! /bin/sh
+# stop on errors
+set -e
+
# mwccnlm is having a hard time understanding "-I./../include"
# convert it to "-I../include"
args=" "`echo $* | sed -e 's/-I.\/../-I../g'`
diff --git a/netware/BUILD/mwldnlm b/netware/BUILD/mwldnlm
index 7ad2872ccbb..28566fc5cb1 100755
--- a/netware/BUILD/mwldnlm
+++ b/netware/BUILD/mwldnlm
@@ -1,5 +1,8 @@
#! /bin/sh
+# stop on errors
+set -e
+
args=" $*"
wine --debugmsg -all -- mwldnlm $args
diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap
index 002e19c8e49..5d068e4e4de 100755
--- a/netware/BUILD/nwbootstrap
+++ b/netware/BUILD/nwbootstrap
@@ -3,11 +3,11 @@
# debug
#set -x
-path=`dirname $0`
-
# stop on errors
set -e
+path=`dirname $0`
+
# repository direcotry
repo_dir=`pwd`
@@ -24,6 +24,7 @@ temp_dir=""
revision=""
rev=""
build=""
+suffix=""
mwenv=""
# show usage
@@ -81,6 +82,7 @@ for arg do
--wine-build-dir=*) wine_build_dir=`echo "$arg" | sed -e "s;--wine-build-dir=;;"` ;;
--revision=*) revision=`echo "$arg" | sed -e "s;--revision=;;"` ;;
--build=*) build=`echo "$arg" | sed -e "s;--build=;;"` ;;
+ --suffix=*) suffix=`echo "$arg" | sed -e "s;--suffix=;;"` ;;
--doc-dir=*) doc_dir=`echo "$arg" | sed -e "s;--doc-dir=;;"` ;;
*) show_usage ;;
esac
@@ -111,6 +113,12 @@ echo "version: $version"
# build target directory
target_dir="$build_dir/mysql-$version"
+# add suffix
+if test $suffix
+then
+ target_dir="$target_dir-$suffix"
+fi
+
# delete any old target
if test -d $target_dir.old; then rm -rf $target_dir.old; fi
diff --git a/repl-tests/README b/repl-tests/README
deleted file mode 100644
index 95611c6538d..00000000000
--- a/repl-tests/README
+++ /dev/null
@@ -1,12 +0,0 @@
-This directory contains a set of test cases for replication. To get it
-to work on your system, install this version of MySQL on the master and on
-the slave, configure them according to the Replication HOWTO in the manual,
-modify include/master-slave.inc to specify correct connection parameters
-for the master and the slave and do
-
-sh run-all-tests
-
-If you would like to add your own test case, create a directory
-test-your-test-case-name, write your own run.test following the examples
-in the other test cases. Note that you can create the files containing
-the expected output ( master files) by running mysqltest --record < run.test \ No newline at end of file
diff --git a/repl-tests/include/master-slave.inc b/repl-tests/include/master-slave.inc
deleted file mode 100644
index ad2dea1f520..00000000000
--- a/repl-tests/include/master-slave.inc
+++ /dev/null
@@ -1,2 +0,0 @@
-connect (slave,localhost,root,,test,0,/var/lib/mysql/mysql.sock);
-connect (master,sarochka,admin,,test,0,0);
diff --git a/repl-tests/run-all-tests b/repl-tests/run-all-tests
deleted file mode 100755
index d9f08d8a8fb..00000000000
--- a/repl-tests/run-all-tests
+++ /dev/null
@@ -1,9 +0,0 @@
-#! /bin/sh
-
-for d in test-*; do
-cd $d
-echo -n $d | sed -e s/test-//
-echo -n "...."
-../../client/mysqltest $@ < run.test
-cd ..
-done \ No newline at end of file
diff --git a/repl-tests/test-auto-inc/run.test b/repl-tests/test-auto-inc/run.test
deleted file mode 100755
index 8405329f458..00000000000
--- a/repl-tests/test-auto-inc/run.test
+++ /dev/null
@@ -1,10 +0,0 @@
-source ../include/master-slave.inc;
-connection master;
-drop table if exists x;
-create table x(n int auto_increment primary key);
-set insert_id = 2000;
-insert into x values (NULL),(NULL),(NULL);
-connection slave;
-sleep 3;
-@x.master select * from x;
-
diff --git a/repl-tests/test-auto-inc/x.master b/repl-tests/test-auto-inc/x.master
deleted file mode 100644
index c76fc46ae97..00000000000
--- a/repl-tests/test-auto-inc/x.master
+++ /dev/null
@@ -1,4 +0,0 @@
-n
-2000
-2001
-2002
diff --git a/repl-tests/test-bad-query/run.test b/repl-tests/test-bad-query/run.test
deleted file mode 100755
index a86aaf84096..00000000000
--- a/repl-tests/test-bad-query/run.test
+++ /dev/null
@@ -1,10 +0,0 @@
-source ../include/master-slave.inc;
-connection master;
-drop table if exists x;
-create table x(n int primary key);
-!insert into x values (1),(2),(2);
-insert into x values (3);
-connection slave;
-sleep 3;
-@x.master select * from x;
-
diff --git a/repl-tests/test-bad-query/x.master b/repl-tests/test-bad-query/x.master
deleted file mode 100644
index c62967af0bb..00000000000
--- a/repl-tests/test-bad-query/x.master
+++ /dev/null
@@ -1,4 +0,0 @@
-n
-1
-2
-3
diff --git a/repl-tests/test-dump/run.test b/repl-tests/test-dump/run.test
deleted file mode 100644
index c714186a67b..00000000000
--- a/repl-tests/test-dump/run.test
+++ /dev/null
@@ -1,25 +0,0 @@
-source ../include/master-slave.inc;
-connection slave;
-!slave stop;
-flush slave;
-connection master;
-flush master;
-connection slave;
-slave start;
-connection master;
-use test;
-drop table if exists words;
-create table words (word char(20) not null, index(word));
-load data infile '/usr/dict/words' into table words;
-drop table if exists words1;
-create table words1 (word char(20) not null);
-load data infile '/usr/dict/words' into table words1;
-sleep 20;
-connection slave;
-use test;
-drop table if exists words;
-load table words from master;
-drop table if exists words1;
-load table words1 from master;
-@table-dump-check.master check table words;
-@table-dump-select.master select count(*) from words1;
diff --git a/repl-tests/test-dump/table-dump-check.master b/repl-tests/test-dump/table-dump-check.master
deleted file mode 100644
index 4061fdb4a0d..00000000000
--- a/repl-tests/test-dump/table-dump-check.master
+++ /dev/null
@@ -1,2 +0,0 @@
-Table Op Msg_type Msg_text
-test.words check status OK
diff --git a/repl-tests/test-dump/table-dump-select.master b/repl-tests/test-dump/table-dump-select.master
deleted file mode 100644
index ae93d31c066..00000000000
--- a/repl-tests/test-dump/table-dump-select.master
+++ /dev/null
@@ -1,2 +0,0 @@
-count(*)
-45402
diff --git a/repl-tests/test-repl-alter/run.test b/repl-tests/test-repl-alter/run.test
deleted file mode 100644
index 2e031010d5c..00000000000
--- a/repl-tests/test-repl-alter/run.test
+++ /dev/null
@@ -1,12 +0,0 @@
-source ../include/master-slave.inc;
-connection master;
-drop table if exists test;
-CREATE TABLE test (name varchar(64), age smallint(3));
-INSERT INTO test SET name='Andy', age=31;
-INSERT test SET name='Jacob', age=2;
-INSERT into test SET name='Caleb', age=1;
-ALTER TABLE test ADD id int(8) ZEROFILL AUTO_INCREMENT PRIMARY KEY;
-@test.master select * from test;
-connection slave;
-sleep 3;
-@test.master select * from test;
diff --git a/repl-tests/test-repl-alter/test.master b/repl-tests/test-repl-alter/test.master
deleted file mode 100644
index 763154b938e..00000000000
--- a/repl-tests/test-repl-alter/test.master
+++ /dev/null
@@ -1,4 +0,0 @@
-name age id
-Andy 31 00000001
-Jacob 2 00000002
-Caleb 1 00000003
diff --git a/repl-tests/test-repl-ts/repl-timestamp.master b/repl-tests/test-repl-ts/repl-timestamp.master
deleted file mode 100644
index c3e4a2326d0..00000000000
--- a/repl-tests/test-repl-ts/repl-timestamp.master
+++ /dev/null
@@ -1,2 +0,0 @@
-unix_timestamp(t)
-200006
diff --git a/repl-tests/test-repl-ts/repl-timestamp.master.reject b/repl-tests/test-repl-ts/repl-timestamp.master.reject
deleted file mode 100644
index 091b18351ed..00000000000
--- a/repl-tests/test-repl-ts/repl-timestamp.master.reject
+++ /dev/null
@@ -1,2 +0,0 @@
-unix_timestamp(t)
-973999074
diff --git a/repl-tests/test-repl-ts/run.test b/repl-tests/test-repl-ts/run.test
deleted file mode 100644
index 0a5224ce02a..00000000000
--- a/repl-tests/test-repl-ts/run.test
+++ /dev/null
@@ -1,17 +0,0 @@
-#! ../client/mysqltest
-# tests if the replicaion preserves timestamp properly
-
-source ../include/master-slave.inc;
-connection master;
-set timestamp=200006;
-drop table if exists foo;
-create table foo(t timestamp not null,a char(1));
-insert into foo ( a) values ('F');
-@repl-timestamp.master select unix_timestamp(t) from foo;
-sleep 3;
-connection slave;
-drop table if exists foo;
-load table foo from master;
-@repl-timestamp.master select unix_timestamp(t) from foo;
-
-
diff --git a/repl-tests/test-repl/foo-dump-master.master b/repl-tests/test-repl/foo-dump-master.master
deleted file mode 100644
index 982e0523cfb..00000000000
--- a/repl-tests/test-repl/foo-dump-master.master
+++ /dev/null
@@ -1,3 +0,0 @@
-n
-1
-2
diff --git a/repl-tests/test-repl/foo-dump-slave.master b/repl-tests/test-repl/foo-dump-slave.master
deleted file mode 100644
index 982e0523cfb..00000000000
--- a/repl-tests/test-repl/foo-dump-slave.master
+++ /dev/null
@@ -1,3 +0,0 @@
-n
-1
-2
diff --git a/repl-tests/test-repl/run.test b/repl-tests/test-repl/run.test
deleted file mode 100755
index cc93d964efa..00000000000
--- a/repl-tests/test-repl/run.test
+++ /dev/null
@@ -1,24 +0,0 @@
-source ../include/master-slave.inc;
-connection slave;
-!slave stop;
-connection master;
-flush master;
-connection slave;
-flush slave;
-!slave start;
-sleep 3;
-connection master;
-use test;
-drop table if exists words;
-create table words (word char(20) not null, index(word));
-load data infile '/usr/dict/words' into table words;
-drop table if exists foo;
-create table foo(n int);
-insert into foo values(1),(2);
-@foo-dump-master.master select * from foo;
-@sum-wlen-master.master select sum(length(word)) from words;
-connection slave;
-sleep 15;
-use test;
-@sum-wlen-slave.master select sum(length(word)) from words;
-@foo-dump-slave.master select * from foo;
diff --git a/repl-tests/test-repl/sum-wlen-master.master b/repl-tests/test-repl/sum-wlen-master.master
deleted file mode 100644
index e749ab4840a..00000000000
--- a/repl-tests/test-repl/sum-wlen-master.master
+++ /dev/null
@@ -1,2 +0,0 @@
-sum(length(word))
-363634
diff --git a/repl-tests/test-repl/sum-wlen-slave.master b/repl-tests/test-repl/sum-wlen-slave.master
deleted file mode 100644
index e749ab4840a..00000000000
--- a/repl-tests/test-repl/sum-wlen-slave.master
+++ /dev/null
@@ -1,2 +0,0 @@
-sum(length(word))
-363634
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 83ee5023b89..05d6f3ffb71 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -1,14 +1,5 @@
#!/bin/sh
-echo "This scripts updates the mysql.user, mysql.db, mysql.host and the"
-echo "mysql.func tables to MySQL 3.22.14 and above."
-echo ""
-echo "This is needed if you want to use the new GRANT functions,"
-echo "CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23"
-echo ""
-echo "If you get 'Access denied' errors, you should run this script again"
-echo "and give the MySQL root user password as an argument!"
-
root_password="$1"
host="localhost"
user="root"
@@ -20,6 +11,21 @@ else
cmd="@bindir@/mysql -f --user=$user --password=$root_password --host=$host mysql"
fi
+# Debian addition
+if [ "$1" = "--sql-only" ]; then
+ root_password=""
+ cmd="/usr/share/mysql/echo_stderr"
+fi
+
+echo "This scripts updates the mysql.user, mysql.db, mysql.host and the"
+echo "mysql.func tables to MySQL 3.22.14 and above."
+echo ""
+echo "This is needed if you want to use the new GRANT functions,"
+echo "CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23"
+echo ""
+echo "If you get 'Access denied' errors, you should run this script again"
+echo "and give the MySQL root user password as an argument!"
+
echo "Converting all privilege tables to MyISAM format"
$cmd <<END_OF_DATA
ALTER TABLE user type=MyISAM;
diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh
index 1a969895f7f..b5048054832 100644
--- a/scripts/mysql_install_db.sh
+++ b/scripts/mysql_install_db.sh
@@ -147,7 +147,8 @@ then
resolved=`$bindir/resolveip localhost 2>&1`
if [ $? -eq 0 ]
then
- echo "Sorry, the host '$hostname' could not be looked up."
+ echo "Neither host '$hostname' and 'localhost' could not be looked up with"
+ echo "$bindir/resolveip"
echo "Please configure the 'hostname' command to return a correct hostname."
echo "If you want to solve this at a later stage, restart this script with"
echo "the --force option"
@@ -164,14 +165,12 @@ fi
# Create database directories mysql & test
if test "$in_rpm" -eq 0 || "$windows" -eq 0
-then
if test ! -d $ldata; then mkdir $ldata; chmod 700 $ldata ; fi
if test ! -d $ldata/mysql; then mkdir $ldata/mysql; chmod 700 $ldata/mysql ; fi
if test ! -d $ldata/test; then mkdir $ldata/test; chmod 700 $ldata/test ; fi
if test -w / -a ! -z "$user"; then
chown $user $ldata $ldata/mysql $ldata/test;
fi
-fi
# Initialize variables
c_d="" i_d=""
diff --git a/scripts/mysql_setpermission.sh b/scripts/mysql_setpermission.sh
index 43bf8a14c06..9699cd28047 100644
--- a/scripts/mysql_setpermission.sh
+++ b/scripts/mysql_setpermission.sh
@@ -16,20 +16,25 @@
## 1.2 begin screen now in a loop + quit is using 0 instead of 9
## after ideas of Paul DuBois.
## 1.2a Add Grant, References, Index and Alter privilege handling (Monty)
+## 1.3 Applied patch provided by Martin Mokrejs <mmokrejs@natur.cuni.cz>
+## (General code cleanup, use the GRANT statement instead of updating
+## the privilege tables directly, added option to revoke privileges)
#### TODO
#
# empty ... suggestions ... mail them to me ...
-$version="1.2";
+$version="1.3";
use DBI;
use Getopt::Long;
use strict;
-use vars qw($dbh $hostname $opt_user $opt_password $opt_help $opt_host
+use vars qw($dbh $sth $hostname $opt_user $opt_password $opt_help $opt_host
$opt_socket $opt_port $host $version);
+my $sqlhost = "";
+my $user = "";
$dbh=$host=$opt_user= $opt_password= $opt_help= $opt_host= $opt_socket= "";
$opt_port=0;
@@ -42,11 +47,11 @@ usage() if ($opt_help); # the help function
if ($opt_host eq '')
{
- $hostname = "localhost";
+ $sqlhost = "localhost";
}
else
{
- $hostname = $opt_host;
+ $sqlhost = $opt_host;
}
# ask for a password if no password is set already
@@ -62,7 +67,7 @@ if ($opt_password eq '')
# make the connection to MySQL
-$dbh= DBI->connect("DBI:mysql:mysql:host=$hostname:port=$opt_port:mysql_socket=$opt_socket",$opt_user,$opt_password, {PrintError => 0}) ||
+$dbh= DBI->connect("DBI:mysql:mysql:host=$sqlhost:port=$opt_port:mysql_socket=$opt_socket",$opt_user,$opt_password, {PrintError => 0}) ||
die("Can't make a connection to the mysql server.\n The error: $DBI::errstr");
# the start of the program
@@ -86,27 +91,44 @@ sub q1 { # first question ...
print "#"x70;
print "\n";
print "What would you like to do:\n";
- print " 1. Set password for a user.\n";
- print " 2. Add a database + user privilege for that database.\n";
- print " - user can do all except all admin functions\n";
- print " 3. Add user privilege for an existing database.\n";
- print " - user can do all except all admin functions\n";
- print " 4. Add user privilege for an existing database.\n";
- print " - user can do all except all admin functions + no create/drop\n";
- print " 5. Add user privilege for an existing database.\n";
- print " - user can do only selects (no update/delete/insert etc.)\n";
+ print " 1. Set password for an existing user.\n";
+ print " 2. Create a database + user privilege for that database\n";
+ print " and host combination (user can only do SELECT)\n";
+ print " 3. Create/append user privilege for an existing database\n";
+ print " and host combination (user can only do SELECT)\n";
+ print " 4. Create/append broader user privileges for an existing\n";
+ print " database and host combination\n";
+ print " (user can do SELECT,INSERT,UPDATE,DELETE)\n";
+ print " 5. Create/append quite extended user privileges for an\n";
+ print " existing database and host combination (user can do\n";
+ print " SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,\n";
+ print " LOCK TABLES,CREATE TEMPORARY TABLES)\n";
+ print " 6. Create/append database administrative privileges for an\n";
+ print " existing database and host combination (user can do\n";
+ print " SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,\n";
+ print " CREATE TEMPORARY TABLES,SHOW DATABASES,PROCESS)\n";
+ print " 7. Create/append full privileges for an existing database\n";
+ print " and host combination (user has FULL privilege)\n";
+ print " 8. Remove all privileges for for an existing database and\n";
+ print " host combination.\n";
+ print " (user will have all permission fields set to N)\n";
print " 0. exit this program\n";
- print "\nMake your choice [1,2,3,4,5,0]: ";
+ print "\nMake your choice [1,2,3,4,5,6,7,0]: ";
while (<STDIN>) {
$answer = $_;
chomp($answer);
- if ($answer =~ /1|2|3|4|5|0/) {
- &setpwd if ($answer == 1);
- &addall($answer) if ($answer =~ /^[2345]$/);
- if ($answer == 0) {
- print "Sorry, hope we can help you next time \n\n";
+ if ($answer =~ /^[12345678]$/) {
+ if ($answer == 1) {
+ setpwd();
+ } elsif ($answer =~ /^[2345678]$/) {
+ addall($answer);
+ } else {
+ print "Sorry, something went wrong. With such option number you should not get here.\n\n";
$end = 1;
}
+ } elsif ($answer == 0) {
+ print "We hope we can help you next time \n\n";
+ $end = 1;
} else {
print "Your answer was $answer\n";
print "and that's wrong .... Try again\n";
@@ -121,7 +143,7 @@ sub q1 { # first question ...
###
sub setpwd
{
- my ($user,$pass,$host);
+ my ($user,$pass,$host) = "";
print "\n\nSetting a (new) password for a user.\n";
$user = user();
@@ -168,22 +190,18 @@ sub setpwd
###
# all things which will be added are done here
###
-sub addall
-{
+sub addall {
my ($todo) = @_;
my ($answer,$good,$db,$user,$pass,$host,$priv);
- if ($todo == 2)
- {
+ if ($todo == 2) {
$db = newdatabase();
- }
- else
- {
+ } else {
$db = database();
}
$user = newuser();
- $pass = newpass();
+ $pass = newpass("$user");
$host = newhosts();
print "#"x70;
@@ -198,104 +216,80 @@ sub addall
print "Are you pretty sure you would like to implement this [yes/no]: ";
my $no = <STDIN>;
chomp($no);
- if ($no =~ /n/i)
- {
+ if ($no =~ /n/i) {
print "Okay .. that was it then ... See ya\n\n";
return(0);
- }
- else
- {
+ } else {
print "Okay ... let's go then ...\n\n";
}
- if ($todo == 2)
- {
+ if ($todo == 2) {
# create the database
- my $sth = $dbh->do("create database $db") || $dbh->errstr;
- }
-
- # select the privilege ....
- if (($todo == 2) || ($todo == 3))
- {
- $priv = "'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y'";
+ if ($db) {
+ my $sth = $dbh->do("CREATE DATABASE $db") || $dbh->errstr;
+ } else {
+ print STDERR "What do you want? You wanted to create new database and add new user, right?\n";
+ die "But then specify databasename, please\n";
}
- elsif ($todo == 4)
- {
- $priv = "'Y','Y','Y','Y','N','N','N','Y','Y','Y'";
}
- elsif ($todo == 5)
- {
- $priv = "'Y','N','N','N','N','N','N','N','N','N'";
- }
- else
- {
- print "Sorry, choice number $todo isn't known inside the program .. See ya\n";
+
+ if ( ( !$todo ) or not ( $todo =~ m/^[2-8]$/ ) ) {
+ print STDERR "Sorry, select option $todo isn't known inside the program .. See ya\n";
quit();
}
my @hosts = split(/,/,$host);
- $user = $dbh->quote($user);
- $db = $dbh->quote($db);
- if ($pass eq '')
- {
- $pass = "''";
+ if (!$user) {
+ die "username not specified: $user\n";
}
- else
- {
- $pass = "PASSWORD(". $dbh->quote($pass) . ")";
+ if (!$db) {
+ die "databasename is not specified nor *\n";
}
- foreach my $key (@hosts)
- {
- my $key1 = $dbh->quote($key);
- my $sth = $dbh->prepare("select Host,User from user where Host = $key1 and User = $user") || die $dbh->errstr;
- $sth->execute || die $dbh->errstr;
- my @r = $sth->fetchrow_array;
- if ($r[0])
- {
- print "WARNING WARNING SKIPPING CREATE FOR USER $user AND HOST $key\n";
- print "Reason: entry already exists in the user table.\n";
+ foreach $host (@hosts) {
+ # user privileges: SELECT
+ if (($todo == 2) || ($todo == 3)) {
+ $sth = $dbh->do("GRANT SELECT ON $db.* TO $user@\"$host\" IDENTIFIED BY \'$pass\'") || die $dbh->errstr;
+ } elsif ($todo == 4) {
+ # user privileges: SELECT,INSERT,UPDATE,DELETE
+ $sth = $dbh->do("GRANT SELECT,INSERT,UPDATE,DELETE ON $db.* TO $user@\"$host\" IDENTIFIED BY \'$pass\'") || die $dbh->errstr;
+ } elsif ($todo == 5) {
+ # user privileges: SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES
+ $sth = $dbh->do("GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES ON $db.* TO $user@\"$host\" IDENTIFIED BY \'$pass\'") || die $dbh->errstr;
+ } elsif ($todo == 6) {
+ # admin privileges: GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES,SHOW DATABASES,PROCESS
+ $sth = $dbh->do("GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,LOCK TABLES,CREATE TEMPORARY TABLES,SHOW DATABASES,PROCESS ON $db.* TO $user@\"$host\" IDENTIFIED BY \'$pass\'") || die $dbh->errstr;
+ } elsif ($todo == 7) {
+ # all privileges
+ $sth = $dbh->do("GRANT ALL ON $db.* TO \'$user\'\@\'$host\' IDENTIFIED BY \'$pass\'") || die $dbh->errstr;
+ } elsif ($todo == 8) {
+ # all privileges set to N
+ $sth = $dbh->do("REVOKE ALL ON *.* FROM \'$user\'\@\'$host\'") || die $dbh->errstr;
}
- else
- {
- $sth = $dbh->prepare("insert into user (Host,User,Password) values($key1,$user,$pass)") || die $dbh->errstr;
- $sth->execute || die $dbh->errstr;
- $sth->finish;
}
- $sth = $dbh->prepare("INSERT INTO db (Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Grant_priv,References_priv,Index_priv,Alter_priv) VALUES ($key1,$db,$user,$priv)") || die $dbh->errstr;
- $sth->execute || die $dbh->errstr;
- $sth->finish;
- }
- $dbh->do("flush privileges") || print "Can't load privileges\n";
+ $dbh->do("FLUSH PRIVILEGES") || print STDERR "Can't flush privileges\n";
print "Everything is inserted and mysql privileges have been reloaded.\n\n";
}
###
# ask for a new database name
###
-sub newdatabase
-{
+sub newdatabase {
my ($answer,$good,$db);
print "\n\nWhich database would you like to add: ";
- while (<STDIN>)
- {
+ while (<STDIN>) {
$answer = $_;
$good = 0;
chomp($answer);
- if ($answer)
- {
- my $sth = $dbh->prepare("show databases") || die $dbh->errstr;
+ if ($answer) {
+ my $sth = $dbh->prepare("SHOW DATABASES") || die $dbh->errstr;
$sth->execute || die $dbh->errstr;
- while (my @r = $sth->fetchrow_array)
- {
- if ($r[0] eq $answer)
- {
+ while (my @r = $sth->fetchrow_array) {
+ if ($r[0] eq $answer) {
print "\n\nSorry, this database name is already in use; try something else: ";
$good = 1;
}
}
- }
- else
- {
+ } else {
print "You must type something ...\nTry again: ";
next;
}
@@ -309,48 +303,44 @@ sub newdatabase
###
# select a database
###
-sub database
-{
+sub database {
my ($answer,$good,$db);
- print "\n\nWhich database would you like to select: \n";
+ print "\n\nWhich database from existing databases would you like to select: \n";
print "You can choose from: \n";
my $sth = $dbh->prepare("show databases") || die $dbh->errstr;
$sth->execute || die $dbh->errstr;
- while (my @r = $sth->fetchrow_array)
- {
+ while (my @r = $sth->fetchrow_array) {
print " - $r[0] \n";
}
- print "Which database will it be (case sensitive): ";
- while (<STDIN>)
- {
+ print "Which database will it be (case sensitive). Type * for any: \n";
+ while (<STDIN>) {
$answer = $_;
$good = 0;
chomp($answer);
- if ($answer)
- {
+ if ($answer) {
+ if ($answer eq "*") {
+ print "OK, the user entry will NOT be limited to any database";
+ return("*");
+ }
my $sth = $dbh->prepare("show databases") || die $dbh->errstr;
$sth->execute || die $dbh->errstr;
- while (my @r = $sth->fetchrow_array)
- {
- if ($r[0] eq $answer)
- {
+ while (my @r = $sth->fetchrow_array) {
+ if ($r[0] eq $answer) {
$good = 1;
$db = $r[0];
last;
}
}
- }
- else
- {
- print "You must type something ...\nTry again: ";
+ } else {
+ print "Type either database name or * meaning any databasename. That means";
+ print " any of those above but also any which will be created in future!";
+ print " This option gives a user chance to operate on databse mysql, which";
+ print " contains privilege settings. That is really risky!\n";
next;
}
- if ($good == 1)
- {
+ if ($good == 1) {
last;
- }
- else
- {
+ } else {
print "You must select one from the list.\nTry again: ";
next;
}
@@ -364,7 +354,8 @@ sub database
###
sub newuser
{
- my ($answer,$user);
+ my $user = "";
+ my $answer = "";
print "\nWhat username is to be created: ";
while(<STDIN>)
@@ -430,7 +421,7 @@ sub user
sub newpass
{
my ($user) = @_;
- my ($answer,$good,$pass,$yes);
+ my ($pass,$answer,$good,$yes);
print "Would you like to set a password for $user [y/n]: ";
$yes = <STDIN>;
@@ -487,7 +478,7 @@ sub newpass
###
sub newhosts
{
- my ($answer,$good,$host);
+ my ($host,$answer,$good);
print "We now need to know from what host(s) the user will connect.\n";
print "Keep in mind that % means 'from any host' ...\n";
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index 094b1fbfcd3..e400c27b84c 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -224,7 +224,7 @@ then
if test -n "$open_files"
then
ulimit -n $open_files
- args="open-files-limit=$open_files $args"
+ 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 ec76aa479f3..a89a8919752 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -55,7 +55,8 @@ Usage: $0 db_name[./table_regex/] [new_db_name | directory]
-P, --port=# port to use when connecting to local server with TCP/IP
-S, --socket=# socket to use when connecting to local server
- --allowold don\'t abort if target already exists (rename it _old)
+ --allowold don\'t abort if target dir already exists (rename it _old)
+ --addtodest don\'t rename target dir if it exists, just add files to it
--keepold don\'t delete previous (now renamed) target when done
--noindices don\'t include full index files in copy
--method=# method for copy (only "cp" currently supported)
@@ -98,6 +99,7 @@ GetOptions( \%opt,
"socket|S=s",
"allowold!",
"keepold!",
+ "addtodest!",
"noindices!",
"method=s",
"debug",
@@ -380,14 +382,14 @@ if ($opt{method} =~ /^cp\b/)
push @existing, $rdb->{target} if ( -d $rdb->{target} );
}
- if ( @existing && !$opt{allowold} )
+ if ( @existing && !($opt{allowold} || $opt{addtodest}) )
{
$dbh->disconnect();
- die "Can't hotcopy to '", join( "','", @existing ), "' because directory\nalready exist and the --allowold option was not given.\n"
+ die "Can't hotcopy to '", join( "','", @existing ), "' because directory\nalready exist and the --allowold or --addtodest options were not given.\n"
}
}
-retire_directory( @existing ) if ( @existing );
+retire_directory( @existing ) if @existing && !$opt{addtodest};
foreach my $rdb ( @db_desc ) {
foreach my $td ( '', @{$rdb->{raid_dirs}} ) {
@@ -403,8 +405,8 @@ foreach my $rdb ( @db_desc ) {
## ...
}
else {
- mkdir($tgt_dirpath, 0750)
- or die "Can't create '$tgt_dirpath': $!\n";
+ mkdir($tgt_dirpath, 0750) or die "Can't create '$tgt_dirpath': $!\n"
+ unless -d $tgt_dirpath;
}
}
}
@@ -861,6 +863,22 @@ Any existing versions of the backup directory are deleted.
Behaves as for the --allowold, with the additional feature
of keeping the backup directory after the copy successfully completes.
+=item --addtodest
+
+Don't rename target directory if it already exists, just add the
+copied files into it.
+
+This is most useful when backing up a database with many large
+tables and you don't want to have all the tables locked for the
+whole duration.
+
+In this situation, I<if> you are happy for groups of tables to be
+backed up separately (and thus possibly not be logically consistant
+with one another) then you can run mysqlhotcopy several times on
+the same database each with different db_name./table_regex/.
+All but the first should use the --addtodest option so the tables
+all end up in the same directory.
+
=item --flushlog
Rotate the log files by executing "FLUSH LOGS" after all tables are
@@ -869,13 +887,13 @@ locked, and before they are copied.
=item --resetmaster
Reset the bin-log by executing "RESET MASTER" after all tables are
-locked, and before they are copied. Usefull if you are recovering a
+locked, and before they are copied. Useful if you are recovering a
slave in a replication setup.
=item --resetslave
Reset the master.info by executing "RESET SLAVE" after all tables are
-locked, and before they are copied. Usefull if you are recovering a
+locked, and before they are copied. Useful if you are recovering a
server in a mutual replication setup.
=item --regexp pattern
@@ -941,7 +959,7 @@ will vary with your ability to understand how scp works. 'man scp'
and 'man ssh' are your friends.
The destination directory _must exist_ on the target machine using the
-scp method. --keepold and --allowold are meeningless with scp.
+scp method. --keepold and --allowold are meaningless with scp.
Liberal use of the --debug option will help you figure out what\'s
really going on when you do an scp.
diff --git a/sql-bench/Makefile.am b/sql-bench/Makefile.am
index ab6be7269e3..579a2a9f7fe 100644
--- a/sql-bench/Makefile.am
+++ b/sql-bench/Makefile.am
@@ -41,12 +41,9 @@ EXTRA_DIST = $(EXTRA_SCRIPTS)
dist-hook:
mkdir -p $(distdir)/Data/ATIS $(distdir)/Data/Wisconsin \
- $(distdir)/Results $(distdir)/Results-win32 \
$(distdir)/limits $(distdir)/Comments
for i in $(srcdir)/Data/ATIS/*.* ; do $(INSTALL_DATA) $$i $(distdir)/Data/ATIS ; done
for i in $(srcdir)/Data/Wisconsin/*.* ; do $(INSTALL_DATA) $$i $(distdir)/Data/Wisconsin ; done
- for i in $(srcdir)/Results/*-* ; do $(INSTALL_DATA) $$i $(distdir)/Results; done
- for i in $(srcdir)/Results-win32/*-* ; do $(INSTALL_DATA) $$i $(distdir)/Results-win32; done
for i in $(srcdir)/limits/*.* ; do $(INSTALL_DATA) $$i $(distdir)/limits; done
for i in $(srcdir)/Comments/*.* ; do $(INSTALL_DATA) $$i $(distdir)/Comments; done
@@ -55,15 +52,11 @@ install-data-local:
$(DESTDIR)$(benchdir)/Data \
$(DESTDIR)$(benchdir)/Data/ATIS \
$(DESTDIR)$(benchdir)/Data/Wisconsin \
- $(DESTDIR)$(benchdir)/Results \
- $(DESTDIR)$(benchdir)/Results-win32 \
$(DESTDIR)$(benchdir)/limits \
$(DESTDIR)$(benchdir)/Comments
$(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(benchdir)
for i in $(srcdir)/Data/ATIS/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Data/ATIS ; done
for i in $(srcdir)/Data/Wisconsin/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Data/Wisconsin ; done
- for i in $(srcdir)/Results/*-* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Results; done
- for i in $(srcdir)/Results-win32/*-* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Results-win32; done
for i in $(srcdir)/limits/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/limits; done
for i in $(srcdir)/Comments/*.* ; do $(INSTALL_DATA) $$i $(DESTDIR)$(benchdir)/Comments; done
diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh
index 61468d69fb1..ff649acdae4 100644
--- a/sql-bench/crash-me.sh
+++ b/sql-bench/crash-me.sh
@@ -2734,6 +2734,51 @@ assert("drop table crash_me_n $drop_attr");
+$key = 'sorted_group_by';
+$prompt = 'Group by always sorted';
+if (!defined($limits{$key}))
+{
+ save_incomplete($key,$prompt);
+ print "$prompt=";
+ safe_query_l($key,[
+ "create table crash_me_t1 (a int not null, b int not null)",
+ "insert into crash_me_t1 values (1,1)",
+ "insert into crash_me_t1 values (1,2)",
+ "insert into crash_me_t1 values (3,1)",
+ "insert into crash_me_t1 values (3,2)",
+ "insert into crash_me_t1 values (2,2)",
+ "insert into crash_me_t1 values (2,1)",
+ "create table crash_me_t2 (a int not null, b int not null)",
+ "create index crash_me_t2_ind on crash_me_t2 (a)",
+ "insert into crash_me_t2 values (1,3)",
+ "insert into crash_me_t2 values (3,1)",
+ "insert into crash_me_t2 values (2,2)",
+ "insert into crash_me_t2 values (1,1)"]);
+
+ my $bigqry = "select crash_me_t1.a,crash_me_t2.b from ".
+ "crash_me_t1,crash_me_t2 where crash_me_t1.a=crash_me_t2.a ".
+ "group by crash_me_t1.a,crash_me_t2.b";
+
+ my $limit='no';
+ my $rs = get_recordset($key,$bigqry);
+ print_recordset($key,$rs);
+ if ( defined ($rs)) {
+ if (compare_recordset($key,$rs,[[1,1],[1,3],[2,2],[3,1]]) eq 0)
+ {
+ $limit='yes'
+ }
+ } else {
+ add_log($key,"error: ".$DBI::errstr);
+ }
+
+ print "$limit\n";
+ safe_query_l($key,["drop table crash_me_t1",
+ "drop table crash_me_t2"]);
+ save_config_data($key,$limit,$prompt);
+
+} else {
+ print "$prompt=$limits{$key} (cashed)\n";
+}
#
diff --git a/sql/field.cc b/sql/field.cc
index 3695268a888..d6f9797071b 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -161,6 +161,14 @@ static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
}
+static inline uint field_length_without_space(const char *ptr, uint length)
+{
+ const char *end= ptr+length;
+ while (end > ptr && end[-1] == ' ')
+ end--;
+ return (uint) (end-ptr);
+}
+
/****************************************************************************
** Functions for the base classes
** This is an unpacked number.
@@ -3604,11 +3612,11 @@ bool Field_newdate::get_date(TIME *ltime,bool fuzzydate)
if (is_null())
return 1;
uint32 tmp=(uint32) uint3korr(ptr);
- bzero((char*) ltime,sizeof(*ltime));
ltime->day= tmp & 31;
ltime->month= (tmp >> 5) & 15;
ltime->year= (tmp >> 9);
ltime->time_type=TIMESTAMP_DATE;
+ ltime->hour= ltime->minute= ltime->second= ltime->second_part= 0;
return (!fuzzydate && (!ltime->month || !ltime->day)) ? 1 : 0;
}
@@ -3969,9 +3977,23 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
int Field_string::cmp(const char *a_ptr, const char *b_ptr)
{
+#ifdef USE_STRCOLL
+ if (field_charset->mbmaxlen > 1)
+ {
+ /*
+ We have to remove end space to be able to compare multi-byte-characters
+ like in latin_de 'ae' and 0xe4
+ */
+ uint a_length= field_length_without_space(a_ptr, field_length);
+ uint b_length= field_length_without_space(b_ptr, field_length);
+ return my_strnncoll(field_charset,
+ (const uchar*) a_ptr, a_length,
+ (const uchar*) b_ptr, b_length);
+ }
+#endif
return my_strnncoll(field_charset,
- (const uchar*)a_ptr,field_length,
- (const uchar*)b_ptr,field_length);
+ (const uchar*) a_ptr, field_length,
+ (const uchar*) b_ptr, field_length);
}
void Field_string::sort_string(char *to,uint length)
diff --git a/sql/field.h b/sql/field.h
index 80bfc516ef7..2ee984e3a2a 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -134,6 +134,8 @@ public:
Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
if (tmp)
{
+ if (tmp->table->maybe_null)
+ tmp->flags&= ~NOT_NULL_FLAG;
tmp->table= new_table;
tmp->key_start= tmp->part_of_key= tmp->part_of_sortkey= 0;
tmp->unireg_check=Field::NONE;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index a3d24cd9242..68b8737bc79 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -494,6 +494,7 @@ static void make_sortkey(register SORTPARAM *param,
sort_field != param->end ;
sort_field++)
{
+ bool maybe_null=0;
if ((field=sort_field->field))
{ // Field
if (field->maybe_null())
@@ -519,7 +520,7 @@ static void make_sortkey(register SORTPARAM *param,
case STRING_RESULT:
{
CHARSET_INFO *cs=item->charset();
- if (item->maybe_null)
+ if ((maybe_null=item->maybe_null))
*to++=1;
/* All item->str() to use some extra byte for end null.. */
String tmp((char*) to,sort_field->length+4,cs);
@@ -567,7 +568,7 @@ static void make_sortkey(register SORTPARAM *param,
case INT_RESULT:
{
longlong value=item->val_int();
- if (item->maybe_null)
+ if ((maybe_null=item->maybe_null))
*to++=1; /* purecov: inspected */
if (item->null_value)
{
@@ -601,13 +602,13 @@ static void make_sortkey(register SORTPARAM *param,
case REAL_RESULT:
{
double value=item->val();
- if (item->null_value)
+ if ((maybe_null=item->null_value))
{
bzero((char*) to,sort_field->length+1);
to++;
break;
}
- if (item->maybe_null)
+ if ((maybe_null=item->maybe_null))
*to++=1;
change_double_for_sort(value,(byte*) to);
break;
@@ -621,6 +622,8 @@ static void make_sortkey(register SORTPARAM *param,
}
if (sort_field->reverse)
{ /* Revers key */
+ if (maybe_null)
+ to[-1]= ~to[-1];
length=sort_field->length;
while (length--)
{
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index fe874dab3f2..c369c7029b4 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -53,8 +53,9 @@ class ha_heap: public handler
uint max_keys() const { return MAX_KEY; }
uint max_key_parts() const { return MAX_REF_PARTS; }
uint max_key_length() const { return HA_MAX_REC_LENGTH; }
- virtual double scan_time() { return (double) (records+deleted) / 20.0+10; }
- virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; }
+ double scan_time() { return (double) (records+deleted) / 20.0+10; }
+ double read_time(uint index, uint ranges, ha_rows rows)
+ { return (double) rows / 20.0+1; }
virtual bool fast_key_read() { return 1;}
int open(const char *name, int mode, uint test_if_locked);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 4f955d8f79e..a426dc5a9a9 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -100,7 +100,7 @@ char* innobase_unix_file_flush_method = NULL;
/* Below we have boolean-valued start-up parameters, and their default
values */
-uint innobase_flush_log_at_trx_commit = 0;
+uint innobase_flush_log_at_trx_commit = 1;
my_bool innobase_log_archive = FALSE;
my_bool innobase_use_native_aio = FALSE;
my_bool innobase_fast_shutdown = TRUE;
@@ -242,6 +242,10 @@ convert_error_code_to_mysql(
return(HA_ERR_CANNOT_ADD_FOREIGN);
+ } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
+
+ return(HA_WRONG_CREATE_OPTION);
+
} else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
return(HA_ERR_CRASHED);
@@ -597,7 +601,7 @@ innobase_invalidate_query_cache(
Call this when you have opened a new table handle in HANDLER, before you
call index_read_idx() etc. Actually, we can let the cursor stay open even
over a transaction commit! Then you should call this before every operation,
-fecth next etc. This function inits the necessary things even after a
+fetch next etc. This function inits the necessary things even after a
transaction commit. */
void
@@ -644,6 +648,8 @@ ha_innobase::init_table_handle_for_HANDLER(void)
we???? */
prebuilt->read_just_key = FALSE;
+
+ prebuilt->used_in_HANDLER = TRUE;
}
/*************************************************************************
@@ -883,7 +889,7 @@ innobase_flush_logs(void)
DBUG_ENTER("innobase_flush_logs");
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
DBUG_RETURN(result);
}
@@ -932,7 +938,7 @@ Commits a transaction in an InnoDB database. */
int
innobase_commit(
/*============*/
- /* out: 0 or error number */
+ /* out: 0 */
THD* thd, /* in: MySQL thread handle of the user for whom
the transaction should be committed */
void* trx_handle)/* in: InnoDB trx handle or
@@ -940,7 +946,6 @@ innobase_commit(
that the current SQL statement ended, and we should
mark the start of a new statement with a savepoint */
{
- int error = 0;
trx_t* trx;
DBUG_ENTER("innobase_commit");
@@ -967,29 +972,27 @@ innobase_commit(
innobase_release_stat_resources(trx);
trx_mark_sql_stat_end(trx);
-#ifndef DBUG_OFF
- if (error) {
- DBUG_PRINT("error", ("error: %d", error));
- }
-#endif
/* Tell InnoDB server that there might be work for
utility threads: */
srv_active_wake_master_thread();
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
}
/*********************************************************************
This is called when MySQL writes the binlog entry for the current
transaction. Writes to the InnoDB tablespace info which tells where the
MySQL binlog entry for the current transaction ended. Also commits the
-transaction inside InnoDB. */
+transaction inside InnoDB but does NOT flush InnoDB log files to disk.
+To flush you have to call innobase_flush_log_to_disk. We have separated
+flushing to eliminate the bottleneck of LOCK_log in log.cc which disabled
+InnoDB's group commit capability. */
int
innobase_report_binlog_offset_and_commit(
/*=====================================*/
- /* out: 0 or error code */
+ /* out: 0 */
THD* thd, /* in: user thread */
void* trx_handle, /* in: InnoDB trx handle */
char* log_file_name, /* in: latest binlog file name */
@@ -1005,7 +1008,39 @@ innobase_report_binlog_offset_and_commit(
trx->mysql_log_file_name = log_file_name;
trx->mysql_log_offset = (ib_longlong)end_offset;
- return(innobase_commit(thd, trx_handle));
+ trx->flush_log_later = TRUE;
+
+ innobase_commit(thd, trx_handle);
+
+ trx->flush_log_later = FALSE;
+
+ return(0);
+}
+
+/*********************************************************************
+This is called after MySQL has written the binlog entry for the current
+transaction. Flushes the InnoDB log files to disk if required. */
+
+int
+innobase_commit_complete(
+/*=====================*/
+ /* out: 0 */
+ void* trx_handle) /* in: InnoDB trx handle */
+{
+ trx_t* trx;
+
+ if (srv_flush_log_at_trx_commit == 0) {
+
+ return(0);
+ }
+
+ trx = (trx_t*)trx_handle;
+
+ ut_a(trx != NULL);
+
+ trx_commit_complete_for_mysql(trx);
+
+ return(0);
}
/*********************************************************************
@@ -1195,6 +1230,9 @@ ha_innobase::open(
last_query_id = (ulong)-1;
+ active_index = 0;
+ active_index_before_scan = (uint)-1; /* undefined value */
+
if (!(share=get_share(name)))
DBUG_RETURN(1);
@@ -1938,13 +1976,6 @@ ha_innobase::write_row(
build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
}
- if (user_thd->lex.sql_command == SQLCOM_INSERT
- && user_thd->lex.duplicates == DUP_IGNORE) {
- prebuilt->trx->ignore_duplicates_in_insert = TRUE;
- } else {
- prebuilt->trx->ignore_duplicates_in_insert = FALSE;
- }
-
srv_conc_enter_innodb(prebuilt->trx);
error = row_insert_for_mysql((byte*) record, prebuilt);
@@ -1985,8 +2016,6 @@ ha_innobase::write_row(
}
}
- prebuilt->trx->ignore_duplicates_in_insert = FALSE;
-
error = convert_error_code_to_mysql(error, user_thd);
/* Tell InnoDB server that there might be work for
@@ -2057,7 +2086,8 @@ calc_row_difference(
upd_t* uvect, /* in/out: update vector */
mysql_byte* old_row, /* in: old row in MySQL format */
mysql_byte* new_row, /* in: new row in MySQL format */
- struct st_table* table, /* in: table in MySQL data dictionary */
+ struct st_table* table, /* in: table in MySQL data
+ dictionary */
mysql_byte* upd_buff, /* in: buffer to use */
row_prebuilt_t* prebuilt, /* in: InnoDB prebuilt struct */
THD* thd) /* in: user thread */
@@ -2107,8 +2137,10 @@ calc_row_difference(
case DATA_VARCHAR:
case DATA_BINARY:
case DATA_VARMYSQL:
- o_ptr = row_mysql_read_var_ref_noninline(&o_len, o_ptr);
- n_ptr = row_mysql_read_var_ref_noninline(&n_len, n_ptr);
+ o_ptr = row_mysql_read_var_ref_noninline(&o_len,
+ o_ptr);
+ n_ptr = row_mysql_read_var_ref_noninline(&n_len,
+ n_ptr);
default:
;
}
@@ -2556,7 +2588,7 @@ ha_innobase::change_active_index(
/* MySQL changes the active index for a handle also during some
queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
- and then calculates te sum. Previously we played safe and used
+ and then calculates the sum. Previously we played safe and used
the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
copying. Starting from MySQL-4.1 we use a more efficient flag here. */
@@ -2755,6 +2787,11 @@ ha_innobase::rnd_init(
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ /* Store the active index value so that we can restore the original
+ value after a scan */
+
+ active_index_before_scan = active_index;
+
if (prebuilt->clust_index_was_generated) {
err = change_active_index(MAX_KEY);
} else {
@@ -2767,13 +2804,25 @@ ha_innobase::rnd_init(
}
/*********************************************************************
-Ends a table scan ???????????????? */
+Ends a table scan. */
int
ha_innobase::rnd_end(void)
/*======================*/
/* out: 0 or error number */
{
+ /* Restore the old active_index back; MySQL may assume that a table
+ scan does not change active_index. We only restore the value if
+ MySQL has called rnd_init before: sometimes MySQL seems to call
+ rnd_end WITHOUT calling rnd_init. */
+
+ if (active_index_before_scan != (uint)-1) {
+
+ change_active_index(active_index_before_scan);
+
+ active_index_before_scan = (uint)-1;
+ }
+
return(index_end());
}
@@ -3088,6 +3137,9 @@ ha_innobase::create(
trx_search_latch_release_if_reserved(parent_trx);
trx = trx_allocate_for_mysql();
+
+ trx->mysql_thd = thd;
+ trx->mysql_query_str = &((*thd).query);
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
trx->check_foreigns = FALSE;
@@ -3216,7 +3268,7 @@ ha_innobase::create(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
innobase_table = dict_table_get(norm_name, NULL);
@@ -3271,6 +3323,9 @@ ha_innobase::delete_table(
trx = trx_allocate_for_mysql();
+ trx->mysql_thd = current_thd;
+ trx->mysql_query_str = &((*current_thd).query);
+
name_len = strlen(name);
assert(name_len < 1000);
@@ -3288,7 +3343,7 @@ ha_innobase::delete_table(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -3349,6 +3404,8 @@ innobase_drop_database(
my_casedn_str(system_charset_info, namebuf);
#endif
trx = trx_allocate_for_mysql();
+ trx->mysql_thd = current_thd;
+ trx->mysql_query_str = &((*current_thd).query);
error = row_drop_database_for_mysql(namebuf, trx);
@@ -3356,7 +3413,7 @@ innobase_drop_database(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -3408,6 +3465,8 @@ ha_innobase::rename_table(
}
trx = trx_allocate_for_mysql();
+ trx->mysql_thd = current_thd;
+ trx->mysql_query_str = &((*current_thd).query);
name_len1 = strlen(from);
name_len2 = strlen(to);
@@ -3426,7 +3485,7 @@ ha_innobase::rename_table(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -3541,10 +3600,8 @@ ha_innobase::records_in_range(
/*************************************************************************
Gives an UPPER BOUND to the number of rows in a table. This is used in
-filesort.cc and the upper bound must hold. TODO: Since the number of
-rows in a table may change after this function is called, we still may
-get a 'Sort aborted' error in filesort.cc of MySQL. The ultimate fix is to
-improve the algorithm of filesort.cc. */
+filesort.cc and its better if the upper bound hold.
+*/
ha_rows
ha_innobase::estimate_number_of_rows(void)
@@ -3610,6 +3667,29 @@ ha_innobase::scan_time()
return((double) (prebuilt->table->stat_clustered_index_size));
}
+/*
+ Calculate the time it takes to read a set of ranges through and index
+ This enables us to optimise reads for clustered indexes.
+*/
+
+double ha_innobase::read_time(uint index, uint ranges, ha_rows rows)
+{
+ ha_rows total_rows;
+ double time_for_scan;
+ if (index != table->primary_key)
+ return handler::read_time(index, ranges, rows); // Not clustered
+ if (rows <= 2)
+ return (double) rows;
+ /*
+ Assume that the read is proportional to scan time for all rows + one
+ seek per range.
+ */
+ time_for_scan= scan_time();
+ if ((total_rows= estimate_number_of_rows()) < rows)
+ return time_for_scan;
+ return (ranges + (double) rows / (double) total_rows * time_for_scan);
+}
+
/*************************************************************************
Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. */
@@ -3734,6 +3814,23 @@ ha_innobase::info(
DBUG_VOID_RETURN;
}
+/**************************************************************************
+Updates index cardinalities of the table, based on 10 random dives into
+each index tree. This does NOT calculate exact statistics of the table. */
+
+int
+ha_innobase::analyze(
+/*=================*/
+ /* out: returns always 0 (success) */
+ THD* thd, /* in: connection thread handle */
+ HA_CHECK_OPT* check_opt) /* in: currently ignored */
+{
+ /* Simply call ::info() with all the flags */
+ info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
+
+ return(0);
+}
+
/***********************************************************************
Tries to check that an InnoDB table is not corrupted. If corruption is
noticed, prints to stderr information about it. In case of corruption
@@ -3915,7 +4012,7 @@ ha_innobase::extra(
break;
case HA_EXTRA_RESET_STATE:
prebuilt->read_just_key = 0;
- break;
+ break;
case HA_EXTRA_NO_KEYREAD:
prebuilt->read_just_key = 0;
break;
@@ -4084,6 +4181,8 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked = 0;
+ prebuilt->used_in_HANDLER = FALSE;
+
/* Here we release the search latch and InnoDB
thread FIFO ticket if they were reserved. */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index be1174added..9ca8475e75e 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -58,7 +58,15 @@ class ha_innobase: public handler
ulong start_of_scan; /* this is set to 1 when we are
starting a table scan but have not
yet fetched any row, else 0 */
-
+ uint active_index_before_scan;
+ /* since a table scan in InnoDB is
+ always done through an index, a table
+ scan may change active_index; but
+ MySQL may assume that active_index
+ after a table scan is the same as
+ before; we store the value here so
+ that we can restore the value after
+ a scan */
uint last_match_mode;/* match mode of the latest search:
ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
or undefined */
@@ -118,6 +126,7 @@ class ha_innobase: public handler
void initialize(void);
int close(void);
double scan_time();
+ double read_time(uint index, uint ranges, ha_rows rows);
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
@@ -143,6 +152,7 @@ class ha_innobase: public handler
void position(const byte *record);
void info(uint);
+ int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int extra(enum ha_extra_function operation);
int reset(void);
int external_lock(THD *thd, int lock_type);
@@ -189,6 +199,9 @@ extern char *innobase_unix_file_flush_method;
/* The following variables have to be my_bool for SHOW VARIABLES to work */
extern my_bool innobase_log_archive,
innobase_use_native_aio, innobase_fast_shutdown;
+extern "C" {
+extern ulong srv_max_buf_pool_modified_pct;
+}
extern TYPELIB innobase_lock_typelib;
@@ -203,6 +216,8 @@ int innobase_report_binlog_offset_and_commit(
void* trx_handle,
char* log_file_name,
my_off_t end_offset);
+int innobase_commit_complete(
+ void* trx_handle);
int innobase_rollback(THD *thd, void* trx_handle);
int innobase_close_connection(THD *thd);
int innobase_drop_database(char *path);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 213f5baf388..a9c3ddaef60 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -499,7 +499,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
param.thd = thd;
param.op_name = (char*) "repair";
param.testflag = ((check_opt->flags & ~(T_EXTEND)) |
- T_SILENT | T_FORCE_CREATE |
+ T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
(check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
param.sort_buffer_length= check_opt->sort_buffer_size;
start_records=file->state->records;
@@ -592,10 +592,24 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
{
local_testflag|= T_STATISTICS;
param.testflag|= T_STATISTICS; // We get this for free
- thd->proc_info="Repair by sorting";
statistics_done=1;
- error = mi_repair_by_sort(&param, file, fixed_name,
- param.testflag & T_QUICK);
+ if (current_thd->variables.myisam_repair_threads>1)
+ {
+ char buf[40];
+ /* TODO: respect myisam_repair_threads variable */
+ my_snprintf(buf, 40, "Repair with %d threads", my_count_bits(key_map));
+ thd->proc_info=buf;
+ error = mi_repair_parallel(&param, file, fixed_name,
+ param.testflag & T_QUICK);
+ thd->proc_info="Repair done"; // to reset proc_info, as
+ // it was pointing to local buffer
+ }
+ else
+ {
+ thd->proc_info="Repair by sorting";
+ error = mi_repair_by_sort(&param, file, fixed_name,
+ param.testflag & T_QUICK);
+ }
}
else
{
diff --git a/sql/handler.cc b/sql/handler.cc
index f2b7dbdf531..db1857e938c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -253,6 +253,9 @@ int ha_autocommit_or_rollback(THD *thd, int error)
replication. This function also calls the commit of the table
handler, because the order of transactions in the log of the table
handler must be the same as in the binlog.
+ NOTE that to eliminate the bottleneck of the group commit, we do not
+ flush the handler log files here, but only later in a call of
+ ha_commit_complete().
arguments:
thd: the thread handle of the current connection
@@ -279,13 +282,38 @@ int ha_report_binlog_offset_and_commit(THD *thd,
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
error=1;
}
- trans->innodb_active_trans=0;
}
#endif
return error;
}
/*
+ Flushes the handler log files (if my.cnf settings do not free us from it)
+ after we have called ha_report_binlog_offset_and_commit(). To eliminate
+ the bottleneck from the group commit, this should be called when
+ LOCK_log has been released in log.cc.
+
+ arguments:
+ thd: the thread handle of the current connection
+ return value: always 0
+*/
+
+int ha_commit_complete(THD *thd)
+{
+#ifdef HAVE_INNOBASE_DB
+ THD_TRANS *trans;
+ trans = &thd->transaction.all;
+ if (trans->innobase_tid)
+ {
+ innobase_commit_complete(trans->innobase_tid);
+
+ trans->innodb_active_trans=0;
+ }
+#endif
+ return 0;
+}
+
+/*
This function should be called when MySQL sends rows of a SELECT result set
or the EOF mark to the client. It releases a possible adaptive hash index
S-latch held by thd in InnoDB and also releases a possible InnoDB query
@@ -812,7 +840,8 @@ void handler::print_error(int error, myf errflag)
DBUG_VOID_RETURN;
}
- /* Return key if error because of duplicated keys */
+
+/* Return key if error because of duplicated keys */
uint handler::get_dup_key(int error)
{
@@ -823,6 +852,7 @@ uint handler::get_dup_key(int error)
DBUG_RETURN(table->file->errkey);
}
+
int handler::delete_table(const char *name)
{
int error=0;
@@ -849,9 +879,10 @@ int handler::rename_table(const char * from, const char * to)
DBUG_RETURN(0);
}
-/* Tell the handler to turn on or off logging to the handler's
- recovery log
+/*
+ Tell the handler to turn on or off logging to the handler's recovery log
*/
+
int ha_recovery_logging(THD *thd, bool on)
{
int error=0;
@@ -906,7 +937,6 @@ bool handler::caching_allowed(THD* thd, char* table_key,
int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info)
-
{
int error;
TABLE table;
diff --git a/sql/handler.h b/sql/handler.h
index 8c23a3625e0..97ce295d520 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -235,7 +235,8 @@ 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 rows2double(rows); }
+ virtual double read_time(uint index, uint ranges, ha_rows rows)
+ { return rows2double(ranges+rows); }
virtual bool fast_key_read() { return 0;}
virtual key_map keys_to_use_for_scanning() { return 0; }
virtual bool has_transactions(){ return 0;}
@@ -389,6 +390,7 @@ void ha_resize_key_cache(void);
int ha_start_stmt(THD *thd);
int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name,
my_off_t end_offset);
+int ha_commit_complete(THD *thd);
int ha_release_temporary_latches(THD *thd);
int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
diff --git a/sql/init.cc b/sql/init.cc
index 8834fd3a89c..50d504068a0 100644
--- a/sql/init.cc
+++ b/sql/init.cc
@@ -38,13 +38,11 @@ void unireg_init(ulong options)
init_my_atof(); /* use our atof */
#endif
my_abort_hook=unireg_abort; /* Abort with close of databases */
- f_fyllchar=' '; /* Input fill char */
VOID(strmov(reg_ext,".frm"));
for (i=0 ; i < 6 ; i++) // YYMMDDHHMMSS
dayord.pos[i]=i;
specialflag=SPECIAL_SAME_DB_NAME;
- blob_newline='^'; /* Convert newline in blobs to this */
/* Make a tab of powers of 10 */
for (i=0,nr=1.0; i < array_elements(log_10) ; i++)
{ /* It's used by filesort... */
diff --git a/sql/item.cc b/sql/item.cc
index 053a94cb695..7599ae6486f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1048,6 +1048,14 @@ inline uint char_val(char X)
X-'a'+10);
}
+/* In MySQL 4.1 this will always return STRING_RESULT */
+
+enum Item_result Item_varbinary::result_type () const
+{
+ return (current_thd->variables.new_mode) ? STRING_RESULT : INT_RESULT;
+}
+
+
Item_varbinary::Item_varbinary(const char *str, uint str_length)
{
name=(char*) str-2; // Lex makes this start with 0x
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 1e547a9c76e..b027b156641 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -321,7 +321,7 @@ Item *create_func_current_user()
char buff[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
uint length;
- length= (uint) (strxmov(buff, thd->priv_user, "@", thd->host_or_ip, NullS) -
+ length= (uint) (strxmov(buff, thd->priv_user, "@", thd->priv_host, NullS) -
buff);
return new Item_string(NullS, thd->memdup(buff, length), length,
default_charset_info);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index d427e3c5a3a..eeab2367b2e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -109,15 +109,16 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ // Print purify happy
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
- if ((*arg)->fix_fields(thd, tables, arg) ||
- (*arg)->check_cols(allowed_arg_cols))
+ Item *item= *arg;
+ if (item->fix_fields(thd, tables, arg) ||
+ item->check_cols(allowed_arg_cols))
return 1; /* purecov: inspected */
- if ((*arg)->maybe_null)
+ if (item->maybe_null)
maybe_null=1;
- with_sum_func= with_sum_func || (*arg)->with_sum_func;
- used_tables_cache|=(*arg)->used_tables();
- const_item_cache&= (*arg)->const_item();
+ with_sum_func= with_sum_func || item->with_sum_func;
+ used_tables_cache|=item->used_tables();
+ const_item_cache&= item->const_item();
}
}
fix_length_and_dec();
@@ -140,14 +141,15 @@ void Item_func::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
Item **arg, **arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
{
- if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM)
- (*arg)->split_sum_func(ref_pointer_array, fields);
- else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
+ Item *item=* arg;
+ if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
+ item->split_sum_func(ref_pointer_array, fields);
+ else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
uint el= fields.elements;
- fields.push_front(*arg);
- ref_pointer_array[el]= *arg;
- *arg= new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
+ fields.push_front(item);
+ ref_pointer_array[el]= item;
+ *arg= new Item_ref(ref_pointer_array + el, 0, item->name);
}
}
}
@@ -1247,47 +1249,6 @@ longlong Item_func_find_in_set::val_int()
return 0;
}
-static char nbits[256] = {
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
- 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
-};
-
-uint count_bits(ulonglong v)
-{
-#if SIZEOF_LONG_LONG > 4
- /* The following code is a bit faster on 16 bit machines than if we would
- only shift v */
- ulong v2=(ulong) (v >> 32);
- return (uint) (uchar) (nbits[(uchar) v] +
- nbits[(uchar) (v >> 8)] +
- nbits[(uchar) (v >> 16)] +
- nbits[(uchar) (v >> 24)] +
- nbits[(uchar) (v2)] +
- nbits[(uchar) (v2 >> 8)] +
- nbits[(uchar) (v2 >> 16)] +
- nbits[(uchar) (v2 >> 24)]);
-#else
- return (uint) (uchar) (nbits[(uchar) v] +
- nbits[(uchar) (v >> 8)] +
- nbits[(uchar) (v >> 16)] +
- nbits[(uchar) (v >> 24)]);
-#endif
-}
-
longlong Item_func_bit_count::val_int()
{
ulonglong value= (ulonglong) args[0]->val_int();
@@ -1296,7 +1257,7 @@ longlong Item_func_bit_count::val_int()
null_value=1; /* purecov: inspected */
return 0; /* purecov: inspected */
}
- return (longlong) count_bits(value);
+ return (longlong) my_count_bits(value);
}
@@ -1370,16 +1331,17 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
arg != arg_end ;
arg++,i++)
{
- if ((*arg)->fix_fields(thd, tables, arg) || (*arg)->check_cols(1))
+ Item *item= *arg;
+ if (item->fix_fields(thd, tables, arg) || item->check_cols(1))
return 1;
- if ((*arg)->binary())
+ if (item->binary())
func->set_charset(&my_charset_bin);
- if ((*arg)->maybe_null)
+ if (item->maybe_null)
func->maybe_null=1;
- func->with_sum_func= func->with_sum_func || (*arg)->with_sum_func;
- used_tables_cache|=(*arg)->used_tables();
- const_item_cache&=(*arg)->const_item();
- f_args.arg_type[i]=(*arg)->result_type();
+ func->with_sum_func= func->with_sum_func || item->with_sum_func;
+ used_tables_cache|=item->used_tables();
+ const_item_cache&=item->const_item();
+ f_args.arg_type[i]=item->result_type();
}
if (!(buffers=new String[arg_count]) ||
!(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
@@ -2449,7 +2411,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
used_tables_cache|=item->used_tables();
}
/* check that all columns come from the same table */
- if (count_bits(used_tables_cache) != 1)
+ if (my_count_bits(used_tables_cache) != 1)
key=NO_SUCH_KEY;
const_item_cache=0;
table=((Item_field *)fields.head())->field->table;
@@ -2623,10 +2585,7 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name)
char buff[MAX_SYS_VAR_LENGTH+3+8], *pos;
if (!(var= find_sys_var(name.str, name.length)))
- {
- net_printf(thd, ER_UNKNOWN_SYSTEM_VARIABLE, name.str);
return 0;
- }
if (!(item=var->item(thd, var_type)))
return 0; // Impossible
thd->lex.uncacheable();
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 6118b25a88c..d28341c3bd0 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -27,9 +27,6 @@
#include "mysql_priv.h"
#include "sql_acl.h"
#include <m_ctype.h>
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
#ifdef HAVE_OPENSSL
#include <openssl/des.h>
#endif /* HAVE_OPENSSL */
@@ -925,7 +922,7 @@ void Item_str_func::left_right_max_length()
max_length=args[0]->max_length;
if (args[1]->const_item())
{
- int length=(int) args[1]->val_int();
+ int length=(int) args[1]->val_int()*default_charset_info->mbmaxlen;
if (length <= 0)
max_length=0;
else
@@ -1006,7 +1003,7 @@ void Item_func_substr::fix_length_and_dec()
}
if (arg_count == 3 && args[2]->const_item())
{
- int32 length= (int32) args[2]->val_int();
+ int32 length= (int32) args[2]->val_int() * default_charset_info->mbmaxlen;
if (length <= 0)
max_length=0; /* purecov: inspected */
else
@@ -1585,15 +1582,17 @@ String *Item_func_format::val_str(String *str)
str_length=str->length();
if (nr < 0)
str_length--; // Don't count sign
- length=str->length()+(diff=(str_length- dec-1)/3);
- if (diff)
+
+ /* We need this test to handle 'nan' values */
+ if (str_length >= dec+4)
{
char *tmp,*pos;
- str=copy_if_not_alloced(&tmp_str,str,length);
+ length= str->length()+(diff=(str_length- dec-1)/3);
+ str= copy_if_not_alloced(&tmp_str,str,length);
str->length(length);
- tmp=(char*) str->ptr()+length - dec-1;
- for (pos=(char*) str->ptr()+length ; pos != tmp; pos--)
- pos[0]=pos[- (int) diff];
+ tmp= (char*) str->ptr()+length - dec-1;
+ for (pos= (char*) str->ptr()+length ; pos != tmp; pos--)
+ pos[0]= pos[-(int) diff];
while (diff)
{
pos[0]=pos[-(int) diff]; pos--;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 11c850f9d5f..fa8bf7e6e0f 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -219,12 +219,14 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
void Item_sum_sum::reset()
{
- null_value=0; sum=0.0; Item_sum_sum::add();
+ null_value=1; sum=0.0; Item_sum_sum::add();
}
bool Item_sum_sum::add()
{
sum+=args[0]->val();
+ if (!args[0]->null_value)
+ null_value= 0;
return 0;
}
@@ -641,8 +643,10 @@ void Item_sum_sum::reset_field()
{
double nr=args[0]->val(); // Nulls also return 0
float8store(result_field->ptr,nr);
- null_value=0;
- result_field->set_notnull();
+ if (args[0]->null_value)
+ result_field->set_null();
+ else
+ result_field->set_notnull();
}
@@ -698,7 +702,10 @@ void Item_sum_sum::update_field(int offset)
float8get(old_nr,res+offset);
nr=args[0]->val();
if (!args[0]->null_value)
+ {
old_nr+=nr;
+ result_field->set_notnull();
+ }
float8store(res,old_nr);
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 37d7e7f79d0..f996f980fff 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -99,9 +99,6 @@ public:
class Item_sum_int :public Item_sum_num
{
- void fix_length_and_dec()
- { decimals=0; max_length=21; maybe_null=null_value=0; }
-
public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
@@ -109,6 +106,8 @@ public:
double val() { return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
+ void fix_length_and_dec()
+ { decimals=0; max_length=21; maybe_null=null_value=0; }
};
@@ -127,6 +126,7 @@ class Item_sum_sum :public Item_sum_num
double val();
void reset_field();
void update_field(int offset);
+ void no_rows_in_result() {}
const char *func_name() const { return "sum"; }
Item *copy_or_same(THD* thd) { return new Item_sum_sum(thd, *this); }
};
@@ -449,6 +449,8 @@ class Item_sum_bit :public Item_sum_int
void reset();
longlong val_int();
void reset_field();
+ void fix_length_and_dec()
+ { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; }
};
diff --git a/sql/log.cc b/sql/log.cc
index c9e20bc0cc9..c05d52bdc5d 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -317,7 +317,10 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
DBUG_RETURN(0);
err:
- sql_print_error("Could not use %s for logging (error %d)", log_name, errno);
+ sql_print_error("Could not use %s for logging (error %d). \
+Turning logging off for the whole duration of the MySQL server process. \
+To turn it on again: fix the cause, \
+shutdown the MySQL server and restart it.", log_name, errno);
if (file >= 0)
my_close(file,MYF(0));
if (index_file_nr >= 0)
@@ -1157,6 +1160,8 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command,
bool MYSQL_LOG::write(Log_event* event_info)
{
+ THD *thd=event_info->thd;
+ bool called_handler_commit=0;
bool error=0;
bool should_rotate = 0;
DBUG_ENTER("MYSQL_LOG::write(event)");
@@ -1171,7 +1176,6 @@ bool MYSQL_LOG::write(Log_event* event_info)
/* In most cases this is only called if 'is_open()' is true */
if (is_open())
{
- THD *thd=event_info->thd;
const char *local_db = event_info->get_db();
#ifdef USING_TRANSACTIONS
IO_CACHE *file = ((event_info->get_cache_stmt()) ?
@@ -1268,24 +1272,35 @@ bool MYSQL_LOG::write(Log_event* event_info)
the table handler commit here, protected by the LOCK_log mutex,
because otherwise the transactions may end up in a different order
in the table handler log!
+
+ Note that we will NOT call ha_report_binlog_offset_and_commit() if
+ there are binlog events cached in the transaction cache. That is
+ because then the log event which we write to the binlog here is
+ not a transactional event. In versions < 4.0.13 before this fix this
+ caused an InnoDB transaction to be committed if in the middle there
+ was a MyISAM event!
*/
- if (file == &log_file)
+ if (file == &log_file) // we are writing to the real log (disk)
{
- /*
- LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog
- chunks also before it is successfully completed. We only report
- the binlog write and do the commit inside the transactional table
- handler if the log event type is appropriate.
- */
-
- if (event_info->get_type_code() == QUERY_EVENT
- || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log))
{
- error = ha_report_binlog_offset_and_commit(thd, log_file_name,
- file->pos_in_file);
+ /*
+ LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog
+ chunks also before it is successfully completed. We only report
+ the binlog write and do the commit inside the transactional table
+ handler if the log event type is appropriate.
+ */
+
+ if (event_info->get_type_code() == QUERY_EVENT
+ || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ {
+ error = ha_report_binlog_offset_and_commit(thd, log_file_name,
+ file->pos_in_file);
+ called_handler_commit=1;
+ }
}
-
+ /* we wrote to the real log, check automatic rotation */
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
}
@@ -1309,6 +1324,16 @@ err:
}
pthread_mutex_unlock(&LOCK_log);
+
+ /*
+ Flush the transactional handler log file now that we have released
+ LOCK_log; the flush is placed here to eliminate the bottleneck on the
+ group commit
+ */
+
+ if (called_handler_commit)
+ ha_commit_complete(thd);
+
#ifdef HAVE_REPLICATION
if (should_rotate && expire_logs_days)
{
@@ -1316,7 +1341,6 @@ err:
if (purge_time >= 0)
error= purge_logs_before_date(purge_time);
}
-
#endif
DBUG_RETURN(error);
}
@@ -1423,6 +1447,13 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
}
VOID(pthread_mutex_unlock(&LOCK_log));
+
+ /* Flush the transactional handler log file now that we have released
+ LOCK_log; the flush is placed here to eliminate the bottleneck on the
+ group commit */
+
+ ha_commit_complete(thd);
+
DBUG_RETURN(0);
err:
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 39db264d898..be5b5079eee 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -26,11 +26,10 @@
#define log_cs &my_charset_latin1
-/*****************************************************************************
-
+/*
my_b_safe_write()
+*/
- ****************************************************************************/
inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
int len)
{
@@ -45,11 +44,11 @@ inline int my_b_safe_write(IO_CACHE* file, const byte *buf,
return my_b_write(file, buf,len);
}
-/*****************************************************************************
+/*
pretty_print_str()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
static void pretty_print_str(FILE* file, char* str, int len)
{
@@ -75,11 +74,11 @@ static void pretty_print_str(FILE* file, char* str, int len)
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
ignored_error_code()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
inline int ignored_error_code(int err_code)
{
@@ -87,11 +86,10 @@ inline int ignored_error_code(int err_code)
}
#endif
-/*****************************************************************************
-
+/*
pretty_print_str()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
static char* pretty_print_str(char* packet, char* str, int len)
{
@@ -117,13 +115,13 @@ static char* pretty_print_str(char* packet, char* str, int len)
*pos++= '\'';
return pos;
}
-#endif // !MYSQL_CLIENT
+#endif /* !MYSQL_CLIENT */
-/*****************************************************************************
+/*
slave_load_file_stem()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
static inline char* slave_load_file_stem(char*buf, uint file_id,
int event_server_id)
@@ -138,8 +136,7 @@ static inline char* slave_load_file_stem(char*buf, uint file_id,
}
#endif
-/*****************************************************************************
-
+/*
cleanup_load_tmpdir()
Delete all temporary files used for SQL_LOAD.
@@ -148,8 +145,8 @@ static inline char* slave_load_file_stem(char*buf, uint file_id,
- When we get a 'server start' event, we should only remove
the files associated with the server id that just started.
Easily fixable by adding server_id as a prefix to the log files.
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
static void cleanup_load_tmpdir()
{
@@ -170,22 +167,22 @@ static void cleanup_load_tmpdir()
}
#endif
-/*****************************************************************************
+/*
write_str()
+*/
- ****************************************************************************/
static bool write_str(IO_CACHE *file, char *str, byte length)
{
return (my_b_safe_write(file, &length, 1) ||
my_b_safe_write(file, (byte*) str, (int) length));
}
-/*****************************************************************************
+/*
read_str()
+*/
- ****************************************************************************/
static inline int read_str(char * &buf, char *buf_end, char * &str,
uint8 &len)
{
@@ -198,19 +195,14 @@ static inline int read_str(char * &buf, char *buf_end, char * &str,
}
-/*****************************************************************************
- *****************************************************************************
-
- Log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ Log_event methods
+***************************************************************************/
+/*
Log_event::get_type_str()
+*/
- ****************************************************************************/
const char* Log_event::get_type_str()
{
switch(get_type_code()) {
@@ -232,11 +224,11 @@ const char* Log_event::get_type_str()
}
}
-/*****************************************************************************
+/*
Log_event::Log_event()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
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),
@@ -258,13 +250,13 @@ Log_event::Log_event()
when= time(NULL);
log_pos= 0;
}
-#endif // !MYSQL_CLIENT
+#endif /* !MYSQL_CLIENT */
-/*****************************************************************************
+/*
Log_event::Log_event()
+*/
- ****************************************************************************/
Log_event::Log_event(const char* buf, bool old_format)
:temp_buf(0), cached_event_len(0), cache_stmt(0)
{
@@ -285,15 +277,13 @@ Log_event::Log_event(const char* buf, bool old_format)
#endif
}
-
#ifndef MYSQL_CLIENT
#ifdef HAVE_REPLICATION
-/*****************************************************************************
-
+/*
Log_event::exec_event()
+*/
- ****************************************************************************/
int Log_event::exec_event(struct st_relay_log_info* rli)
{
/*
@@ -324,15 +314,15 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
- then it will be MyISAM on the slave
- but as opt_using_transactions is true, the slave will believe he is
transactional with the MyISAM table. And problems will come when one
- does START SLAVE; STOP SLAVE; START SLAVE; (the slave will resume at BEGIN
- whereas there has not been any rollback). This is the problem of
+ does START SLAVE; STOP SLAVE; START SLAVE; (the slave will resume at
+ BEGIN whereas there has not been any rollback). This is the problem of
using opt_using_transactions instead of a finer
"does the slave support _the_transactional_handler_used_on_the_master_".
More generally, we'll have problems when a query mixes a transactional
handler and MyISAM and STOP SLAVE is issued in the middle of the
- "transaction". START SLAVE will resume at BEGIN while the MyISAM table has
- already been updated.
+ "transaction". START SLAVE will resume at BEGIN while the MyISAM table
+ has already been updated.
*/
if ((thd->options & OPTION_BEGIN) && opt_using_transactions)
@@ -346,24 +336,22 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
return 0;
}
-/*****************************************************************************
+/*
Log_event::pack_info()
+*/
- ****************************************************************************/
void Log_event::pack_info(Protocol *protocol)
{
protocol->store("", &my_charset_bin);
}
-/*****************************************************************************
-
+/*
Log_event::net_send()
Only called by SHOW BINLOG EVENTS
-
- ****************************************************************************/
+*/
int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
{
@@ -384,11 +372,11 @@ int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
}
#endif /* HAVE_REPLICATION */
-/*****************************************************************************
+/*
Log_event::init_show_field_list()
+*/
- ****************************************************************************/
void Log_event::init_show_field_list(List<Item>* field_list)
{
field_list->push_back(new Item_empty_string("Log_name", 20));
@@ -404,21 +392,20 @@ void Log_event::init_show_field_list(List<Item>* field_list)
#endif // !MYSQL_CLIENT
-/*****************************************************************************
-
+/*
Log_event::write()
+*/
- ****************************************************************************/
int Log_event::write(IO_CACHE* file)
{
return (write_header(file) || write_data(file)) ? -1 : 0;
}
-/*****************************************************************************
+/*
Log_event::write_header()
+*/
- ****************************************************************************/
int Log_event::write_header(IO_CACHE* file)
{
char buf[LOG_EVENT_HEADER_LEN];
@@ -439,11 +426,10 @@ int Log_event::write_header(IO_CACHE* file)
}
-/*****************************************************************************
-
+/*
Log_event::read_log_event()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
int Log_event::read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock)
@@ -510,13 +496,13 @@ end:
#define LOCK_MUTEX
#endif
-/*****************************************************************************
-
+/*
Log_event::read_log_event()
- Allocates memory--the caller is responsible for clean-up
+ NOTE:
+ Allocates memory; The caller is responsible for clean-up
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Log_event* Log_event::read_log_event(IO_CACHE* file,
pthread_mutex_t* log_lock,
@@ -588,11 +574,11 @@ data_len=%d,event_type=%d",error,data_len,head[EVENT_TYPE_OFFSET]);
return res;
}
-/*****************************************************************************
+/*
Log_event::read_log_event()
+*/
- ****************************************************************************/
Log_event* Log_event::read_log_event(const char* buf, int event_len,
const char **error, bool old_format)
{
@@ -657,9 +643,18 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
}
if (!ev || !ev->is_valid())
{
- *error= "Found invalid event in binary log";
delete ev;
+#ifdef MYSQL_CLIENT
+ if (!force_opt)
+ {
+ *error= "Found invalid event in binary log";
+ return 0;
+ }
+ ev= new Unknown_log_event(buf, old_format);
+#else
+ *error= "Found invalid event in binary log";
return 0;
+#endif
}
ev->cached_event_len = event_len;
return ev;
@@ -667,11 +662,10 @@ Log_event* Log_event::read_log_event(const char* buf, int event_len,
#ifdef MYSQL_CLIENT
-/*****************************************************************************
-
+/*
Log_event::print_header()
+*/
- ****************************************************************************/
void Log_event::print_header(FILE* file)
{
char llbuff[22];
@@ -681,11 +675,10 @@ void Log_event::print_header(FILE* file)
llstr(log_pos,llbuff));
}
-/*****************************************************************************
-
+/*
Log_event::print_timestamp()
+*/
- ****************************************************************************/
void Log_event::print_timestamp(FILE* file, time_t* ts)
{
struct tm *res;
@@ -709,11 +702,10 @@ void Log_event::print_timestamp(FILE* file, time_t* ts)
#endif // MYSQL_CLIENT
-/*****************************************************************************
-
+/*
Log_event::set_log_pos()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
void Log_event::set_log_pos(MYSQL_LOG* log)
{
@@ -723,21 +715,16 @@ void Log_event::set_log_pos(MYSQL_LOG* log)
#endif // !MYSQL_CLIENT
-
-/*****************************************************************************
- *****************************************************************************
-
- Query_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
+/**************************************************************************/
+ Query_log_event methods
+***************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
-/*****************************************************************************
+/*
Query_log_event::pack_info()
+*/
- ****************************************************************************/
void Query_log_event::pack_info(Protocol *protocol)
{
char *buf, *pos;
@@ -761,21 +748,21 @@ void Query_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Query_log_event::write()
+*/
- ****************************************************************************/
int Query_log_event::write(IO_CACHE* file)
{
return query ? Log_event::write(file) : -1;
}
-/*****************************************************************************
+/*
Query_log_event::write_data()
+*/
- ****************************************************************************/
int Query_log_event::write_data(IO_CACHE* file)
{
if (!query)
@@ -792,11 +779,11 @@ int Query_log_event::write_data(IO_CACHE* file)
my_b_safe_write(file, (byte*) query, q_len)) ? -1 : 0;
}
-/*****************************************************************************
+/*
Query_log_event::Query_log_event()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
ulong query_length, bool using_trans)
@@ -812,13 +799,12 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
exec_time = (ulong) (end_time - thd->start_time);
db_len = (db) ? (uint32) strlen(db) : 0;
}
-#endif // MYSQL_CLIENT
-
-/*****************************************************************************
+#endif /* MYSQL_CLIENT */
+/*
Query_log_event::Query_log_event()
+*/
- ****************************************************************************/
Query_log_event::Query_log_event(const char* buf, int event_len,
bool old_format)
:Log_event(buf, old_format),data_buf(0), query(NULL), db(NULL)
@@ -854,11 +840,11 @@ Query_log_event::Query_log_event(const char* buf, int event_len,
*((char*)query+q_len) = 0;
}
-/*****************************************************************************
+/*
Query_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Query_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -889,13 +875,13 @@ void Query_log_event::print(FILE* file, bool short_form, char* last_db)
my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
fprintf(file, ";\n");
}
-#endif // MYSQL_CLIENT
+#endif /* MYSQL_CLIENT */
-/*****************************************************************************
+/*
Query_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Query_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -996,19 +982,14 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Start_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ Start_log_event methods
+***************************************************************************/
+/*
Start_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Start_log_event::pack_info(Protocol *protocol)
{
@@ -1021,11 +1002,11 @@ void Start_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Start_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Start_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -1035,17 +1016,16 @@ void Start_log_event::print(FILE* file, bool short_form, char* last_db)
print_header(file);
fprintf(file, "\tStart: binlog v %d, server v %s created ", binlog_version,
server_version);
- print_timestamp(file, (time_t*)&created);
+ print_timestamp(file, &created);
fputc('\n', file);
fflush(file);
}
-#endif // MYSQL_CLIENT
-
-/*****************************************************************************
+#endif /* MYSQL_CLIENT */
+/*
Start_log_event::Start_log_event()
+*/
- ****************************************************************************/
Start_log_event::Start_log_event(const char* buf,
bool old_format)
:Log_event(buf, old_format)
@@ -1057,11 +1037,11 @@ Start_log_event::Start_log_event(const char* buf,
created = uint4korr(buf+ST_CREATED_OFFSET);
}
-/*****************************************************************************
+/*
Start_log_event::write_data()
+*/
- ****************************************************************************/
int Start_log_event::write_data(IO_CACHE* file)
{
char buff[START_HEADER_LEN];
@@ -1071,8 +1051,7 @@ int Start_log_event::write_data(IO_CACHE* file)
return (my_b_safe_write(file, (byte*) buff, sizeof(buff)) ? -1 : 0);
}
-/*****************************************************************************
-
+/*
Start_log_event::exec_event()
The master started
@@ -1080,6 +1059,10 @@ int Start_log_event::write_data(IO_CACHE* file)
IMPLEMENTATION
- To handle the case where the master died without a stop event,
we clean up all temporary tables + locks that we got.
+ However, we don't clean temporary tables if the master was 3.23
+ (this is because a 3.23 master writes a Start_log_event at every
+ binlog rotation; if we were not careful we would remove temp tables
+ on the slave when FLUSH LOGS is issued on the master).
TODO
- Remove all active user locks
@@ -1087,36 +1070,37 @@ int Start_log_event::write_data(IO_CACHE* file)
in the middle while writing the transaction to the binary log.
In this case we should stop the slave.
- ****************************************************************************/
+*/
+
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Start_log_event::exec_event(struct st_relay_log_info* rli)
{
DBUG_ENTER("Start_log_event::exec_event");
- /* All temporary tables was deleted on the master */
- close_temporary_tables(thd);
- /*
- If we have old format, load_tmpdir is cleaned up by the I/O thread
- */
+
if (!rli->mi->old_format)
+ {
+ /*
+ If 4.0 master, all temporary tables have been deleted on the master;
+ if 3.23 master, this is far from sure.
+ */
+ close_temporary_tables(thd);
+ /*
+ If we have old format, load_tmpdir is cleaned up by the I/O thread
+ */
cleanup_load_tmpdir();
+ }
DBUG_RETURN(Log_event::exec_event(rli));
}
-#endif
-
+#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
-/*****************************************************************************
- *****************************************************************************
-
- Load_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ Load_log_event methods
+***************************************************************************/
+/*
Load_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Load_log_event::pack_info(Protocol *protocol)
{
@@ -1220,13 +1204,13 @@ void Load_log_event::pack_info(Protocol *protocol)
protocol->store(buf, pos-buf, &my_charset_bin);
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
}
-#endif
+#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
-/*****************************************************************************
+/*
Load_log_event::write_data_header()
+*/
- ****************************************************************************/
int Load_log_event::write_data_header(IO_CACHE* file)
{
char buf[LOAD_HEADER_LEN];
@@ -1239,11 +1223,11 @@ int Load_log_event::write_data_header(IO_CACHE* file)
return my_b_safe_write(file, (byte*)buf, LOAD_HEADER_LEN);
}
-/*****************************************************************************
+/*
Load_log_event::write_data_body()
+*/
- ****************************************************************************/
int Load_log_event::write_data_body(IO_CACHE* file)
{
if (sql_ex.write_data(file))
@@ -1259,11 +1243,11 @@ int Load_log_event::write_data_body(IO_CACHE* file)
my_b_safe_write(file, (byte*)fname, fname_len));
}
-/*****************************************************************************
+/*
Load_log_event::Load_log_event()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
const char *db_arg, const char *table_name_arg,
@@ -1343,16 +1327,16 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
field_lens = (const uchar*)field_lens_buf.ptr();
fields = fields_buf.ptr();
}
-#endif // !MYSQL_CLIENT
-
-/*****************************************************************************
+#endif /* !MYSQL_CLIENT */
+/*
Load_log_event::Load_log_event()
- The caller must do buf[event_len] = 0 before he starts using the
- constructed event.
+ NOTE
+ The caller must do buf[event_len] = 0 before he starts using the
+ 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),
@@ -1364,11 +1348,11 @@ Load_log_event::Load_log_event(const char *buf, int event_len,
copy_log_event(buf, event_len, old_format);
}
-/*****************************************************************************
+/*
Load_log_event::copy_log_event()
+*/
- ****************************************************************************/
int Load_log_event::copy_log_event(const char *buf, ulong event_len,
bool old_format)
{
@@ -1413,11 +1397,11 @@ int Load_log_event::copy_log_event(const char *buf, ulong event_len,
return 0;
}
-/*****************************************************************************
+/*
Load_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Load_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -1502,13 +1486,13 @@ void Load_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf(file, ";\n");
}
-#endif /* #ifdef MYSQL_CLIENT */
+#endif /* MYSQL_CLIENT */
-/*****************************************************************************
+/*
Load_log_event::set_fields()
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
void Load_log_event::set_fields(List<Item> &field_list)
{
@@ -1645,12 +1629,11 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
close_thread_tables(thd);
if (thd->query_error)
{
- int sql_error = thd->net.last_errno;
+ int sql_error= thd->net.last_errno;
if (!sql_error)
- sql_error = ER_UNKNOWN_ERROR;
-
+ sql_error= ER_UNKNOWN_ERROR;
slave_print_error(rli,sql_error,
- "Slave: Error '%s' running load data infile ",
+ "Error '%s' running LOAD DATA INFILE",
ER_SAFE(sql_error));
free_root(&thd->mem_root,0);
return 1;
@@ -1659,7 +1642,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
if (thd->is_fatal_error)
{
- sql_print_error("Slave: Fatal error running LOAD DATA INFILE ");
+ sql_print_error("Fatal error running LOAD DATA INFILE");
return 1;
}
@@ -1668,19 +1651,14 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Rotate_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/****************************************************************************/
+ Rotate_log_event methods
+*****************************************************************************/
+/*
Rotate_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Rotate_log_event::pack_info(Protocol *protocol)
{
@@ -1699,11 +1677,11 @@ void Rotate_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Rotate_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -1724,11 +1702,11 @@ void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
Rotate_log_event::Rotate_log_event()
+*/
- ****************************************************************************/
Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
bool old_format)
:Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
@@ -1760,11 +1738,11 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
alloced = 1;
}
-/*****************************************************************************
+/*
Rotate_log_event::write_data()
+*/
- ****************************************************************************/
int Rotate_log_event::write_data(IO_CACHE* file)
{
char buf[ROTATE_HEADER_LEN];
@@ -1773,8 +1751,8 @@ int Rotate_log_event::write_data(IO_CACHE* file)
my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
}
-/*****************************************************************************
+/*
Rotate_log_event::exec_event()
Got a rotate log even from the master
@@ -1788,8 +1766,8 @@ int Rotate_log_event::write_data(IO_CACHE* file)
RETURN VALUES
0 ok
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -1810,19 +1788,14 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Intvar_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Intvar_log_event methods
+****************************************************************************/
+/*
Intvar_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Intvar_log_event::pack_info(Protocol *protocol)
{
@@ -1834,11 +1807,11 @@ void Intvar_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Intvar_log_event::Intvar_log_event()
+*/
- ****************************************************************************/
Intvar_log_event::Intvar_log_event(const char* buf, bool old_format)
:Log_event(buf, old_format)
{
@@ -1847,11 +1820,11 @@ Intvar_log_event::Intvar_log_event(const char* buf, bool old_format)
val = uint8korr(buf+I_VAL_OFFSET);
}
-/*****************************************************************************
+/*
Intvar_log_event::get_var_type_name()
+*/
- ****************************************************************************/
const char* Intvar_log_event::get_var_type_name()
{
switch(type) {
@@ -1861,11 +1834,11 @@ const char* Intvar_log_event::get_var_type_name()
}
}
-/*****************************************************************************
+/*
Intvar_log_event::write_data()
+*/
- ****************************************************************************/
int Intvar_log_event::write_data(IO_CACHE* file)
{
char buf[9];
@@ -1874,11 +1847,11 @@ int Intvar_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, (byte*) buf, sizeof(buf));
}
-/*****************************************************************************
+/*
Intvar_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -1904,13 +1877,13 @@ void Intvar_log_event::print(FILE* file, bool short_form, char* last_db)
fprintf(file, "%s=%s;\n", msg, llstr(val,llbuff));
fflush(file);
}
-#endif // MYSQL_CLIENT
+#endif
-/*****************************************************************************
+/*
Intvar_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2121,11 +2094,10 @@ int User_var_log_event::write_data(IO_CACHE* file)
}
-/*****************************************************************************
-
+/*
User_var_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -2168,11 +2140,11 @@ void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
}
#endif
-/*****************************************************************************
+/*
User_var_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int User_var_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2226,7 +2198,18 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
/****************************************************************************
Slave_log_event methods
****************************************************************************/
+
#ifdef HAVE_REPLICATION
+#ifdef MYSQL_CLIENT
+void Unknown_log_event::print(FILE* file, bool short_form, char* last_db)
+{
+ if (short_form)
+ return;
+ print_header(file);
+ fputc('\n', file);
+ fprintf(file, "# %s", "Unknown event\n");
+}
+#endif
#ifndef MYSQL_CLIENT
void Slave_log_event::pack_info(Protocol *protocol)
@@ -2359,19 +2342,14 @@ int Slave_log_event::exec_event(struct st_relay_log_info* rli)
#endif // !MYSQL_CLIENT
-/*****************************************************************************
- *****************************************************************************
-
- Stop_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Stop_log_event methods
+****************************************************************************/
+/*
Stop_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
{
@@ -2384,8 +2362,8 @@ void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
Stop_log_event::exec_event()
The master stopped. Clean up all temporary tables + locks that the
@@ -2393,12 +2371,18 @@ void Stop_log_event::print(FILE* file, bool short_form, char* last_db)
TODO
- Remove all active user locks
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
int Stop_log_event::exec_event(struct st_relay_log_info* rli)
{
- // do not clean up immediately after rotate event
+ /*
+ do not clean up immediately after rotate event;
+ QQ: this should be a useless test: the only case when it is false is when
+ shutdown occurred just after FLUSH LOGS. It has nothing to do with Rotate?
+ By the way, immediately after a Rotate the I/O thread does not write
+ the Stop to the relay log, so we won't come here in that case.
+ */
if (rli->group_master_log_pos > BIN_LOG_HEADER_SIZE)
{
close_temporary_tables(thd);
@@ -2415,23 +2399,18 @@ int Stop_log_event::exec_event(struct st_relay_log_info* rli)
flush_relay_log_info(rli);
return 0;
}
-#endif // !MYSQL_CLIENT
+#endif /* !MYSQL_CLIENT */
#endif /* HAVE_REPLICATION */
-/*****************************************************************************
- *****************************************************************************
-
- Create_file_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Create_file_log_event methods
+****************************************************************************/
+/*
Create_file_log_event ctor
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Create_file_log_event::
Create_file_log_event(THD* thd_arg, sql_exchange* ex,
@@ -2447,11 +2426,11 @@ Create_file_log_event(THD* thd_arg, sql_exchange* ex,
}
#endif // !MYSQL_CLIENT
-/*****************************************************************************
+/*
Create_file_log_event::write_data_body()
+*/
- ****************************************************************************/
int Create_file_log_event::write_data_body(IO_CACHE* file)
{
int res;
@@ -2461,11 +2440,11 @@ int Create_file_log_event::write_data_body(IO_CACHE* file)
my_b_safe_write(file, (byte*) block, block_len));
}
-/*****************************************************************************
+/*
Create_file_log_event::write_data_header()
+*/
- ****************************************************************************/
int Create_file_log_event::write_data_header(IO_CACHE* file)
{
int res;
@@ -2476,11 +2455,11 @@ int Create_file_log_event::write_data_header(IO_CACHE* file)
return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN);
}
-/*****************************************************************************
+/*
Create_file_log_event::write_base()
+*/
- ****************************************************************************/
int Create_file_log_event::write_base(IO_CACHE* file)
{
int res;
@@ -2490,11 +2469,11 @@ int Create_file_log_event::write_base(IO_CACHE* file)
return res;
}
-/*****************************************************************************
+/*
Create_file_log_event ctor
+*/
- ****************************************************************************/
Create_file_log_event::Create_file_log_event(const char* buf, int len,
bool old_format)
:Load_log_event(buf,0,old_format),fake_base(0),block(0),inited_from_old(0)
@@ -2521,11 +2500,11 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len,
}
}
-/*****************************************************************************
+/*
Create_file_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Create_file_log_event::print(FILE* file, bool short_form,
char* last_db, bool enable_local)
@@ -2555,11 +2534,11 @@ void Create_file_log_event::print(FILE* file, bool short_form,
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
Create_file_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Create_file_log_event::pack_info(Protocol *protocol)
{
@@ -2578,11 +2557,11 @@ void Create_file_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Create_file_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2643,19 +2622,14 @@ err:
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Append_block_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Append_block_log_event methods
+****************************************************************************/
+/*
Append_block_log_event ctor
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
uint block_len_arg,
@@ -2664,13 +2638,13 @@ Append_block_log_event::Append_block_log_event(THD* thd_arg, char* block_arg,
block_len(block_len_arg), file_id(thd_arg->file_id)
{
}
-#endif // !MYSQL_CLIENT
+#endif
-/*****************************************************************************
+/*
Append_block_log_event ctor
+*/
- ****************************************************************************/
Append_block_log_event::Append_block_log_event(const char* buf, int len)
:Log_event(buf, 0),block(0)
{
@@ -2681,11 +2655,11 @@ Append_block_log_event::Append_block_log_event(const char* buf, int len)
block_len = len - APPEND_BLOCK_EVENT_OVERHEAD;
}
-/*****************************************************************************
+/*
Append_block_log_event::write_data()
+*/
- ****************************************************************************/
int Append_block_log_event::write_data(IO_CACHE* file)
{
byte buf[APPEND_BLOCK_HEADER_LEN];
@@ -2694,11 +2668,11 @@ int Append_block_log_event::write_data(IO_CACHE* file)
my_b_safe_write(file, (byte*) block, block_len));
}
-/*****************************************************************************
+/*
Append_block_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Append_block_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -2712,11 +2686,11 @@ void Append_block_log_event::print(FILE* file, bool short_form,
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
+/*
Append_block_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Append_block_log_event::pack_info(Protocol *protocol)
{
@@ -2729,11 +2703,11 @@ void Append_block_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
+/*
Append_block_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2765,31 +2739,25 @@ err:
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Delete_file_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/***************************************************************************/
+ Delete_file_log_event methods
+****************************************************************************/
+/*
Delete_file_log_event ctor
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
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
-
-/*****************************************************************************
+#endif
+/*
Delete_file_log_event ctor
+*/
- ****************************************************************************/
Delete_file_log_event::Delete_file_log_event(const char* buf, int len)
:Log_event(buf, 0),file_id(0)
{
@@ -2798,11 +2766,11 @@ Delete_file_log_event::Delete_file_log_event(const char* buf, int len)
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + AB_FILE_ID_OFFSET);
}
-/*****************************************************************************
+/*
Delete_file_log_event::write_data()
+*/
- ****************************************************************************/
int Delete_file_log_event::write_data(IO_CACHE* file)
{
byte buf[DELETE_FILE_HEADER_LEN];
@@ -2810,11 +2778,11 @@ int Delete_file_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, buf, DELETE_FILE_HEADER_LEN);
}
-/*****************************************************************************
+/*
Delete_file_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Delete_file_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -2827,11 +2795,10 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
}
#endif // MYSQL_CLIENT
-/*****************************************************************************
-
+/*
Delete_file_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Delete_file_log_event::pack_info(Protocol *protocol)
{
@@ -2842,11 +2809,10 @@ void Delete_file_log_event::pack_info(Protocol *protocol)
}
#endif
-/*****************************************************************************
-
+/*
Delete_file_log_event::exec_event()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -2863,31 +2829,26 @@ int Delete_file_log_event::exec_event(struct st_relay_log_info* rli)
#endif
-/*****************************************************************************
- *****************************************************************************
-
- Execute_load_log_event methods
-
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ Execute_load_log_event methods
+***************************************************************************/
+/*
Execute_load_log_event ctor
+*/
- ****************************************************************************/
#ifndef MYSQL_CLIENT
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
+#endif
-/*****************************************************************************
+/*
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)
{
@@ -2896,11 +2857,11 @@ Execute_load_log_event::Execute_load_log_event(const char* buf, int len)
file_id = uint4korr(buf + LOG_EVENT_HEADER_LEN + EL_FILE_ID_OFFSET);
}
-/*****************************************************************************
+/*
Execute_load_log_event::write_data()
+*/
- ****************************************************************************/
int Execute_load_log_event::write_data(IO_CACHE* file)
{
byte buf[EXEC_LOAD_HEADER_LEN];
@@ -2908,11 +2869,11 @@ int Execute_load_log_event::write_data(IO_CACHE* file)
return my_b_safe_write(file, buf, EXEC_LOAD_HEADER_LEN);
}
-/*****************************************************************************
+/*
Execute_load_log_event::print()
+*/
- ****************************************************************************/
#ifdef MYSQL_CLIENT
void Execute_load_log_event::print(FILE* file, bool short_form,
char* last_db)
@@ -2924,13 +2885,12 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
fprintf(file, "#Exec_load: file_id=%d\n",
file_id);
}
-#endif // MYSQL_CLIENT
-
-/*****************************************************************************
+#endif
+/*
Execute_load_log_event::pack_info()
+*/
- ****************************************************************************/
#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
void Execute_load_log_event::pack_info(Protocol *protocol)
{
@@ -2940,11 +2900,10 @@ void Execute_load_log_event::pack_info(Protocol *protocol)
protocol->store(buf, (int32) length, &my_charset_bin);
}
-/*****************************************************************************
+/*
Execute_load_log_event::exec_event()
-
- ****************************************************************************/
+*/
int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
{
@@ -3009,22 +2968,17 @@ err:
return error ? error : Log_event::exec_event(rli);
}
-#endif
-
-
-/*****************************************************************************
- *****************************************************************************
+#endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
- sql_ex_info methods
- *****************************************************************************
- ****************************************************************************/
-
-/*****************************************************************************
+/**************************************************************************/
+ sql_ex_info methods
+***************************************************************************/
+/*
sql_ex_info::write_data()
+*/
- ****************************************************************************/
int sql_ex_info::write_data(IO_CACHE* file)
{
if (new_format())
@@ -3050,11 +3004,11 @@ int sql_ex_info::write_data(IO_CACHE* file)
}
}
-/*****************************************************************************
+/*
sql_ex_info::init()
+*/
- ****************************************************************************/
char* sql_ex_info::init(char* buf,char* buf_end,bool use_new_format)
{
cached_new_format = use_new_format;
diff --git a/sql/log_event.h b/sql/log_event.h
index 62b5873fabb..1d2fc741fa8 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -227,10 +227,11 @@ struct sql_ex_info
enum Log_event_type
{
- START_EVENT = 1, QUERY_EVENT =2, STOP_EVENT=3, ROTATE_EVENT = 4,
- INTVAR_EVENT=5, LOAD_EVENT=6, SLAVE_EVENT=7, CREATE_FILE_EVENT=8,
- APPEND_BLOCK_EVENT=9, EXEC_LOAD_EVENT=10, DELETE_FILE_EVENT=11,
- NEW_LOAD_EVENT=12, RAND_EVENT=13, USER_VAR_EVENT=14
+ UNKNOWN_EVENT= 0, START_EVENT= 1, QUERY_EVENT= 2, STOP_EVENT= 3,
+ ROTATE_EVENT= 4, INTVAR_EVENT= 5, LOAD_EVENT=6, SLAVE_EVENT= 7,
+ CREATE_FILE_EVENT= 8, APPEND_BLOCK_EVENT= 9, EXEC_LOAD_EVENT= 10,
+ DELETE_FILE_EVENT= 11, NEW_LOAD_EVENT= 12, RAND_EVENT= 13,
+ USER_VAR_EVENT= 14
};
enum Int_event_type
@@ -524,14 +525,14 @@ extern char server_version[SERVER_VERSION_LENGTH];
class Start_log_event: public Log_event
{
public:
- uint32 created;
+ time_t created;
uint16 binlog_version;
char server_version[ST_SERVER_VER_LEN];
#ifndef MYSQL_CLIENT
Start_log_event() :Log_event(), binlog_version(BINLOG_VERSION)
{
- created = (uint32) when;
+ created = (time_t) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
}
#ifdef HAVE_REPLICATION
@@ -887,4 +888,18 @@ public:
int write_data(IO_CACHE* file);
};
+#ifdef MYSQL_CLIENT
+class Unknown_log_event: public Log_event
+{
+public:
+ Unknown_log_event(const char* buf, bool old_format):
+ Log_event(buf, old_format)
+ {}
+ ~Unknown_log_event() {}
+ void print(FILE* file, bool short_form= 0, char* last_db= 0);
+ Log_event_type get_type_code() { return UNKNOWN_EVENT;}
+ bool is_valid() { return 1; }
+};
+#endif
+
#endif /* _log_event_h */
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index afcee5fbb02..9bfaa95d9d9 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -247,7 +247,7 @@ static void mc_free_old_query(MYSQL *mysql)
static int mc_sock_connect(my_socket s, const struct sockaddr *name,
uint namelen, uint to)
{
-#if defined(__WIN__) || defined(OS2)
+#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
return connect(s, (struct sockaddr*) name, namelen);
#else
int flags, res, s_err;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index ea6e544a1fd..5caa93115ab 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -368,7 +368,12 @@ void mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length);
+#ifndef EMBEDDED_LIBRARY
bool check_stack_overrun(THD *thd,char *dummy);
+#else
+#define check_stack_overrun(A, B) 0
+#endif
+
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
bool *write_to_binlog);
void table_cache_init(void);
@@ -624,8 +629,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table,
bool return_if_owned_by_thd=0);
bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables);
void copy_field_from_tmp_record(Field *field,int offset);
-int fill_record(List<Item> &fields,List<Item> &values);
-int fill_record(Field **field,List<Item> &values);
+int fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors);
+int fill_record(Field **field,List<Item> &values, bool ignore_errors);
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild);
/* sql_calc.cc */
@@ -690,7 +695,6 @@ extern char language[LIBLEN],reg_ext[FN_EXTLEN];
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file;
extern char log_error_file[FN_REFLEN];
-extern char blob_newline;
extern double log_10[32];
extern ulonglong keybuff_size;
extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
@@ -736,11 +740,11 @@ extern uint volatile thread_count, thread_running, global_read_lock;
extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types;
extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names;
extern my_bool opt_slave_compressed_protocol, use_temp_pool;
+extern my_bool opt_readonly;
extern my_bool opt_enable_named_pipe;
extern my_bool opt_old_passwords, use_old_passwords;
extern char *shared_memory_base_name;
extern bool opt_enable_shared_memory;
-extern char f_fyllchar;
extern MYSQL_LOG mysql_log,mysql_update_log,mysql_slow_log,mysql_bin_log;
extern FILE *bootstrap_file;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f73bd6721f0..c75b1981426 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -46,7 +46,7 @@
#define MAIN_THD
#define SIGNAL_THD
-#ifdef PURIFY
+#ifdef HAVE_purify
#define IF_PURIFY(A,B) (A)
#else
#define IF_PURIFY(A,B) (B)
@@ -208,12 +208,12 @@ static char **opt_argv;
#ifdef __WIN__
#undef MYSQL_SERVER_SUFFIX
#ifdef __NT__
-#if defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB)
+#if defined(HAVE_BERKELEY_DB)
#define MYSQL_SERVER_SUFFIX "-max-nt"
#else
#define MYSQL_SERVER_SUFFIX "-nt"
#endif /* ...DB */
-#elif defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB)
+#elif defined(HAVE_BERKELEY_DB)
#define MYSQL_SERVER_SUFFIX "-max"
#else
#define MYSQL_SERVER_SUFFIX ""
@@ -300,7 +300,7 @@ my_bool opt_enable_named_pipe= 0;
my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol;
uint delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
-static bool opt_do_pstack = 0;
+static my_bool opt_do_pstack = 0;
static ulong opt_specialflag=SPECIAL_ENGLISH;
static ulong opt_myisam_block_size;
@@ -392,7 +392,7 @@ const char *localhost=LOCAL_HOST;
const char *delayed_user="DELAYED";
uint master_port = MYSQL_PORT, master_connect_retry = 60;
uint report_port = MYSQL_PORT;
-bool master_ssl = 0;
+my_bool master_ssl = 0;
ulong master_retry_count=0;
ulong bytes_sent = 0L, bytes_received = 0L;
@@ -421,8 +421,7 @@ ulong expire_logs_days = 0;
char mysql_real_data_home[FN_REFLEN],
language[LIBLEN],reg_ext[FN_EXTLEN],
mysql_charsets_dir[FN_REFLEN], *charsets_list,
- blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot,
- *opt_init_file;
+ max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file;
char *language_ptr= language;
char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
#ifndef EMBEDDED_LIBRARY
@@ -823,9 +822,9 @@ static void __cdecl kill_server(int sig_ptr)
unireg_end();
#ifdef __NETWARE__
pthread_join(select_thread, NULL); // wait for main thread
-#else
- pthread_exit(0); /* purecov: deadcode */
#endif /* __NETWARE__ */
+
+ pthread_exit(0); /* purecov: deadcode */
#endif /* EMBEDDED_LIBRARY */
RETURN_FROM_KILL_SERVER;
@@ -883,13 +882,11 @@ void unireg_end(void)
{
clean_up(1);
my_thread_end();
-#ifndef __NETWARE__
-#ifdef SIGNALS_DONT_BREAK_READ
+#if defined(SIGNALS_DONT_BREAK_READ) && !defined(__NETWARE__)
exit(0);
#else
pthread_exit(0); // Exit is in main thread
#endif
-#endif /* __NETWARE__ */
}
@@ -954,6 +951,8 @@ void clean_up(bool print_message)
end_slave_list();
#endif
#ifdef HAVE_OPENSSL
+ if (ssl_acceptor_fd)
+ my_free((gptr) ssl_acceptor_fd, MYF(MY_ALLOW_ZERO_PTR));
free_des_key_file();
#endif /* HAVE_OPENSSL */
#ifdef USE_REGEX
@@ -1647,6 +1646,7 @@ static void init_signals(void)
sa.sa_handler=handle_segfault;
#endif
sigaction(SIGSEGV, &sa, NULL);
+ sigaction(SIGABRT, &sa, NULL);
#ifdef SIGBUS
sigaction(SIGBUS, &sa, NULL);
#endif
@@ -1732,9 +1732,10 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
/*
Setup alarm handler
- The two extra handlers are for slave threads
+ This should actually be '+ max_number_of_slaves' instead of +10,
+ but the +10 should be quite safe.
*/
- init_thr_alarm(max_connections+max_insert_delayed_threads+2);
+ init_thr_alarm(max_connections+max_insert_delayed_threads+10);
#if SIGINT != THR_KILL_SIGNAL
(void) sigemptyset(&set); // Setup up SIGINT for debug
(void) sigaddset(&set,SIGINT); // For debugging
@@ -3468,10 +3469,11 @@ enum options
OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER,
OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE,
OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME,
+ OPT_READONLY,
OPT_SORT_BUFFER, OPT_TABLE_CACHE,
OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE,
OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK,
- OPT_WAIT_TIMEOUT,
+ OPT_WAIT_TIMEOUT, OPT_MYISAM_REPAIR_THREADS,
OPT_INNODB_MIRRORED_LOG_GROUPS,
OPT_INNODB_LOG_FILES_IN_GROUP,
OPT_INNODB_LOG_FILE_SIZE,
@@ -3483,6 +3485,7 @@ enum options
OPT_INNODB_LOCK_WAIT_TIMEOUT,
OPT_INNODB_THREAD_CONCURRENCY,
OPT_INNODB_FORCE_RECOVERY,
+ OPT_INNODB_MAX_DIRTY_PAGES_PCT,
OPT_BDB_CACHE_SIZE,
OPT_BDB_LOG_BUFFER_SIZE,
OPT_BDB_MAX_LOCK,
@@ -3649,6 +3652,10 @@ Disable with --skip-bdb (will save memory)",
{"innodb_fast_shutdown", OPT_INNODB_FAST_SHUTDOWN,
"Speeds up server shutdown process", (gptr*) &innobase_fast_shutdown,
(gptr*) &innobase_fast_shutdown, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"innodb_max_dirty_pages_pct", OPT_INNODB_MAX_DIRTY_PAGES_PCT,
+ "Percentage of dirty pages allowed in bufferpool", (gptr*) &srv_max_buf_pool_modified_pct,
+ (gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0},
+
#endif /* End HAVE_INNOBASE_DB */
{"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
@@ -3667,7 +3674,7 @@ Disable with --skip-bdb (will save memory)",
(gptr*) &opt_local_infile, 0, GET_BOOL, OPT_ARG,
1, 0, 0, 0, 0, 0},
{"log-bin", OPT_BIN_LOG,
- "Log queries in new binary format (for replication)",
+ "Log update queries in binary format",
(gptr*) &opt_bin_logname, (gptr*) &opt_bin_logname, 0, GET_STR_ALLOC,
OPT_ARG, 0, 0, 0, 0, 0, 0},
{"log-bin-index", OPT_BIN_LOG_INDEX,
@@ -3721,27 +3728,32 @@ Disable with --skip-bdb (will save memory)",
(gptr*) &master_retry_count, (gptr*) &master_retry_count, 0, GET_ULONG,
REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
{"master-info-file", OPT_MASTER_INFO_FILE,
- "The location of the file that remembers where we left off on the master during the replication process. The default is `master.info' in the data directory. You should not need to change this.",
+ "The location and name of the file that remembers the master and where the I/O replication \
+thread is in the master's binlogs.",
(gptr*) &master_info_file, (gptr*) &master_info_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"master-ssl", OPT_MASTER_SSL,
- "Turn SSL on for replication. Be warned that is this is a relatively new feature.",
+ "Planned to enable the slave to connect to the master using SSL. Does nothing yet.",
(gptr*) &master_ssl, (gptr*) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"master-ssl-key", OPT_MASTER_SSL_KEY,
- "Master SSL keyfile name. Only applies if you have enabled master-ssl.",
+ "Master SSL keyfile name. Only applies if you have enabled master-ssl. Does \
+nothing yet.",
(gptr*) &master_ssl_key, (gptr*) &master_ssl_key, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"master-ssl-cert", OPT_MASTER_SSL_CERT,
- "Master SSL certificate file name. Only applies if you have enabled master-ssl.",
+ "Master SSL certificate file name. Only applies if you have enabled \
+master-ssl. Does nothing yet.",
(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.",
+ "Master SSL CA path. Only applies if you have enabled master-ssl. \
+Does nothing yet.",
(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.",
+ "Master SSL cipher. Only applies if you have enabled master-ssl. \
+Does nothing yet.",
(gptr*) &master_ssl_cipher, (gptr*) &master_ssl_capath, 0, GET_STR, OPT_ARG,
0, 0, 0, 0, 0, 0},
{"myisam-recover", OPT_MYISAM_RECOVER,
@@ -3842,10 +3854,13 @@ Disable with --skip-bdb (will save memory)",
{"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented",
(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",
+ {"relay-log", OPT_RELAY_LOG,
+ "The location and name to use for relay logs",
(gptr*) &opt_relay_logname, (gptr*) &opt_relay_logname, 0,
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"relay-log-index", OPT_RELAY_LOG_INDEX, "Undocumented",
+ {"relay-log-index", OPT_RELAY_LOG_INDEX,
+ "The location and name to use for the file that keeps a list of the last \
+relay logs",
(gptr*) &opt_relaylog_index_name, (gptr*) &opt_relaylog_index_name, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
@@ -3915,16 +3930,20 @@ Disable with --skip-isam",
{"skip-stack-trace", OPT_SKIP_STACK_TRACE,
"Don't print a stack trace on failure", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
0, 0, 0, 0},
- {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables",
+ {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. Depricated option. Use --skip-symbolic-links instead",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"skip-thread-priority", OPT_SKIP_PRIOR,
"Don't give threads different priorities.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
- {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, "Undocumented",
+ {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE,
+ "The location and name of the file that remembers where the SQL replication \
+thread is in the relay logs",
(gptr*) &relay_log_info_file, (gptr*) &relay_log_info_file, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_REPLICATION
- {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, "Undocumented",
+ {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR,
+ "The location where the slave should put its temporary files when \
+replicating a LOAD DATA INFILE command",
(gptr*) &slave_load_tmpdir, (gptr*) &slave_load_tmpdir, 0, GET_STR_ALLOC,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS,
@@ -3965,11 +3984,12 @@ Disable with --skip-isam",
{"external-locking", OPT_USE_LOCKING, "Use system (external) locking. With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running",
(gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
-#ifdef USE_SYMDIR
- {"use-symbolic-links", 's', "Enable symbolic link support",
+ {"use-symbolic-links", 's', "Enable symbolic link support. Depricated option; Use --symbolic-links instead",
+ (gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
+ IF_PURIFY(0,1), 0, 0, 0, 0, 0},
+ {"--symbolic-links", 's', "Enable symbolic link support",
(gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
IF_PURIFY(0,1), 0, 0, 0, 0, 0},
-#endif
{"user", 'u', "Run mysqld daemon as user", 0, 0, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit", 0, 0, 0, GET_NO_ARG,
@@ -4147,7 +4167,7 @@ Disable with --skip-isam",
(gptr*) &max_connect_errors, (gptr*) &max_connect_errors, 0, GET_ULONG,
REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0},
{"max_delayed_threads", OPT_MAX_DELAYED_THREADS,
- "Don't start more than this number of threads to handle INSERT DELAYED statements. This option does not yet have effect (on TODO), unless it is set to zero, which means INSERT DELAYED is not used.",
+ "Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.",
(gptr*) &max_insert_delayed_threads, (gptr*) &max_insert_delayed_threads,
0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0},
{"max_error_count", OPT_MAX_ERROR_COUNT,
@@ -4209,12 +4229,18 @@ Disable with --skip-isam",
(gptr*) &global_system_variables.myisam_max_extra_sort_file_size,
(gptr*) &max_system_variables.myisam_max_extra_sort_file_size,
0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH,
- 0, ~0L, 0, 1, 0},
+ 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0},
{"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE,
"Don't use the fast sort index method to created index if the temporary file would get bigger than this!",
(gptr*) &global_system_variables.myisam_max_sort_file_size,
(gptr*) &max_system_variables.myisam_max_sort_file_size, 0,
- GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, ~0L, 0, 1024*1024, 0},
+ GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE,
+ 0, 1024*1024, 0},
+ {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS,
+ "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.",
+ (gptr*) &global_system_variables.myisam_repair_threads,
+ (gptr*) &max_system_variables.myisam_repair_threads, 0,
+ GET_ULONG, REQUIRED_ARG, 1, 1, ~0L, 0, 1, 0},
{"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE,
"The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.",
(gptr*) &global_system_variables.myisam_sort_buff_size,
@@ -4289,7 +4315,7 @@ Disable with --skip-isam",
(gptr*) &relay_log_purge, 0, GET_BOOL, NO_ARG,
1, 0, 1, 0, 1, 0},
{"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT,
- "Max space to use for all relay logs",
+ "Maximum space to use for all relay logs",
(gptr*) &relay_log_space_limit,
(gptr*) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L,
(longlong) ULONG_MAX, 0, 1, 0},
@@ -4303,6 +4329,11 @@ Disable with --skip-isam",
(gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
#endif /* HAVE_REPLICATION */
+ {"read-only", OPT_READONLY,
+ "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege",
+ (gptr*) &opt_readonly,
+ (gptr*) &opt_readonly,
+ 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
{"slow_launch_time", OPT_SLOW_LAUNCH_TIME,
"If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.",
(gptr*) &slow_launch_time, (gptr*) &slow_launch_time, 0, GET_ULONG,
@@ -4844,9 +4875,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
myisam_concurrent_insert=0;
myisam_recover_options= HA_RECOVER_NONE;
- my_disable_symlinks=1;
my_use_symdir=0;
- have_symlink=SHOW_OPTION_DISABLED;
ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
#ifdef HAVE_QUERY_CACHE
query_cache_size=0;
@@ -4893,9 +4922,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
test_flags|=TEST_NO_STACKTRACE;
break;
case (int) OPT_SKIP_SYMLINKS:
- my_disable_symlinks=1;
my_use_symdir=0;
- have_symlink=SHOW_OPTION_DISABLED;
break;
case (int) OPT_BIND_ADDRESS:
if (argument && my_isdigit(mysqld_charset, argument[0]))
@@ -5167,11 +5194,9 @@ static void get_options(int argc,char **argv)
my_disable_locking= myisam_single_user= test(opt_external_locking == 0);
my_default_record_cache_size=global_system_variables.read_buff_size;
myisam_max_temp_length=
- (my_off_t) min(global_system_variables.myisam_max_sort_file_size,
- (ulonglong) MAX_FILE_SIZE);
+ (my_off_t) global_system_variables.myisam_max_sort_file_size;
myisam_max_extra_temp_length=
- (my_off_t) min(global_system_variables.myisam_max_extra_sort_file_size,
- (ulonglong) MAX_FILE_SIZE);
+ (my_off_t) global_system_variables.myisam_max_extra_sort_file_size;
/* Set global variables based on startup options */
myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 550fb772fce..8271d971782 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -48,13 +48,6 @@
can't normally do this the client should have a bigger max_allowed_packet.
*/
-#ifdef MYSQL_SERVER
-#define USE_QUERY_CACHE
-extern uint test_flags;
-extern void query_cache_insert(NET *net, const char *packet, ulong length);
-#else
-#endif
-
#if defined(__WIN__) || !defined(MYSQL_SERVER)
/* The following is because alarms doesn't work on windows. */
#define NO_ALARM
@@ -63,16 +56,23 @@ extern void query_cache_insert(NET *net, const char *packet, ulong length);
#ifndef NO_ALARM
#include "my_pthread.h"
void sql_print_error(const char *format,...);
-extern ulong bytes_sent, bytes_received;
-extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#else
-#undef statistic_add
-#define statistic_add(A,B,C)
#define DONT_USE_THR_ALARM
#endif /* NO_ALARM */
#include "thr_alarm.h"
+#ifdef MYSQL_SERVER
+#define USE_QUERY_CACHE
+extern uint test_flags;
+extern void query_cache_insert(NET *net, const char *packet, ulong length);
+extern ulong bytes_sent, bytes_received;
+extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
+#else
+#undef statistic_add
+#define statistic_add(A,B,C)
+#endif
+
#define TEST_BLOCKING 8
#define MAX_PACKET_LENGTH (256L*256L*256L-1)
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 7526772cd09..d40f2e22ea2 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -283,7 +283,7 @@ typedef struct st_qsel_param {
KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY];
MEM_ROOT *mem_root;
table_map prev_tables,read_tables,current_table;
- uint baseflag,keys,max_key_part;
+ uint baseflag, keys, max_key_part, range_count;
uint real_keynr[MAX_KEY];
char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
@@ -709,8 +709,10 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
(double) keys_per_block);
}
else
- found_read_time= head->file->read_time(found_records)+
- (double) found_records / TIME_FOR_COMPARE;
+ found_read_time= (head->file->read_time(keynr,
+ param.range_count,
+ found_records)+
+ (double) found_records / TIME_FOR_COMPARE);
if (read_time > found_read_time)
{
read_time=found_read_time;
@@ -2074,11 +2076,12 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
if (!tree)
DBUG_RETURN(HA_POS_ERROR); // Can't use it
+ param->max_key_part=0;
+ param->range_count=0;
if (tree->type == SEL_ARG::IMPOSSIBLE)
DBUG_RETURN(0L); // Impossible select. return
if (tree->type != SEL_ARG::KEY_RANGE || tree->part != 0)
DBUG_RETURN(HA_POS_ERROR); // Don't use tree
- param->max_key_part=0;
records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0);
if (records != HA_POS_ERROR)
{
@@ -2146,6 +2149,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
}
keynr=param->real_keynr[idx];
+ param->range_count++;
if (!tmp_min_flag && ! tmp_max_flag &&
(uint) key_tree->part+1 == param->table->key_info[keynr].key_parts &&
(param->table->key_info[keynr].flags & HA_NOSAME) &&
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 1e116518da0..b96c6383bbb 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -69,8 +69,10 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
RETURN VALUES
0 No errors
- 1 if all items was resolved
- -1 on impossible conditions
+ 1 if all items were resolved
+ -1 on impossible conditions
+ OR an error number from my_base.h HA_ERR_... if a deadlock or a lock
+ wait timeout happens, for example
*/
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
@@ -82,6 +84,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
table_map where_tables= 0;
Item *item;
COND *org_conds= conds;
+ int error;
if (conds)
where_tables= conds->used_tables();
@@ -131,7 +134,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if (outer_tables || (table->table->file->table_flags() &
HA_NOT_EXACT_COUNT))
{
- const_result= 0; // Can't optimize left join
+ const_result= 0; // Can't optimize left join
break;
}
tables->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -164,6 +167,11 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
Item_field *item_field= ((Item_field*) expr);
TABLE *table= item_field->field->table;
+ if ((table->file->table_flags() & HA_NOT_READ_AFTER_KEY))
+ {
+ const_result=0;
+ break;
+ }
/*
Look for a partial key that can be used for optimization.
If we succeed, ref.key_length will contain the length of
@@ -179,18 +187,21 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
- bool error= table->file->index_init((uint) ref.key);
+ error= table->file->index_init((uint) ref.key);
if (!ref.key_length)
- error= table->file->index_first(table->record[0]) != 0;
+ error= table->file->index_first(table->record[0]);
else
- error= table->file->index_read(table->record[0],key_buff,
- ref.key_length,
- range_fl & NEAR_MIN ?
- HA_READ_AFTER_KEY :
- HA_READ_KEY_OR_NEXT) ||
- reckey_in_range(0, &ref, item_field->field,
- conds, range_fl, prefix_len);
+ {
+ error= table->file->index_read(table->record[0],key_buff,
+ ref.key_length,
+ range_fl & NEAR_MIN ?
+ HA_READ_AFTER_KEY :
+ HA_READ_KEY_OR_NEXT);
+ if (!error && reckey_in_range(0, &ref, item_field->field,
+ conds, range_fl, prefix_len))
+ error= HA_ERR_KEY_NOT_FOUND;
+ }
if (table->key_read)
{
table->key_read= 0;
@@ -198,10 +209,16 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
table->file->index_end();
if (error)
- return -1; // No rows matching where
+ {
+ if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
+ return -1; // No rows matching WHERE
+ /* HA_ERR_LOCK_DEADLOCK or some other error */
+ table->file->print_error(error, MYF(0));
+ return(error);
+ }
removed_tables|= table->map;
}
- else if (!expr->const_item()) // This is VERY seldom false
+ else if (!expr->const_item()) // This is VERY seldom false
{
const_result= 0;
break;
@@ -249,18 +266,20 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
const_result= 0;
break;
}
- bool error= table->file->index_init((uint) ref.key);
+ error= table->file->index_init((uint) ref.key);
if (!ref.key_length)
- error=table->file->index_last(table->record[0]) != 0;
+ error= table->file->index_last(table->record[0]);
else
- error= table->file->index_read(table->record[0], key_buff,
- ref.key_length,
- range_fl & NEAR_MAX ?
- HA_READ_BEFORE_KEY :
- HA_READ_PREFIX_LAST_OR_PREV) ||
- reckey_in_range(1, &ref, item_field->field,
- conds, range_fl, prefix_len);
+ {
+ error= table->file->index_read(table->record[0], key_buff,
+ ref.key_length,
+ range_fl & NEAR_MAX ?
+ HA_READ_BEFORE_KEY :
+ HA_READ_PREFIX_LAST_OR_PREV);
+ if (!error && reckey_in_range(1, &ref, item_field->field,
+ conds, range_fl, prefix_len))
+ error= HA_ERR_KEY_NOT_FOUND;
if (table->key_read)
{
table->key_read=0;
@@ -268,10 +287,16 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
table->file->index_end();
if (error)
- return -1; // Impossible query
+ {
+ if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
+ return -1; // No rows matching WHERE
+ /* HA_ERR_LOCK_DEADLOCK or some other error */
+ table->file->print_error(error, MYF(0));
+ return(error);
+ }
removed_tables|= table->map;
}
- else if (!expr->const_item()) // This is VERY seldom false
+ else if (!expr->const_item()) // This is VERY seldom false
{
const_result= 0;
break;
@@ -597,6 +622,10 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
(if we have a condition field = const, prefix_len contains the length
of the whole search key)
+ NOTE
+ This function may set table->key_read to 1, which must be reset after
+ index is used! (This can only happen when function returns 1)
+
RETURN
0 Index can not be used to optimize MIN(field)/MAX(field)
1 Can use key to optimize MIN()/MAX()
diff --git a/sql/records.cc b/sql/records.cc
index 9d8627bc1fc..783ca663dfe 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -16,7 +16,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Functions to read, write and lock records */
+/* Functions for easy reading of records, possible through a cache */
#include "mysql_priv.h"
diff --git a/sql/set_var.cc b/sql/set_var.cc
index e4adbb0a318..0071f50f7a0 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -87,6 +87,8 @@ static void fix_max_join_size(THD *thd, enum_var_type type);
static void fix_query_cache_size(THD *thd, enum_var_type type);
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
static void fix_key_buffer_size(THD *thd, enum_var_type type);
+static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type);
+static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
static byte *get_error_count(THD *thd);
static byte *get_warning_count(THD *thd);
@@ -184,8 +186,9 @@ sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables",
&SV::max_tmp_tables);
sys_var_long_ptr sys_max_write_lock_count("max_write_lock_count",
&max_write_lock_count);
-sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size);
-sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size);
+sys_var_thd_ulonglong sys_myisam_max_extra_sort_file_size("myisam_max_extra_sort_file_size", &SV::myisam_max_extra_sort_file_size, fix_myisam_max_extra_sort_file_size, 1);
+sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
+sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads);
sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
sys_var_thd_ulong sys_net_buffer_length("net_buffer_length",
&SV::net_buffer_length);
@@ -229,6 +232,8 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
&slave_net_timeout);
#endif
+sys_var_bool_ptr sys_readonly("read_only",
+ &opt_readonly);
sys_var_long_ptr sys_slow_launch_time("slow_launch_time",
&slow_launch_time);
sys_var_thd_ulong sys_sort_buffer("sort_buffer_size",
@@ -249,6 +254,11 @@ sys_var_thd_ulong sys_tmp_table_size("tmp_table_size",
&SV::tmp_table_size);
sys_var_thd_ulong sys_net_wait_timeout("wait_timeout",
&SV::net_wait_timeout);
+
+#ifdef HAVE_INNOBASE_DB
+sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct",
+ &srv_max_buf_pool_modified_pct);
+#endif
/*
Variables that are bits in THD
*/
@@ -267,7 +277,7 @@ static sys_var_thd_bit sys_sql_big_tables("sql_big_tables",
#endif
static sys_var_thd_bit sys_big_selects("sql_big_selects",
set_option_bit,
- OPTION_BIG_TABLES);
+ OPTION_BIG_SELECTS);
static sys_var_thd_bit sys_log_off("sql_log_off",
set_option_bit,
OPTION_LOG_OFF);
@@ -395,6 +405,7 @@ sys_var *sys_variables[]=
&sys_max_write_lock_count,
&sys_myisam_max_extra_sort_file_size,
&sys_myisam_max_sort_file_size,
+ &sys_myisam_repair_threads,
&sys_myisam_sort_buffer_size,
&sys_net_buffer_length,
&sys_net_read_timeout,
@@ -426,6 +437,7 @@ sys_var *sys_variables[]=
&sys_slave_net_timeout,
&sys_slave_skip_counter,
#endif
+ &sys_readonly,
&sys_slow_launch_time,
&sys_sort_buffer,
&sys_sql_big_tables,
@@ -439,6 +451,9 @@ sys_var *sys_variables[]=
&sys_timestamp,
&sys_tmp_table_size,
&sys_tx_isolation,
+#ifdef HAVE_INNOBASE_DB
+ &sys_innodb_max_dirty_pages_pct,
+#endif
&sys_unique_checks,
&sys_warning_count
};
@@ -514,6 +529,7 @@ struct show_var_st init_vars[]= {
{"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG},
{"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
{"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
+ {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS},
#endif
{sys_interactive_timeout.name,(char*) &sys_interactive_timeout, SHOW_SYS},
{sys_join_buffer_size.name, (char*) &sys_join_buffer_size, SHOW_SYS},
@@ -550,13 +566,14 @@ struct show_var_st init_vars[]= {
{sys_max_prep_stmt_count.name,(char*) &sys_max_prep_stmt_count, SHOW_SYS},
{sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS},
{sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS},
- {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
+ {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
{sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS},
{sys_myisam_max_extra_sort_file_size.name,
(char*) &sys_myisam_max_extra_sort_file_size,
SHOW_SYS},
- {sys_myisam_max_sort_file_size.name,
- (char*) &sys_myisam_max_sort_file_size,
+ {sys_myisam_max_sort_file_size.name, (char*) &sys_myisam_max_sort_file_size,
+ SHOW_SYS},
+ {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads,
SHOW_SYS},
{"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
{sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS},
@@ -595,6 +612,7 @@ struct show_var_st init_vars[]= {
#ifdef HAVE_REPLICATION
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
#endif
+ {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS},
{"skip_external_locking", (char*) &my_disable_locking, SHOW_MY_BOOL},
{"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL},
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
@@ -661,6 +679,21 @@ static void fix_low_priority_updates(THD *thd, enum_var_type type)
}
+static void
+fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type)
+{
+ myisam_max_extra_temp_length=
+ (my_off_t) global_system_variables.myisam_max_extra_sort_file_size;
+}
+
+
+static void
+fix_myisam_max_sort_file_size(THD *thd, enum_var_type type)
+{
+ myisam_max_temp_length=
+ (my_off_t) global_system_variables.myisam_max_sort_file_size;
+}
+
/*
Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR
*/
@@ -911,15 +944,22 @@ byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type)
bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
{
+ ulonglong tmp= var->value->val_int();
+
+ if ((ulonglong) tmp > max_system_variables.*offset)
+ tmp= max_system_variables.*offset;
+
+ if (option_limits)
+ tmp= (ulong) getopt_ull_limit_value(tmp, option_limits);
if (var->type == OPT_GLOBAL)
{
/* Lock is needed to make things safe on 32 bit systems */
pthread_mutex_lock(&LOCK_global_system_variables);
- global_system_variables.*offset= var->value->val_int();
+ global_system_variables.*offset= (ulonglong) tmp;
pthread_mutex_unlock(&LOCK_global_system_variables);
}
else
- thd->variables.*offset= var->value->val_int();
+ thd->variables.*offset= (ulonglong) tmp;
return 0;
}
diff --git a/sql/set_var.h b/sql/set_var.h
index fbd20228d24..667cb824fca 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -235,17 +235,27 @@ class sys_var_thd_ulonglong :public sys_var_thd
{
public:
ulonglong SV::*offset;
+ bool only_global;
sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg)
:sys_var_thd(name_arg), offset(offset_arg)
{}
sys_var_thd_ulonglong(const char *name_arg, ulonglong SV::*offset_arg,
- sys_after_update_func func)
- :sys_var_thd(name_arg,func), offset(offset_arg)
+ sys_after_update_func func, bool only_global_arg)
+ :sys_var_thd(name_arg, func), offset(offset_arg),
+ only_global(only_global_arg)
{}
bool update(THD *thd, set_var *var);
void set_default(THD *thd, enum_var_type type);
SHOW_TYPE type() { return SHOW_LONGLONG; }
byte *value_ptr(THD *thd, enum_var_type type);
+ bool check_default(enum_var_type type)
+ {
+ return type == OPT_GLOBAL && !option_limits;
+ }
+ bool check_type(enum_var_type type)
+ {
+ return (only_global && type != OPT_GLOBAL);
+ }
};
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 5a9d9f2cf29..d48b926ea15 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -114,7 +114,7 @@ v/*
"Blob polo-B¾ka '%-.64s' nemù¾e mít defaultní hodnotu",
"Nep-Bøípustné jméno databáze '%-.64s'",
"Nep-Bøípustné jméno tabulky '%-.64s'",
-"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET OPTION SQL_BIG_SELECTS=1",
+"Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET SQL_BIG_SELECTS=1",
"Nezn-Bámá chyba",
"Nezn-Bámá procedura %s",
"Chybn-Bý poèet parametrù procedury %s",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 4515f78d8e9..babdfad72f2 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -108,7 +108,7 @@
"BLOB feltet '%-.64s' kan ikke have en standard værdi",
"Ugyldigt database navn '%-.64s'",
"Ugyldigt tabel navn '%-.64s'",
-"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET OPTION SQL_BIG_SELECTS=1 hvis udtrykket er korrekt",
+"SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET SQL_BIG_SELECTS=1 hvis udtrykket er korrekt",
"Ukendt fejl",
"Ukendt procedure %s",
"Forkert antal parametre til proceduren %s",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 4b81f94eb83..1437301b144 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -116,7 +116,7 @@
"Blob veld '%-.64s' can geen standaardwaarde bevatten",
"Databasenaam '%-.64s' is niet getoegestaan",
"Niet toegestane tabelnaam '%-.64s'",
-"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET OPTION SQL_BIG_SELECTS=1 als het stament in orde is.",
+"Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET SQL_BIG_SELECTS=1 als het stament in orde is.",
"Onbekende Fout",
"Onbekende procedure %s",
"Foutief aantal parameters doorgegeven aan procedure %s",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 85ab7ac5e9f..69cf492e383 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -105,7 +105,7 @@
"BLOB column '%-.64s' can't have a default value",
"Incorrect database name '%-.100s'",
"Incorrect table name '%-.100s'",
-"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok",
+"The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok",
"Unknown error",
"Unknown procedure '%-.64s'",
"Incorrect parameter count to procedure '%-.64s'",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 20465266d46..04fb93838a9 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -110,7 +110,7 @@
"BLOB-tüüpi tulp '%-.64s' ei saa omada vaikeväärtust",
"Vigane andmebaasi nimi '%-.100s'",
"Vigane tabeli nimi '%-.100s'",
-"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET OPTION SQL_BIG_SELECTS=1",
+"SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1",
"Tundmatu viga",
"Tundmatu protseduur '%-.64s'",
"Vale parameetrite hulk protseduurile '%-.64s'",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 4af12b8dbbc..e1f49e26ad7 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -105,7 +105,7 @@
"BLOB '%-.64s' ne peut avoir de valeur par défaut",
"Nom de base de donnée illégal: '%-.64s'",
"Nom de table illégal: '%-.64s'",
-"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET OPTION SQL_BIG_SELECTS=1 si SELECT se passe bien",
+"SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien",
"Erreur inconnue",
"Procédure %s inconnue",
"Mauvais nombre de paramètres pour la procedure %s",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 525d59164b0..5831e220e4d 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -114,7 +114,7 @@
"BLOB-Feld '%-.64s' kann keinen Vorgabewert (Default-Value) besitzen.",
"Unerlaubter Datenbankname '%-.64s'.",
"Unerlaubter Tabellenname '%-.64s'.",
-"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen oder gegebenenfalls SET OPTION SQL_BIG_SELECTS=1 verwenden.",
+"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen oder gegebenenfalls SET SQL_BIG_SELECTS=1 verwenden.",
"Unbekannter Fehler.",
"Unbekannte Procedure %-.64s.",
"Falsche Parameterzahl für Procedure %-.64s.",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 26db2a19561..478a5728e19 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -105,7 +105,7 @@
"Ôá Blob ðåäßá '%-.64s' äåí ìðïñïýí íá Ý÷ïõí ðñïêáèïñéóìÝíåò ôéìÝò (default value)",
"ËÜèïò üíïìá âÜóçò äåäïìÝíùí '%-.100s'",
"ËÜèïò üíïìá ðßíáêá '%-.100s'",
-"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET OPTION SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü",
+"Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü",
"ÐñïÝêõøå Üãíùóôï ëÜèïò",
"Áãíùóôç äéáäéêáóßá '%-.64s'",
"ËÜèïò áñéèìüò ðáñáìÝôñùí óôç äéáäéêáóßá '%-.64s'",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 7ba86704cb1..8bad9427bc7 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -107,7 +107,7 @@
"A(z) '%-.64s' blob objektumnak nem lehet alapertelmezett erteke",
"Hibas adatbazisnev: '%-.100s'",
"Hibas tablanev: '%-.100s'",
-"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET OPTION SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok",
+"A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT ok",
"Ismeretlen hiba",
"Ismeretlen eljaras: '%-.64s'",
"Rossz parameter a(z) '%-.64s'eljaras szamitasanal",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 30dc00546cd..977d82fbea4 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -105,7 +105,7 @@
"Il campo BLOB '%-.64s' non puo` avere un valore di default",
"Nome database errato '%-.100s'",
"Nome tabella errato '%-.100s'",
-"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET OPTION SQL_BIG_SELECTS=1 se e` tutto a posto.",
+"La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto.",
"Errore sconosciuto",
"Procedura '%-.64s' sconosciuta",
"Numero di parametri errato per la procedura '%-.64s'",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index eb0d085bd28..5ea756c0443 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -107,7 +107,7 @@
"BLOB column '%-.64s' can't have a default value",
"»ØÄꤷ¤¿ database ̾ '%-.100s' ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹",
"»ØÄꤷ¤¿ table ̾ '%-.100s' ¤Ï¤Þ¤Á¤¬¤Ã¤Æ¤¤¤Þ¤¹",
-"The SELECT would examine too many records and probably take a very long time. Check your WHERE and use SET OPTION SQL_BIG_SELECTS=1 if the SELECT is ok",
+"The SELECT would examine more rows than MAX_JOIN_SIZE. Check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is ok",
"Unknown error",
"Unknown procedure '%-.64s'",
"Incorrect parameter count to procedure '%-.64s'",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 9747e3cbb3e..ec4971681c3 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -105,7 +105,7 @@
"BLOB Ä®·³ '%-.64s' ´Â µðÆúÆ® °ªÀ» °¡Áú ¼ö ¾ø½À´Ï´Ù.",
"'%-.100s' µ¥ÀÌŸº£À̽ºÀÇ À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.",
"'%-.100s' Å×À̺í À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù.",
-"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET OPTION SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.",
+"SELECT ¸í·É¿¡¼­ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼­ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä.",
"¾Ë¼ö ¾ø´Â ¿¡·¯ÀÔ´Ï´Ù.",
"¾Ë¼ö ¾ø´Â ¼öÇ๮ : '%-.64s'",
"'%-.64s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆĶó¸ÞÅÍ",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 46eada87157..b2ff7cf8258 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -107,7 +107,7 @@
"Blob feltet '%-.64s' kan ikkje ha ein standard verdi",
"Ugyldig database namn '%-.64s'",
"Ugyldig tabell namn '%-.64s'",
-"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET OPTION SQL_BIG_SELECTS=1 om SELECTen er korrekt",
+"SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt",
"Ukjend feil",
"Ukjend prosedyre %s",
"Feil parameter tal til prosedyra %s",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 0f4a0852222..1d3e6f978e0 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -107,7 +107,7 @@
"Blob feltet '%-.64s' kan ikke ha en standard verdi",
"Ugyldig database navn '%-.64s'",
"Ugyldig tabell navn '%-.64s'",
-"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET OPTION SQL_BIG_SELECTS=1 om SELECTen er korrekt",
+"SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt",
"Ukjent feil",
"Ukjent prosedyre %s",
"Feil parameter antall til prosedyren %s",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index af971e6a6ee..9771a02ce34 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -105,7 +105,7 @@
"Coluna BLOB '%-.64s' não pode ter um valor padrão (default)",
"Nome de banco de dados '%-.100s' incorreto",
"Nome de tabela '%-.100s' incorreto",
-"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET OPTION SQL_BIG_SELECTS=1, se o SELECT estiver correto",
+"O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET SQL_BIG_SELECTS=1, se o SELECT estiver correto",
"Erro desconhecido",
"'Procedure' '%-.64s' desconhecida",
"Número de parâmetros incorreto para a 'procedure' '%-.64s'",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index 49cdad9adb3..2b7cc7824be 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -109,7 +109,7 @@
"Coloana BLOB '%-.64s' nu poate avea o valoare default",
"Numele bazei de date este incorect '%-.100s'",
"Numele tabelei este incorect '%-.100s'",
-"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET OPTION SQL_BIG_SELECTS=1 daca SELECT-ul e ok",
+"SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp. Verifica clauza WHERE si foloseste SET SQL_BIG_SELECTS=1 daca SELECT-ul e ok",
"Eroare unknown",
"Procedura unknown '%-.64s'",
"Procedura '%-.64s' are un numar incorect de parametri",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index ef883b38bd3..79389a43c45 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -107,7 +107,7 @@
"îÅ×ÏÚÍÏÖÎÏ ÕËÁÚÙ×ÁÔØ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ ÓÔÏÌÂÃÁ BLOB '%-.64s'",
"îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÂÁÚÙ ÄÁÎÎÙÈ '%-.100s'",
"îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÔÁÂÌÉÃÙ '%-.100s'",
-"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET OPTION SQL_BIG_SELECTS=1",
+"äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET SQL_BIG_SELECTS=1",
"îÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ",
"îÅÉÚ×ÅÓÔÎÁÑ ÐÒÏÃÅÄÕÒÁ '%-.64s'",
"îÅËÏÒÒÅËÔÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.64s'",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index a6c42c01e1c..cf0845a6f7a 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -113,7 +113,7 @@
"Pole BLOB '%-.64s' nemô¾e ma» implicitnú hodnotu",
"Neprípustné meno databázy '%-.100s'",
"Neprípustné meno tabuµky '%-.100s'",
-"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET OPTION SQL_BIG_SELECTS=1",
+"Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET SQL_BIG_SELECTS=1",
"Neznámá chyba",
"Neznámá procedúra '%-.64s'",
"Chybný poèet parametrov procedúry '%-.64s'",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 6172524ddc3..96cb7ef3316 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -106,7 +106,7 @@
"Campo Blob '%-.64s' no puede tener valores patron",
"Nombre de base de datos ilegal '%-.64s'",
"Nombre de tabla ilegal '%-.64s'",
-"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET OPTION SQL_BIG_SELECTS=1 si el SELECT esta correcto",
+"El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET SQL_BIG_SELECTS=1 si el SELECT esta correcto",
"Error desconocido",
"Procedimiento desconocido %s",
"Equivocado parametro count para procedimiento %s",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index b3cab964fd4..22147795ec3 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -105,7 +105,7 @@
"BLOB fält '%-.64s' kan inte ha ett DEFAULT-värde",
"Felaktigt databasnamn '%-.64s'",
"Felaktigt tabellnamn '%-.64s'",
-"Den angivna frågan skulle troligen ta mycket lång tid! Kontrollera din WHERE och använd SET OPTION SQL_BIG_SELECTS=1 ifall du vill hantera stora joins",
+"Den angivna frågan skulle läsa mer än MAX_JOIN_SIZE rader. Kontrollera din WHERE och använd SET SQL_BIG_SELECTS=1 eller SET MAX_JOIN_SIZE=# ifall du vill hantera stora joins",
"Oidentifierat fel",
"Okänd procedur: %s",
"Felaktigt antal parametrar till procedur %s",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 3c3507c1a2a..84ac581bdb1 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -110,7 +110,7 @@
"óÔÏ×ÂÅÃØ BLOB '%-.64s' ÎÅ ÍÏÖÅ ÍÁÔÉ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ",
"îÅצÒÎÅ ¦Í'Ñ ÂÁÚÉ ÄÁÎÎÉÈ '%-.100s'",
"îÅצÒÎÅ ¦Í'Ñ ÔÁÂÌÉæ '%-.100s'",
-"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET OPTION SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ",
+"úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ",
"îÅצÄÏÍÁ ÐÏÍÉÌËÁ",
"îÅצÄÏÍÁ ÐÒÏÃÅÄÕÒÁ '%-.64s'",
"èÉÂÎÁ ˦ÌØ˦ÓÔØ ÐÁÒÁÍÅÔÒ¦× ÐÒÏÃÅÄÕÒÉ '%-.64s'",
diff --git a/sql/slave.cc b/sql/slave.cc
index eae795ae760..be95cc16d90 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -2429,9 +2429,7 @@ err:
goto slave_begin;
#endif
my_thread_end();
-#ifndef __NETWARE__
pthread_exit(0);
-#endif /* __NETWARE__ */
DBUG_RETURN(0); // Can't return anything here
}
@@ -2573,9 +2571,7 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
goto slave_begin;
#endif
my_thread_end();
-#ifndef __NETWARE__
pthread_exit(0);
-#endif /* __NETWARE__ */
DBUG_RETURN(0); // Can't return anything here
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index b6191b2061e..accbc9cf205 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -70,7 +70,7 @@ static ACL_USER *find_acl_user(const char *host, const char *user);
static bool update_user_table(THD *thd, const char *host, const char *user,
const char *new_password);
static void update_hostname(acl_host_and_ip *host, const char *hostname);
-static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
+static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
const char *ip);
/*
@@ -496,8 +496,9 @@ void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble)
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *message,char **priv_user,
- bool old_ver, USER_RESOURCES *mqh, char *prepared_scramble,
- uint *cur_priv_version, ACL_USER **cached_user)
+ char *priv_host, bool old_ver, USER_RESOURCES *mqh,
+ char *prepared_scramble, uint *cur_priv_version,
+ ACL_USER **cached_user)
{
ulong user_access=NO_ACCESS;
*priv_user= (char*) user;
@@ -593,7 +594,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
{
Vio *vio=thd->net.vio;
/*
- In this point we know that user is allowed to connect
+ At this point we know that user is allowed to connect
from given host by given username/password pair. Now
we check if SSL is required, if user is using SSL and
if X509 certificate attributes are OK
@@ -611,8 +612,11 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
/*
Connections with non-valid certificates are dropped already
in sslaccept() anyway, so we do not check validity here.
+
+ We need to check for absence of SSL because without SSL
+ we should reject connection.
*/
- if (SSL_get_peer_certificate(vio->ssl_))
+ if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_peer_certificate(vio->ssl_))
user_access=acl_user->access;
break;
case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
@@ -622,6 +626,8 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
If cipher name is specified, we compare it to actual cipher in
use.
*/
+ if (vio_type(vio) != VIO_TYPE_SSL)
+ break;
if (acl_user->ssl_cipher)
{
DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
@@ -630,6 +636,10 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
user_access=acl_user->access;
else
{
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'",
+ acl_user->ssl_cipher,
+ SSL_get_cipher(vio->ssl_));
user_access=NO_ACCESS;
break;
}
@@ -647,6 +657,9 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
acl_user->x509_issuer, ptr));
if (strcmp(acl_user->x509_issuer, ptr))
{
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'",
+ acl_user->x509_issuer, ptr);
user_access=NO_ACCESS;
free(ptr);
break;
@@ -662,7 +675,12 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
acl_user->x509_subject, ptr));
if (strcmp(acl_user->x509_subject,ptr))
+ {
+ if (global_system_variables.log_warnings)
+ sql_print_error("X509 subject mismatch: '%s' vs '%s'",
+ acl_user->x509_subject, ptr);
user_access=NO_ACCESS;
+ }
else
user_access=acl_user->access;
free(ptr);
@@ -677,6 +695,11 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
if (!acl_user->user)
*priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
+ if (acl_user->host.hostname)
+ strmake(priv_host, acl_user->host.hostname, MAX_HOSTNAME);
+ else
+ *priv_host= 0;
+
unlock_and_exit:
VOID(pthread_mutex_unlock(&acl_cache->lock));
DBUG_RETURN(user_access);
@@ -780,7 +803,7 @@ static void acl_insert_user(const char *user, const char *host,
VOID(push_dynamic(&acl_users,(gptr) &acl_user));
if (!acl_user.host.hostname || acl_user.host.hostname[0] == wild_many
&& !acl_user.host.hostname[1])
- allow_all_hosts=1; // Anyone can connect /* purecov: tested */
+ allow_all_hosts=1; // Anyone can connect /* purecov: tested */
qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
sizeof(ACL_USER),(qsort_cmp) acl_compare);
@@ -1126,8 +1149,7 @@ bool change_password(THD *thd, const char *host, const char *user,
Simple hack to avoid cracking
*/
length=(uint) strlen(new_password);
-
- if (length!=45)
+ if (length != 45)
new_password[length & 16]=0;
VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -2060,10 +2082,10 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
-int mysql_table_grant (THD *thd, TABLE_LIST *table_list,
- List <LEX_USER> &user_list,
- List <LEX_COLUMN> &columns, ulong rights,
- bool revoke_grant)
+int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
+ List <LEX_USER> &user_list,
+ List <LEX_COLUMN> &columns, ulong rights,
+ bool revoke_grant)
{
ulong column_priv = 0;
List_iterator <LEX_USER> str_list (user_list);
@@ -2437,7 +2459,7 @@ my_bool grant_init(THD *org_thd)
mem_check->ok() && hash_insert(&column_priv_hash,(byte*) mem_check))
{
/* This could only happen if we are out memory */
- grant_option = FALSE; /* purecov: deadcode */
+ grant_option= FALSE; /* purecov: deadcode */
goto end_unlock;
}
}
@@ -2477,16 +2499,16 @@ void grant_reload(THD *thd)
rw_wrlock(&LOCK_grant);
grant_version++;
old_column_priv_hash= column_priv_hash;
- old_grant_option = grant_option;
- old_mem = memex;
+ old_grant_option= grant_option;
+ old_mem= memex;
if (grant_init(thd))
{ // Error. Revert to old hash
DBUG_PRINT("error",("Reverting to old privileges"));
grant_free(); /* purecov: deadcode */
column_priv_hash= old_column_priv_hash; /* purecov: deadcode */
- grant_option = old_grant_option; /* purecov: deadcode */
- memex = old_mem; /* purecov: deadcode */
+ grant_option= old_grant_option; /* purecov: deadcode */
+ memex= old_mem; /* purecov: deadcode */
}
else
{
@@ -2583,8 +2605,8 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
}
-bool check_grant_column (THD *thd,TABLE *table, const char *name,
- uint length, uint show_tables)
+bool check_grant_column(THD *thd,TABLE *table, const char *name,
+ uint length, uint show_tables)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
@@ -2651,6 +2673,8 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
want_access &= ~table->grant.privilege;
if (!want_access)
return 0; // Already checked
+ if (!grant_option)
+ goto err2;
rw_rdlock(&LOCK_grant);
@@ -2679,9 +2703,9 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
return 0;
/* We must use my_printf_error() here! */
- err:
+err:
rw_unlock(&LOCK_grant);
-
+err2:
const char *command="";
if (want_access & SELECT_ACL)
command ="select";
@@ -3108,11 +3132,11 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
}
}
}
- global.append(" ON ",4);
+ global.append(" ON `",5);
global.append(grant_table->db);
- global.append(".",1);
+ global.append("`.`,3);
global.append(grant_table->tname);
- global.append(" TO '",5);
+ global.append("` TO '",6);
global.append(lex_user->user.str,lex_user->user.length);
global.append("'@'",3);
global.append(lex_user->host.str,lex_user->host.length);
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index ceb866d809f..d85a281cbb5 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -136,7 +136,8 @@ void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db);
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
- const char *password,const char *scramble,char **priv_user,
+ const char *password,const char *scramble,
+ char **priv_user, char *priv_host,
bool old_ver, USER_RESOURCES *max,char* prepared_scramble,
uint *cur_priv_version, ACL_USER **cached_user);
bool acl_check_host(const char *host, const char *ip);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index fc95f5deb40..eeaf560693e 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -423,8 +423,9 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
{
DBUG_ENTER("close_thread_table");
- bool found_old_table=0;
- TABLE *table=*table_ptr;
+ bool found_old_table= 0;
+ TABLE *table= *table_ptr;
+ DBUG_ASSERT(table->key_read == 0);
*table_ptr=table->next;
if (table->version != refresh_version ||
@@ -1693,7 +1694,7 @@ Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
else
thd->dupp_field=field;
}
- if (check_grants && check_grant_column(thd,table,name,length))
+ if (check_grants && check_grant_column(thd,table,name,length))
return WRONG_GRANT;
return field;
}
@@ -1743,8 +1744,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
{
found_table=1;
Field *find=find_field_in_table(thd,tables->table,name,length,
- grant_option &&
- tables->table->grant.want_privilege,
+ test(tables->table->grant.
+ want_privilege),
1);
if (find)
{
@@ -1801,8 +1802,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
}
Field *field=find_field_in_table(thd,tables->table,name,length,
- grant_option &&
- tables->table->grant.want_privilege,
+ test(tables->table->grant.want_privilege),
allow_rowid);
if (field)
{
@@ -2098,9 +2098,10 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
(!db_name || !strcmp(tables->db,db_name))))
{
/* Ensure that we have access right to all columns */
- if (grant_option && !thd->master_access &&
- check_grant_all_columns(thd,SELECT_ACL,table) )
+ if (!(table->grant.privilege & SELECT_ACL) &&
+ check_grant_all_columns(thd,SELECT_ACL,table))
DBUG_RETURN(-1);
+
Field **ptr=table->field,*field;
thd->used_tables|=table->map;
while ((field = *ptr++))
@@ -2227,7 +2228,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
******************************************************************************/
int
-fill_record(List<Item> &fields,List<Item> &values)
+fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> f(fields),v(values);
Item *value;
@@ -2237,7 +2238,7 @@ fill_record(List<Item> &fields,List<Item> &values)
while ((field=(Item_field*) f++))
{
value=v++;
- if (value->save_in_field(field->field, 0) > 0)
+ if (value->save_in_field(field->field, 0) > 0 && !ignore_errors)
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -2245,7 +2246,7 @@ fill_record(List<Item> &fields,List<Item> &values)
int
-fill_record(Field **ptr,List<Item> &values)
+fill_record(Field **ptr,List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
Item *value;
@@ -2255,7 +2256,7 @@ fill_record(Field **ptr,List<Item> &values)
while ((field = *ptr++))
{
value=v++;
- if (value->save_in_field(field, 0) == 1)
+ if (value->save_in_field(field, 0) == 1 && !ignore_errors)
DBUG_RETURN(1);
}
DBUG_RETURN(0);
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index d8265a1b359..adc3d177fdf 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -761,11 +761,11 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
uint8 tables_type= 0;
if ((local_tables = is_cacheable(thd, thd->query_length,
- thd->query, &thd->lex, tables_used,
- &tables_type)))
+ thd->query, &thd->lex, tables_used,
+ &tables_type)))
{
NET *net= &thd->net;
- byte flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
+ byte flags= (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size == 0)
@@ -790,8 +790,10 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
*/
flags|= (byte) thd->charset()->number;
DBUG_ASSERT(thd->charset()->number < 128);
- tot_length=thd->query_length+thd->db_length+2;
- thd->query[tot_length-1] = (char) flags;
+ tot_length= thd->query_length+thd->db_length+2+sizeof(ha_rows);
+ thd->query[tot_length-1]= (char) flags;
+ memcpy((void *)(thd->query + (tot_length-sizeof(ha_rows)-1)),
+ (const void *)&thd->variables.select_limit, sizeof(ha_rows));
/* Check if another thread is processing the same query? */
Query_cache_block *competitor = (Query_cache_block *)
@@ -921,7 +923,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
}
Query_cache_block *query_block;
- tot_length=query_length+thd->db_length+2;
+ tot_length= query_length+thd->db_length+2+sizeof(ha_rows);
if (thd->db_length)
{
memcpy(sql+query_length+1, thd->db, thd->db_length);
@@ -937,10 +939,12 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Most significant bit - CLIENT_LONG_FLAG,
Other - charset number (0 no charset convertion)
*/
- flags = (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
- flags |= (byte) thd->charset()->number;
+ flags= (thd->client_capabilities & CLIENT_LONG_FLAG ? 0x80 : 0);
+ flags|= (byte) thd->charset()->number;
DBUG_ASSERT(thd->charset()->number < 128);
- sql[tot_length-1] = (char) flags;
+ sql[tot_length-1]= (char) flags;
+ memcpy((void *)(sql + (tot_length-sizeof(ha_rows)-1)),
+ (const void *)&thd->variables.select_limit, sizeof(ha_rows));
query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
tot_length);
/* Quick abort on unlocked data */
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index f579b02ee50..9f6edd629ca 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -120,6 +120,7 @@ THD::THD():user_time(0), is_fatal_error(0),
net.last_error[0]=0; // If error on boot
ull=0;
system_thread=cleanup_done=0;
+ peer_port= 0; // For SHOW PROCESSLIST
transaction.changed_tables = 0;
#ifdef __WIN__
real_id = 0;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 925afde2202..b24e28e58ec 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -358,6 +358,7 @@ struct system_variables
ulong max_prep_stmt_count;
ulong max_sort_length;
ulong max_tmp_tables;
+ ulong myisam_repair_threads;
ulong myisam_sort_buff_size;
ulong net_buffer_length;
ulong net_interactive_timeout;
@@ -434,13 +435,14 @@ public:
ip - client IP
*/
char *host,*user,*priv_user,*db,*ip;
+ char priv_host[MAX_HOSTNAME];
/* remote (peer) port */
uint16 peer_port;
/* Points to info-string that will show in SHOW PROCESSLIST */
const char *proc_info;
/* points to host if host is available, otherwise points to ip */
const char *host_or_ip;
-
+
ulong client_capabilities; /* What the client supports */
/* Determines if which non-standard SQL behaviour should be enabled */
ulong max_client_packet_length;
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index fe8a945bff8..b288dc68b42 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -401,6 +401,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
ulong found_other_files=0;
char filePath[FN_REFLEN];
TABLE_LIST *tot_list=0, **tot_list_next;
+ List<String> raid_dirs;
+
DBUG_ENTER("mysql_rm_known_files");
DBUG_PRINT("enter",("path: %s", org_path));
@@ -420,6 +422,8 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
{
char newpath[FN_REFLEN];
MY_DIR *new_dirp;
+ String *dir;
+
strxmov(newpath,org_path,"/",file->name,NullS);
unpack_filename(newpath,newpath);
if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
@@ -430,7 +434,11 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
my_dirend(dirp);
DBUG_RETURN(-1);
}
+ raid_dirs.push_back(dir=new String(newpath));
+ dir->copy();
+ continue;
}
+ found_other_files++;
continue;
}
if (find_type(fn_ext(file->name),&deletable_extentions,1+2) <= 0)
@@ -470,12 +478,19 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
deleted++;
}
}
- my_dirend(dirp);
-
if (thd->killed ||
(tot_list && mysql_rm_table_part2_with_lock(thd, tot_list, 1, 0, 1)))
+ {
+ my_dirend(dirp);
DBUG_RETURN(-1);
-
+ }
+ List_iterator<String> it(raid_dirs);
+ String *dir;
+ while ((dir= it++))
+ if (rmdir(dir->c_ptr()) < 0)
+ found_other_files++;
+ my_dirend(dirp);
+
/*
If the directory is a symbolic link, remove the link first, then
remove the directory the symbolic link pointed at
@@ -573,11 +588,11 @@ bool mysql_change_db(THD *thd, const char *name)
{
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
dbname);
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 6bb336a87a6..a12f6efb006 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -67,7 +67,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
}
/* Test if the user wants to delete all rows */
- if (!using_limit && const_cond &&
+ if (!using_limit && const_cond && (!conds || conds->val_int()) &&
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
{
deleted= table->file->records;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 7418140517c..829300859cf 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -258,7 +258,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
if (fields.elements || !value_count)
{
restore_record(table,default_values); // Get empty record
- if (fill_record(fields,*values)|| thd->net.report_error ||
+ if (fill_record(fields, *values, 0)|| thd->net.report_error ||
check_null_fields(thd,table))
{
if (values_list.elements != 1 && !thd->net.report_error)
@@ -276,7 +276,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
restore_record(table,default_values); // Get empty record
else
table->record[0][0]=table->default_values[0]; // Fix delete marker
- if (fill_record(table->field,*values) || thd->net.report_error)
+ if (fill_record(table->field,*values, 0) || thd->net.report_error)
{
if (values_list.elements != 1 && ! thd->net.report_error)
{
@@ -708,6 +708,9 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
/* no match; create a new thread to handle the table */
if (!(tmp=find_handler(thd,table_list)))
{
+ /* Don't create more than max_insert_delayed_threads */
+ if (delayed_insert_threads >= max_insert_delayed_threads)
+ DBUG_RETURN(0);
thd->proc_info="Creating delayed handler";
pthread_mutex_lock(&LOCK_delayed_create);
if (!(tmp=find_handler(thd,table_list))) // Was just created
@@ -1086,12 +1089,12 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
while (!thd->killed)
{
int error;
-#if (defined(HAVE_BROKEN_COND_TIMEDWAIT) || defined(HAVE_LINUXTHREADS))
+#if defined(HAVE_BROKEN_COND_TIMEDWAIT)
error=pthread_cond_wait(&di->cond,&di->mutex);
#else
error=pthread_cond_timedwait(&di->cond,&di->mutex,&abstime);
#ifdef EXTRA_DEBUG
- if (error && error != EINTR)
+ if (error && error != EINTR && error != ETIMEDOUT)
{
fprintf(stderr, "Got error %d from pthread_cond_timedwait\n",error);
DBUG_PRINT("error",("Got error %d from pthread_cond_timedwait",
@@ -1393,9 +1396,9 @@ bool select_insert::send_data(List<Item> &values)
return 0;
}
if (fields->elements)
- fill_record(*fields,values);
+ fill_record(*fields, values, 1);
else
- fill_record(table->field,values);
+ fill_record(table->field, values, 1);
if (thd->net.report_error || write_record(table,&info))
return 1;
if (table->next_number_field) // Clear for next record
@@ -1460,7 +1463,7 @@ bool select_insert::send_eof()
thd->cuted_fields);
if (last_insert_id)
thd->insert_id(last_insert_id); // For update log
- ::send_ok(thd,info.copied,last_insert_id,buff);
+ ::send_ok(thd,info.copied+info.deleted,last_insert_id,buff);
mysql_update_log.write(thd,thd->query,thd->query_length);
return 0;
}
@@ -1510,7 +1513,7 @@ bool select_create::send_data(List<Item> &values)
unit->offset_limit_cnt--;
return 0;
}
- fill_record(field,values);
+ fill_record(field, values, 1);
if (thd->net.report_error ||write_record(table,&info))
return 1;
if (table->next_number_field) // Clear for next record
diff --git a/sql/sql_list.h b/sql/sql_list.h
index f4cca627515..27cdc117267 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index a68eada0025..359209af5ca 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -185,7 +185,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else
{
unpack_filename(name,ex->file_name);
-#if !defined(__WIN__) && !defined(OS2)
+#if !defined(__WIN__) && !defined(OS2) && ! defined(__NETWARE__)
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(MY_WME)))
DBUG_RETURN(-1);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 1d2449839d8..45c5ea4d520 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -213,7 +213,15 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
thd->db=0;
thd->db_length=0;
USER_RESOURCES ur;
+ char tmp_passwd[SCRAMBL41_LENGTH];
DBUG_ENTER("check_user");
+
+ /*
+ Move password to temporary buffer as it may be stored in communication
+ buffer
+ */
+ strmake(tmp_passwd, passwd, sizeof(tmp_passwd));
+ passwd= tmp_passwd; // Use local copy
/* We shall avoid dupplicate user allocations here */
if (!thd->user && !(thd->user = my_strdup(user, MYF(0))))
@@ -222,7 +230,8 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
DBUG_RETURN(1);
}
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user,
- passwd, thd->scramble, &thd->priv_user,
+ passwd, thd->scramble,
+ &thd->priv_user, &thd->priv_host,
(protocol_version == 9 ||
!(thd->client_capabilities &
CLIENT_LONG_PASSWORD)),
@@ -230,9 +239,9 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
cur_priv_version,hint_user);
DBUG_PRINT("info",
- ("Capabilities: %d packet_length: %ld Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'",
+ ("Capabilities: %d packet_length: %ld Host: '%s' Login user: '%s' Priv_user: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_client_packet_length,
- thd->host_or_ip, thd->priv_user,
+ thd->host_or_ip, thd->user, thd->priv_user,
had_password ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
@@ -307,6 +316,7 @@ static int check_user(THD *thd,enum_server_command command, const char *user,
DBUG_RETURN(error);
}
send_ok(thd); // Ready to handle questions
+ thd->password= test(passwd[0]); // Remember for error messages
DBUG_RETURN(0); // ok
}
@@ -582,7 +592,6 @@ check_connections(THD *thd)
DBUG_PRINT("info",("Host: %s",thd->host));
thd->host_or_ip= thd->host;
thd->ip= 0;
- thd->peer_port= 0;
bzero((char*) &thd->remote,sizeof(struct sockaddr));
}
/* Ensure that wrong hostnames doesn't cause buffer overflows */
@@ -751,7 +760,6 @@ check_connections(THD *thd)
}
else if (res)
return -1; // Error sent from check_user()
- thd->password=using_password;
return 0;
}
@@ -1551,7 +1559,8 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
/* We must allocate some extra memory for query cache */
if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet),
packet_length,
- thd->db_length+2)))
+ thd->db_length+2+
+ sizeof(ha_rows))))
return 1;
thd->query[packet_length]=0;
thd->query_length= packet_length;
@@ -1648,6 +1657,18 @@ mysql_execute_command(THD *thd)
#endif
)
DBUG_VOID_RETURN;
+
+ /*
+ When option readonly is set deny operations which change tables.
+ Except for the replication thread and the 'super' users.
+ */
+ if (opt_readonly &&
+ !(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
+ (uc_update_queries[lex->sql_command] > 0))
+ {
+ send_error(&thd->net,ER_CANT_UPDATE_WITH_READLOCK);
+ DBUG_VOID_RETURN;
+ }
statistic_increment(com_stat[lex->sql_command],&LOCK_status);
switch (lex->sql_command) {
@@ -1832,7 +1853,8 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_SLAVE_STAT:
{
- if (check_global_access(thd, SUPER_ACL))
+ /* Accept one of two privileges */
+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
LOCK_ACTIVE_MI;
res = show_master_info(thd,active_mi);
@@ -1841,7 +1863,8 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_SHOW_MASTER_STAT:
{
- if (check_global_access(thd, SUPER_ACL))
+ /* Accept one of two privileges */
+ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
res = show_binlog_info(thd);
break;
@@ -3058,12 +3081,21 @@ error:
/****************************************************************************
Get the user (global) and database privileges for all used tables
- Returns true (error) if we can't get the privileges and we don't use
- table/column grants.
- The idea of EXTRA_ACL is that one will be granted access to the table if
- one has the asked privilege on any column combination of the table; For
- example to be able to check a table one needs to have SELECT privilege on
- any column of the table.
+
+ NOTES
+ The idea of EXTRA_ACL is that one will be granted access to the table if
+ one has the asked privilege on any column combination of the table; For
+ example to be able to check a table one needs to have SELECT privilege on
+ any column of the table.
+
+ RETURN
+ 0 ok
+ 1 If we can't get the privileges and we don't use table/column grants.
+
+ save_priv In this we store global and db level grants for the table
+ Note that we don't store db level grants if the global grants
+ is enough to satisfy the request and the global grants contains
+ a SELECT grant.
****************************************************************************/
bool
@@ -3088,7 +3120,17 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if ((thd->master_access & want_access) == want_access)
{
- *save_priv=thd->master_access;
+ /*
+ If we don't have a global SELECT privilege, we have to get the database
+ specific access rights to be able to handle queries of type
+ UPDATE t1 SET a=1 WHERE b > 0
+ */
+ db_access= thd->db_access;
+ if (!(thd->master_access & SELECT_ACL) &&
+ (db && (!thd->db || strcmp(db,thd->db))))
+ db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr,
+ thd->priv_user, db); /* purecov: inspected */
+ *save_priv=thd->master_access | db_access;
DBUG_RETURN(FALSE);
}
if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) ||
@@ -3097,7 +3139,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (!no_errors)
net_printf(thd,ER_ACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
@@ -3122,18 +3164,35 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (!no_errors)
net_printf(thd,ER_DBACCESS_DENIED_ERROR,
thd->priv_user,
- thd->host_or_ip,
+ thd->priv_host,
db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
-/* check for global access and give descriptive error message if it fails */
+/*
+ check for global access and give descriptive error message if it fails
+
+ SYNOPSIS
+ check_global_access()
+ thd Thread handler
+ want_access Use should have any of these global rights
+
+ WARNING
+ One gets access rigth if one has ANY of the rights in want_access
+ This is useful as one in most cases only need one global right,
+ but in some case we want to check if the user has SUPER or
+ REPL_CLIENT_ACL rights.
+
+ RETURN
+ 0 ok
+ 1 Access denied. In this case an error is sent to the client
+*/
bool check_global_access(THD *thd, ulong want_access)
{
char command[128];
- if ((thd->master_access & want_access) == want_access)
+ if ((thd->master_access & want_access))
return 0;
get_privilege_desc(command, sizeof(command), want_access);
net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR,
@@ -3237,6 +3296,7 @@ static bool check_merge_table_access(THD *thd, char *db,
#define used_stack(A,B) (long) (B - A)
#endif
+#ifndef EMBEDDED_LIBRARY
bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
{
long stack_used;
@@ -3250,6 +3310,7 @@ bool check_stack_overrun(THD *thd,char *buf __attribute__((unused)))
}
return 0;
}
+#endif /* EMBEDDED_LIBRARY */
#define MY_YACC_INIT 1000 // Start with big alloc
#define MY_YACC_MAX 32000 // Because of 'short'
@@ -3548,9 +3609,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->comment.str= (char*) comment->str_value.ptr();
new_field->comment.length=comment->str_value.length();
}
- if (length)
- if (!(new_field->length= (uint) atoi(length)))
- length=0; /* purecov: inspected */
+ if (length && !(new_field->length= (uint) atoi(length)))
+ length=0; /* purecov: inspected */
uint sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
if (new_field->length && new_field->decimals &&
@@ -3583,10 +3643,13 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
break;
case FIELD_TYPE_DECIMAL:
if (!length)
- new_field->length = 10; // Default length for DECIMAL
- new_field->length+=sign_len;
- if (new_field->decimals)
- new_field->length++;
+ new_field->length= 10; // Default length for DECIMAL
+ if (new_field->length < MAX_FIELD_WIDTH) // Skip wrong argument
+ {
+ new_field->length+=sign_len;
+ if (new_field->decimals)
+ new_field->length++;
+ }
break;
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
@@ -4011,6 +4074,24 @@ void add_join_on(TABLE_LIST *b,Item *expr)
}
+/*
+ Mark that we have a NATURAL JOIN between two tables
+
+ SYNOPSIS
+ add_join_natural()
+ a Table to do normal join with
+ b Do normal join with this table
+
+ IMPLEMENTATION
+ This function just marks that table b should be joined with a.
+ The function setup_cond() will create in b->on_expr a list
+ of equal condition between all fields of the same name.
+
+ SELECT * FROM t1 NATURAL LEFT JOIN t2
+ <=>
+ SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
+*/
+
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
{
b->natural_join=a;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index a39541b0fc5..b8f6de30840 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1079,6 +1079,9 @@ err:
}
send_eof(thd);
+ pthread_mutex_lock(&LOCK_thread_count);
+ thd->current_linfo = 0;
+ pthread_mutex_unlock(&LOCK_thread_count);
DBUG_RETURN(0);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 85ebb9f207f..4456c631032 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -466,8 +466,17 @@ JOIN::optimize()
if (tables_list && tmp_table_param.sum_func_count && ! group_list)
{
int res;
+ /*
+ opt_sum_query() returns -1 if no rows match to the WHERE conditions,
+ or 1 if all items were resolved, or 0, or an error number HA_ERR_...
+ */
if ((res=opt_sum_query(tables_list, all_fields, conds)))
{
+ if (res > 1)
+ {
+ delete procedure;
+ DBUG_RETURN(-1);
+ }
if (res < 0)
{
zero_result_cause= "No matching min/max row";
@@ -610,7 +619,17 @@ JOIN::optimize()
select_distinct= 0;
no_order= !order;
if (all_order_fields_used)
+ {
+ if (order && skip_sort_order)
+ {
+ /*
+ Force MySQL to read the table in sorted order to get result in
+ ORDER BY order.
+ */
+ join.tmp_table_param.quick_group=0;
+ }
order=0;
+ }
group=1; // For end_write_group
}
else
@@ -2379,7 +2398,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
if (table->quick_keys & ((key_map) 1 << key))
records= (double) table->quick_rows[key];
else
- records= (double) s->records/rec; // quick_range couldn't use key!
+ {
+ /* quick_range couldn't use key! */
+ records= (double) s->records/rec;
+ }
}
else
{
@@ -3037,6 +3059,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
join->unit->select_limit_cnt)) < 0)
DBUG_RETURN(1); // Impossible range
sel->cond=orig_cond;
+ /* Fix for EXPLAIN */
+ if (sel->quick)
+ join->best_positions[i].records_read= sel->quick->records;
}
else
{
@@ -7249,7 +7274,8 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
while ((item=li++))
{
- if (item->type() != Item::SUM_FUNC_ITEM && !item->marker)
+ if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
+ !item->const_item())
{
my_printf_error(ER_WRONG_FIELD_WITH_GROUP,
ER(ER_WRONG_FIELD_WITH_GROUP),
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2b8982f2484..a77987e4806 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -923,7 +923,10 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
protocol->store((const char*) pos, system_charset_info);
protocol->store(table->file->index_type(i), system_charset_info);
/* Comment */
- protocol->store("", system_charset_info);
+ if (!(table->keys_in_use & ((key_map) 1 << i)))
+ protocol->store("disabled",8, system_charset_info);
+ else
+ protocol->store("", 0, system_charset_info);
if (protocol->write())
DBUG_RETURN(1); /* purecov: inspected */
}
@@ -1591,6 +1594,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
case SHOW_RPL_STATUS:
end= strmov(buff, rpl_status_type[(int)rpl_status]);
break;
+#ifdef HAVE_REPLICATION
case SHOW_SLAVE_RUNNING:
{
LOCK_ACTIVE_MI;
@@ -1599,7 +1603,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
UNLOCK_ACTIVE_MI;
break;
}
-#endif /* EMBEDDED_LIBRARY */
+#endif /* HAVE_REPLICATION */
case SHOW_OPENTABLES:
end= int10_to_str((long) cached_tables(), buff, 10);
break;
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3cac88d05b2..5ff0fea0627 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -23,6 +23,7 @@
#endif
#include <hash.h>
#include <myisam.h>
+#include <my_dir.h>
#ifdef __WIN__
#include <io.h>
@@ -716,6 +717,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
column->field_name);
DBUG_RETURN(-1);
}
+ /* for fulltext keys keyseg length is 1 for blobs (it's ignored in
+ ft code anyway, and 0 (set to column width later) for char's.
+ it has to be correct col width for char's, as char data are not
+ prefixed with length (unlike blobs, where ft code takes data length
+ from a data prefix, ignoring column->length).
+ */
+ if (key->type == Key::FULLTEXT)
+ column->length=test(f_is_blob(sql_field->pack_flag));
if (f_is_blob(sql_field->pack_flag))
{
if (!(file->table_flags() & HA_BLOB_KEY))
@@ -726,15 +735,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
}
if (!column->length)
{
- if (key->type == Key::FULLTEXT)
- column->length=1; /* ft-code ignores it anyway :-) */
- else
- {
- my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
- ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0),
- column->field_name);
- DBUG_RETURN(-1);
- }
+ my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
+ ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0),
+ column->field_name);
+ DBUG_RETURN(-1);
}
}
if (key->type == Key::SPATIAL)
@@ -752,8 +756,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
{
if (key->type == Key::PRIMARY)
{
- my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
- DBUG_RETURN(-1);
+ /* Implicitly set primary key fields to NOT NULL for ISO conf. */
+ sql_field->flags|= NOT_NULL_FLAG;
+ sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
}
if (!(file->table_flags() & HA_NULL_KEY))
{
@@ -1081,12 +1086,9 @@ mysql_rename_table(enum db_type base,
Win32 clients must also have a WRITE LOCK on the table !
*/
-bool close_cached_table(THD *thd,TABLE *table)
+static void safe_remove_from_cache(THD *thd,TABLE *table)
{
- bool result=0;
- DBUG_ENTER("close_cached_table");
- safe_mutex_assert_owner(&LOCK_open);
-
+ DBUG_ENTER("safe_remove_from_cache");
if (table)
{
DBUG_PRINT("enter",("table: %s", table->real_name));
@@ -1109,16 +1111,29 @@ bool close_cached_table(THD *thd,TABLE *table)
#endif
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
+ }
+ DBUG_VOID_RETURN;
+}
+
+bool close_cached_table(THD *thd,TABLE *table)
+{
+ DBUG_ENTER("close_cached_table");
+ safe_mutex_assert_owner(&LOCK_open);
+
+ if (table)
+ {
+ safe_remove_from_cache(thd,table);
/* Close lock if this is not got with LOCK TABLES */
if (thd->lock)
{
- mysql_unlock_tables(thd, thd->lock); thd->lock=0; // Start locked threads
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0; // Start locked threads
}
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
}
- DBUG_RETURN(result);
+ DBUG_RETURN(0);
}
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
@@ -1199,69 +1214,105 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
}
-static int prepare_for_repair(THD* thd, TABLE_LIST* table,
+static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
HA_CHECK_OPT *check_opt)
{
+ int error= 0;
+ TABLE tmp_table, *table;
DBUG_ENTER("prepare_for_repair");
if (!(check_opt->sql_flags & TT_USEFRM))
- {
DBUG_RETURN(0);
- }
- else
+
+ if (!(table= table_list->table)) /* if open_ltable failed */
{
+ char name[FN_REFLEN];
+ strxmov(name, mysql_data_home, "/", table_list->db, "/",
+ table_list->real_name, NullS);
+ if (openfrm(name, "", 0, 0, 0, &tmp_table))
+ DBUG_RETURN(0); // Can't open frm file
+ table= &tmp_table;
+ }
- char from[FN_REFLEN],tmp[FN_REFLEN];
- char* db = thd->db ? thd->db : table->db;
+ /*
+ User gave us USE_FRM which means that the header in the index file is
+ trashed.
+ In this case we will try to fix the table the following way:
+ - Rename the data file to a temporary name
+ - Truncate the table
+ - Replace the new data file with the old one
+ - Run a normal repair using the new index file and the old data file
+ */
- sprintf(from, "%s/%s/%s", mysql_real_data_home, db, table->real_name);
- fn_format(from, from, "", MI_NAME_DEXT, 4);
- sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
+ char from[FN_REFLEN],tmp[FN_REFLEN+32];
+ const char **ext= table->file->bas_ext();
+ MY_STAT stat_info;
- pthread_mutex_lock(&LOCK_open);
- close_cached_table(thd,table->table);
- pthread_mutex_unlock(&LOCK_open);
+ /*
+ Check if this is a table type that stores index and data separately,
+ like ISAM or MyISAM
+ */
+ if (!ext[0] || !ext[1])
+ goto end; // No data file
- if (lock_and_wait_for_table_name(thd,table))
- DBUG_RETURN(-1);
+ strxmov(from, table->path, ext[1], NullS); // Name of data file
+ if (!my_stat(from, &stat_info, MYF(0)))
+ goto end; // Can't use USE_FRM flag
- if (my_rename(from, tmp, MYF(MY_WME)))
- {
- pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, table);
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(send_check_errmsg(thd, table, "repair",
- "Failed renaming .MYD file"));
- }
- if (mysql_truncate(thd, table, 1))
- {
- pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, table);
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(send_check_errmsg(thd, table, "repair",
- "Failed generating table from .frm file"));
- }
- if (my_rename(tmp, from, MYF(MY_WME)))
- {
- pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, table);
- pthread_mutex_unlock(&LOCK_open);
- DBUG_RETURN(send_check_errmsg(thd, table, "repair",
- "Failed restoring .MYD file"));
- }
+ sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
+
+ pthread_mutex_lock(&LOCK_open);
+ close_cached_table(thd,table_list->table);
+ pthread_mutex_unlock(&LOCK_open);
+
+ if (lock_and_wait_for_table_name(thd,table_list))
+ {
+ error= -1;
+ goto end;
+ }
+ if (my_rename(from, tmp, MYF(MY_WME)))
+ {
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, table_list);
+ pthread_mutex_unlock(&LOCK_open);
+ error= send_check_errmsg(thd, table_list, "repair",
+ "Failed renaming data file");
+ goto end;
+ }
+ if (mysql_truncate(thd, table_list, 1))
+ {
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, table_list);
+ pthread_mutex_unlock(&LOCK_open);
+ error= send_check_errmsg(thd, table_list, "repair",
+ "Failed generating table from .frm file");
+ goto end;
+ }
+ if (my_rename(tmp, from, MYF(MY_WME)))
+ {
+ pthread_mutex_lock(&LOCK_open);
+ unlock_table_name(thd, table_list);
+ pthread_mutex_unlock(&LOCK_open);
+ error= send_check_errmsg(thd, table_list, "repair",
+ "Failed restoring .MYD file");
+ goto end;
}
/*
Now we should be able to open the partially repaired table
to finish the repair in the handler later on.
*/
- if (!(table->table = reopen_name_locked_table(thd, table)))
+ if (!(table_list->table = reopen_name_locked_table(thd, table_list)))
{
pthread_mutex_lock(&LOCK_open);
- unlock_table_name(thd, table);
+ unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open);
}
- DBUG_RETURN(0);
+
+end:
+ if (table == &tmp_table)
+ closefrm(table); // Free allocated memory
+ DBUG_RETURN(error);
}
@@ -1759,9 +1810,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
case LEAVE_AS_IS:
break;
case ENABLE:
- error=table->file->activate_all_index(thd);
+ safe_remove_from_cache(thd,table);
+ error= table->file->activate_all_index(thd);
break;
case DISABLE:
+ safe_remove_from_cache(thd,table);
table->file->deactivate_non_unique_index(HA_POS_ERROR);
break;
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index fe4ca49da14..1d0f37f0042 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -76,7 +76,7 @@ bool select_union::send_data(List<Item> &values)
unit->offset_limit_cnt--;
return 0;
}
- fill_record(table->field,values);
+ fill_record(table->field, values, 1);
if (thd->net.report_error || write_record(table,&info))
{
if (thd->net.last_errno == ER_RECORD_FILE_FULL)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 7c5983a0362..1526908f025 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -62,33 +62,46 @@ int mysql_update(THD *thd,
int error=0;
uint used_index, want_privilege;
ulong query_id=thd->query_id, timestamp_query_id;
+ ha_rows updated, found;
key_map old_used_keys;
TABLE *table;
SQL_SELECT *select;
READ_RECORD info;
- TABLE_LIST *update_table_list= (TABLE_LIST*)
- thd->lex.select_lex.table_list.first;
+ TABLE_LIST *update_table_list= ((TABLE_LIST*)
+ thd->lex.select_lex.table_list.first);
+ TABLE_LIST tables;
+ List<Item> all_fields;
DBUG_ENTER("mysql_update");
+
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
if ((open_and_lock_tables(thd, table_list)))
DBUG_RETURN(-1);
+ thd->proc_info="init";
fix_tables_pointers(thd->lex.all_selects_list);
table= table_list->table;
-
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
- thd->proc_info="init";
/* Calculate "table->used_keys" based on the WHERE */
table->used_keys=table->keys_in_use;
table->quick_keys=0;
want_privilege=table->grant.want_privilege;
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
- if (setup_tables(update_table_list) ||
- setup_conds(thd,update_table_list,&conds)
- || setup_ftfuncs(&thd->lex.select_lex))
+
+ bzero((char*) &tables,sizeof(tables)); // For ORDER BY
+ tables.table= table;
+
+ if (setup_tables(update_table_list) ||
+ setup_conds(thd,update_table_list,&conds) ||
+ setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
+ order_num) ||
+ setup_order(thd, thd->lex.select_lex.ref_pointer_array,
+ &tables, fields, all_fields, order) ||
+ setup_ftfuncs(&thd->lex.select_lex))
DBUG_RETURN(-1); /* purecov: inspected */
+
+ /* Check that we are not using table that we are updating in a sub select */
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
{
@@ -96,8 +109,7 @@ int mysql_update(THD *thd,
DBUG_RETURN(-1);
}
- old_used_keys=table->used_keys; // Keys used in WHERE
-
+ old_used_keys= table->used_keys; // Keys used in WHERE
/*
Change the query_id for the timestamp column so that we can
check if this is modified directly
@@ -151,10 +163,9 @@ int mysql_update(THD *thd,
thd->lex.select_lex.options|=QUERY_NO_INDEX_USED;
if (safe_update && !using_limit)
{
- delete select;
- free_underlaid_joins(thd, &thd->lex.select_lex);
- send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
+ goto err;
}
}
init_ftfuncs(thd, &thd->lex.select_lex, 1);
@@ -175,14 +186,6 @@ int mysql_update(THD *thd,
matching rows before updating the table!
*/
table->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE);
- IO_CACHE tempfile;
- if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
- DISK_BUFFER_SIZE, MYF(MY_WME)))
- {
- delete select; /* purecov: inspected */
- free_underlaid_joins(thd, &thd->lex.select_lex);
- DBUG_RETURN(-1);
- }
if (old_used_keys & ((key_map) 1 << used_index))
{
table->key_read=1;
@@ -191,94 +194,102 @@ int mysql_update(THD *thd,
if (order)
{
+ /*
+ Doing an ORDER BY; Let filesort find and sort the rows we are going
+ to update
+ */
uint length;
SORT_FIELD *sortorder;
- TABLE_LIST tables;
List<Item> fields;
- List<Item> all_fields;
ha_rows examined_rows;
- bzero((char*) &tables,sizeof(tables));
- tables.table = table;
-
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
- MYF(MY_FAE | MY_ZEROFILL));
- if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
- order_num)||
- setup_order(thd, thd->lex.select_lex.ref_pointer_array,
- &tables, fields, all_fields, order) ||
- !(sortorder=make_unireg_sortorder(order, &length)) ||
+ MYF(MY_FAE | MY_ZEROFILL));
+ if (!(sortorder=make_unireg_sortorder(order, &length)) ||
(table->sort.found_records = filesort(thd, table, sortorder, length,
- (SQL_SELECT *) 0,
- HA_POS_ERROR, &examined_rows))
+ select, 0L, limit,
+ &examined_rows))
== HA_POS_ERROR)
{
- delete select;
- free_underlaid_joins(thd, &thd->lex.select_lex);
- DBUG_RETURN(-1);
+ free_io_cache(table);
+ goto err;
}
+ /*
+ Filesort has already found and selected the rows we want to update,
+ so we don't need the where clause
+ */
+ delete select;
+ select= 0;
}
+ else
+ {
+ /*
+ We are doing a search on a key that is updated. In this case
+ we go trough the matching rows, save a pointer to them and
+ update these in a separate loop based on the pointer.
+ */
+
+ IO_CACHE tempfile;
+ if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX,
+ DISK_BUFFER_SIZE, MYF(MY_WME)))
+ goto err;
- init_read_record(&info,thd,table,select,0,1);
- thd->proc_info="Searching rows for update";
+ init_read_record(&info,thd,table,select,0,1);
+ thd->proc_info="Searching rows for update";
+ uint tmp_limit= limit;
- while (!(error=info.read_record(&info)) && !thd->killed)
- {
- if (!(select && select->skipp_record()))
+ while (!(error=info.read_record(&info)) && !thd->killed)
{
- table->file->position(table->record[0]);
- if (my_b_write(&tempfile,table->file->ref,
- table->file->ref_length))
+ if (!(select && select->skipp_record()))
{
- error=1; /* purecov: inspected */
- break; /* purecov: inspected */
+ table->file->position(table->record[0]);
+ if (my_b_write(&tempfile,table->file->ref,
+ table->file->ref_length))
+ {
+ error=1; /* purecov: inspected */
+ break; /* purecov: inspected */
+ }
+ if (!--limit && using_limit)
+ {
+ error= -1;
+ break;
+ }
}
}
+ limit= tmp_limit;
+ end_read_record(&info);
+ /* Change select to use tempfile */
+ if (select)
+ {
+ delete select->quick;
+ if (select->free_cond)
+ delete select->cond;
+ select->quick=0;
+ select->cond=0;
+ }
else
{
- if (!(test_flags & 512)) /* For debugging */
- {
- DBUG_DUMP("record",(char*) table->record[0],table->reclength);
- }
+ select= new SQL_SELECT;
+ select->head=table;
}
+ if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
+ error=1; /* purecov: inspected */
+ select->file=tempfile; // Read row ptrs from this file
+ if (error >= 0)
+ goto err;
}
- end_read_record(&info);
-
if (table->key_read)
{
table->key_read=0;
table->file->extra(HA_EXTRA_NO_KEYREAD);
}
- /* Change select to use tempfile */
- if (select)
- {
- delete select->quick;
- if (select->free_cond)
- delete select->cond;
- select->quick=0;
- select->cond=0;
- }
- else
- {
- select= new SQL_SELECT;
- select->head=table;
- }
- if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
- error=1; /* purecov: inspected */
- select->file=tempfile; // Read row ptrs from this file
- if (error >= 0)
- {
- delete select;
- free_underlaid_joins(thd, &thd->lex.select_lex);
- DBUG_RETURN(-1);
- }
}
if (handle_duplicates == DUP_IGNORE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
init_read_record(&info,thd,table,select,0,1);
- ha_rows updated=0L,found=0L;
+ updated= found= 0;
thd->count_cuted_fields=1; /* calc cuted fields */
thd->cuted_fields=0L;
thd->proc_info="Updating";
@@ -289,7 +300,7 @@ int mysql_update(THD *thd,
if (!(select && select->skipp_record()))
{
store_record(table,record[1]);
- if (fill_record(fields,values) || thd->net.report_error)
+ if (fill_record(fields,values, 0) || thd->net.report_error)
break; /* purecov: inspected */
found++;
if (compare_record(table, query_id))
@@ -298,11 +309,6 @@ int mysql_update(THD *thd,
(byte*) table->record[0])))
{
updated++;
- if (!--limit && using_limit)
- {
- error= -1;
- break;
- }
}
else if (handle_duplicates != DUP_IGNORE ||
error != HA_ERR_FOUND_DUPP_KEY)
@@ -312,11 +318,17 @@ int mysql_update(THD *thd,
break;
}
}
+ if (!--limit && using_limit)
+ {
+ error= -1; // Simulate end of file
+ break;
+ }
}
else
table->file->unlock_row();
}
end_read_record(&info);
+ free_io_cache(table); // If ORDER BY
thd->proc_info="end";
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
transactional_table= table->file->has_transactions();
@@ -370,8 +382,17 @@ int mysql_update(THD *thd,
}
thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table);
-
DBUG_RETURN(0);
+
+err:
+ delete select;
+ free_underlaid_joins(thd, &thd->lex.select_lex);
+ if (table->key_read)
+ {
+ table->key_read=0;
+ table->file->extra(HA_EXTRA_NO_KEYREAD);
+ }
+ DBUG_RETURN(-1);
}
@@ -508,6 +529,8 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
table->pos_in_table_list= tl;
}
}
+
+
table_count= update.elements;
update_tables= (TABLE_LIST*) update.first;
@@ -732,7 +755,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
{
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
- if (fill_record(*fields_for_table[offset], *values_for_table[offset]))
+ if (fill_record(*fields_for_table[offset], *values_for_table[offset]), 0)
DBUG_RETURN(1);
found++;
if (compare_record(table, thd->query_id))
@@ -760,7 +783,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
{
int error;
TABLE *tmp_table= tmp_tables[offset];
- fill_record(tmp_table->field+1, *values_for_table[offset]);
+ fill_record(tmp_table->field+1, *values_for_table[offset], 1);
found++;
/* Store pointer to row */
memcpy((char*) tmp_table->field[0]->ptr,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e3b2c738949..659cddb1090 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -555,11 +555,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%left '^'
%right NOT
%right BINARY COLLATE_SYM
-/* These don't actually affect the way the query is really evaluated, but
- they silence a few warnings for shift/reduce conflicts. */
-%left ','
-%left STRAIGHT_JOIN JOIN_SYM
-%nonassoc CROSS INNER_SYM NATURAL LEFT RIGHT
%type <lex_str>
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
@@ -1933,7 +1928,10 @@ select_option:
Select->options|= OPTION_FOUND_ROWS;
}
| SQL_NO_CACHE_SYM { Lex->uncacheable(); }
- | SQL_CACHE_SYM { Select->options|= OPTION_TO_QUERY_CACHE; }
+ | SQL_CACHE_SYM
+ {
+ Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+ }
| ALL {}
;
@@ -2581,8 +2579,12 @@ sum_expr:
{ $$=new Item_sum_count(new Item_int((int32) 0L,1)); }
| COUNT_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_count($3); }
- | COUNT_SYM '(' DISTINCT expr_list ')'
- { $$=new Item_sum_count_distinct(* $4); }
+ | COUNT_SYM '(' DISTINCT
+ { Select->in_sum_expr++; }
+ expr_list
+ { Select->in_sum_expr--; }
+ ')'
+ { $$=new Item_sum_count_distinct(* $5); }
| GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')'
{ $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); }
| MIN_SYM '(' in_sum_expr ')'
@@ -2711,7 +2713,7 @@ join_table_list:
| join_table_list ',' join_table_list { $$=$3; }
| join_table_list normal_join join_table_list { $$=$3; }
| join_table_list STRAIGHT_JOIN join_table_list
- { $$=$3 ; $$->straight=1; }
+ { $$=$3 ; $1->next->straight=1; }
| join_table_list normal_join join_table_list ON expr
{ add_join_on($3,$5); $$=$3; }
| join_table_list normal_join join_table_list
@@ -2735,9 +2737,13 @@ join_table_list:
USING '(' using_list ')'
{ add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| join_table_list NATURAL LEFT opt_outer JOIN_SYM join_table_list
- { add_join_natural($1,$6); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; }
+ {
+ add_join_natural($1,$1->next);
+ $1->next->outer_join|=JOIN_TYPE_LEFT;
+ $$=$6;
+ }
| join_table_list RIGHT opt_outer JOIN_SYM join_table_list ON expr
- { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
+ { add_join_on($1,$7); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; }
| join_table_list RIGHT opt_outer JOIN_SYM join_table_list
{
SELECT_LEX *sel= Select->select_lex();
@@ -2745,11 +2751,15 @@ join_table_list:
sel->db2=$5->db; sel->table2=$5->alias;
}
USING '(' using_list ')'
- { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
+ { add_join_on($1,$9); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$5; }
| join_table_list NATURAL RIGHT opt_outer JOIN_SYM join_table_list
- { add_join_natural($6,$1); $1->outer_join|=JOIN_TYPE_RIGHT; $$=$1; }
+ {
+ add_join_natural($1->next,$1);
+ $1->outer_join|=JOIN_TYPE_RIGHT;
+ $$=$6;
+ }
| join_table_list NATURAL JOIN_SYM join_table_list
- { add_join_natural($1,$4); $$=$4; };
+ { add_join_natural($1,$1->next); $$=$4; };
normal_join:
JOIN_SYM {}
@@ -3076,7 +3086,7 @@ delete_limit_clause:
ULONG_NUM:
NUM { $$= strtoul($1.str,NULL,10); }
- | LONG_NUM { $$= (ulonglong) strtoll($1.str,NULL,10); }
+ | LONG_NUM { $$= (ulong) strtoll($1.str,NULL,10); }
| ULONGLONG_NUM { $$= (ulong) strtoull($1.str,NULL,10); }
| REAL_NUM { $$= strtoul($1.str,NULL,10); }
| FLOAT_NUM { $$= strtoul($1.str,NULL,10); };
diff --git a/sql/time.cc b/sql/time.cc
index 94f9cb2e5e8..eba664a690d 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -251,145 +251,6 @@ void get_date_from_daynr(long daynr,uint *ret_year,uint *ret_month,
DBUG_VOID_RETURN;
}
-/* find date from string and put it in vektor
- Input: pos = "YYMMDD" OR "YYYYMMDD" in any order or
- "xxxxx YYxxxMMxxxDD xxxx" where xxx is anything exept
- a number. Month or day mustn't exeed 2 digits, year may be 4 digits.
-*/
-
-
-#ifdef NOT_NEEDED
-
-void find_date(string pos,uint *vek,uint flag)
-{
- uint length,value;
- string start;
- DBUG_ENTER("find_date");
- DBUG_PRINT("enter",("pos: '%s' flag: %d",pos,flag));
-
- bzero((char*) vek,sizeof(int)*4);
- while (*pos && !my_isdigit(my_charset_latin1,*pos))
- pos++;
- length=(uint) strlen(pos);
- for (uint i=0 ; i< 3; i++)
- {
- start=pos; value=0;
- while (my_isdigit(my_charset_latin1,pos[0]) &&
- ((pos-start) < 2 || ((pos-start) < 4 && length >= 8 &&
- !(flag & 3))))
- {
- value=value*10 + (uint) (uchar) (*pos - '0');
- pos++;
- }
- vek[flag & 3]=value; flag>>=2;
- while (*pos && (my_ispunct(my_charset_latin1,*pos) ||
- my_isspace(my_charset_latin1,*pos)))
- pos++;
- }
- DBUG_PRINT("exit",("year: %d month: %d day: %d",vek[0],vek[1],vek[2]));
- DBUG_VOID_RETURN;
-} /* find_date */
-
-
- /* Outputs YYMMDD if input year < 100 or YYYYMMDD else */
-
-static long calc_daynr_from_week(uint year,uint week,uint day)
-{
- long daynr;
- int weekday;
-
- daynr=calc_daynr(year,1,1);
- if ((weekday= calc_weekday(daynr,0)) >= 3)
- daynr+= (7-weekday);
- else
- daynr-=weekday;
-
- return (daynr+week*7+day-8);
-}
-
-void convert_week_to_date(string date,uint flag,uint *res_length)
-{
- string format;
- uint year,vek[4];
-
- find_date(date,vek,(uint) (1*4+2*16)); /* YY-WW-DD */
- year=vek[0];
-
- get_date_from_daynr(calc_daynr_from_week(vek[0],vek[1],vek[2]),
- &vek[0],&vek[1],&vek[2]);
- *res_length=8;
- format="%04d%02d%02d";
- if (year < 100)
- {
- vek[0]= vek[0]%100;
- *res_length=6;
- format="%02d%02d%02d";
- }
- sprintf(date,format,vek[flag & 3],vek[(flag >> 2) & 3],
- vek[(flag >> 4) & 3]);
- return;
-}
-
- /* returns YYWWDD or YYYYWWDD according to input year */
- /* flag only reflects format of input date */
-
-void convert_date_to_week(string date,uint flag,uint *res_length)
-{
- uint vek[4],weekday,days,year,week,day;
- long daynr,first_daynr;
- char buff[256],*format;
-
- if (! date[0])
- {
- get_date(buff,0,0L); /* Use current date */
- find_date(buff+2,vek,(uint) (1*4+2*16)); /* YY-MM-DD */
- }
- else
- find_date(date,vek,flag);
-
- year= vek[0];
- daynr= calc_daynr(year,vek[1],vek[2]);
- first_daynr=calc_daynr(year,1,1);
-
- /* Caculate year and first daynr of year */
- if (vek[1] == 1 && (weekday=calc_weekday(first_daynr,0)) >= 3 &&
- vek[2] <= 7-weekday)
- {
- if (!year--)
- year=99;
- first_daynr=first_daynr-calc_days_in_year(year);
- }
- else if (vek[1] == 12 &&
- (weekday=calc_weekday(first_daynr+calc_days_in_year(year)),0) < 3 &&
- vek[2] > 31-weekday)
- {
- first_daynr=first_daynr+calc_days_in_year(year);
- if (year++ == 99)
- year=0;
- }
-
- /* Calulate daynr of first day of week 1 */
- if ((weekday= calc_weekday(first_daynr,0)) >= 3)
- first_daynr+= (7-weekday);
- else
- first_daynr-=weekday;
-
- days=(int) (daynr-first_daynr);
- week=days/7+1 ; day=calc_weekday(daynr,0)+1;
-
- *res_length=8;
- format="%04d%02d%02d";
- if (year < 100)
- {
- *res_length=6;
- format="%02d%02d%02d";
- }
- sprintf(date,format,year,week,day);
- return;
-}
-
-#endif
-
/* Functions to handle periods */
ulong convert_period_to_month(ulong period)
@@ -516,14 +377,14 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
else
date[6]=0;
- if (year_length == 2)
+ if (year_length == 2 && i >=2 && (date[1] || date[2]))
date[0]+= (date[0] < YY_PART_YEAR ? 2000 : 1900);
number_of_fields=i;
while (i < 6)
date[i++]=0;
if (number_of_fields < 3 || date[1] > 12 ||
date[2] > 31 || date[3] > 23 || date[4] > 59 || date[5] > 59 ||
- !fuzzy_date && (date[1] == 0 || date[2] == 0))
+ (!fuzzy_date && (date[1] == 0 || date[2] == 0)))
{
/* Only give warning for a zero date if there is some garbage after */
if (!not_zero_date) // If zero date
diff --git a/sql/unireg.h b/sql/unireg.h
index ff942f6748a..b3ea6e3fa21 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -55,6 +55,7 @@
#else
#define MAX_REFLENGTH 4 /* Max length for record ref */
#endif
+#define MAX_HOSTNAME 61 /* len+1 in mysql.user */
#define MAX_FIELD_WIDTH 256 /* Max column width +1 */
#define MAX_TABLES (sizeof(table_map)*8-2) /* Max tables in join */
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index 21722f317a1..e108ffac6af 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -455,82 +455,78 @@ uchar NEAR sort_order_tis620[]=
Arg: const source string and length of converted string
Ret: Sortable string
*/
-
+/*
+ NOTE: isn't it faster to alloc buffer in calling function?
+ */
static uchar* thai2sortable(const uchar * tstr,uint len)
{
/* We use only 3 levels (neglect capitalization). */
- const uchar* p = tstr;
+ const uchar* p= tstr;
uchar *outBuf;
-/* uchar *pRight1, *pRight2, *pRight3, *pRight4; */
-/* uchar *pLeft1, *pLeft2, *pLeft3, *pLeft4; */
uchar *pRight1, *pRight2, *pRight3;
uchar *pLeft1, *pLeft2, *pLeft3;
uint bufSize;
-
- len = (uint) strnlen((char*) tstr,len);
- bufSize = (uint) buffsize((char*) tstr);
- if(!(pRight1 = (uchar *)malloc(sizeof(uchar) * bufSize))) {
- return( (uchar*) tstr);
- }
- pLeft1 = pRight1;
- outBuf = pRight1;
- if(!(pRight2 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) {
- free(pRight1);
- return((uchar*) tstr);
- }
- pLeft2 = pRight2;
- if(!(pRight3 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) {
- free(pRight1);
- free(pRight2);
- return((uchar*) tstr);
- }
- pLeft3 = pRight3;
-/* if(!(pRight4 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) {
- free(pRight1);
- free(pRight2);
- free(pRight3);
- return((uchar*) tstr);
- }
- pLeft4 = pRight4;*/
- while(len--) {
- if(isldvowel(*p) && isconsnt(p[1])) {
- *pRight1++ = t_ctype[p[1]][0];
- *pRight2++ = t_ctype[p[1]][1];
- *pRight3++ = t_ctype[p[1]][2];
-/* *pRight4++ = t_ctype[p[1]][3]; */
- *pRight1++ = t_ctype[*p][0];
- *pRight2++ = t_ctype[*p][1];
- *pRight3++ = t_ctype[*p][2];
-/* *pRight4++ = t_ctype[*p][3]; */
+ uint RightSize;
+
+ len= (uint) strnlen((char*) tstr,len);
+ bufSize= (uint) buffsize((char*) tstr);
+ RightSize= sizeof(uchar) * (len + 1);
+ if (!(outBuf= pLeft1= pRight1=
+ (uchar *)malloc(sizeof(uchar) * bufSize + RightSize*2)))
+ return (uchar*) tstr;
+ pLeft2= pRight2= pRight1 + sizeof(uchar) * bufSize;
+ pLeft3= pRight3= pRight2 + RightSize;
+
+ while (--len)
+ {
+ int *t_ctype0= t_ctype[p[0]];
+ if (isldvowel(*p) && isconsnt(p[1]))
+ {
+ int *t_ctype1= t_ctype[p[1]];
+ *pRight1++= t_ctype1[0];
+ *pRight2++= t_ctype1[1];
+ *pRight3++= t_ctype1[2];
+ *pRight1++= t_ctype0[0];
+ *pRight2++= t_ctype0[1];
+ *pRight3++= t_ctype0[2];
+ p+= 2;
len--;
- p += 2;
- } else {
- *pRight1 = t_ctype[*p][0];
- if(*pRight1 != IGNORE) pRight1++;
- *pRight2 = t_ctype[*p][1];
- if(*pRight2 != IGNORE) pRight2++;
- *pRight3 = t_ctype[*p][2];
- if(*pRight3 != IGNORE) pRight3++;
-/* *pRight4 = t_ctype[*p][3];
- if(*pRight4 != IGNORE) pRight4++;*/
+ }
+ else
+ {
+ *pRight1= t_ctype0[0];
+ if(*pRight1 != IGNORE)
+ pRight1++;
+ *pRight2= t_ctype0[1];
+ if (*pRight2 != IGNORE)
+ pRight2++;
+ *pRight3= t_ctype0[2];
+ if(*pRight3 != IGNORE)
+ pRight3++;
p++;
}
}
- *pRight1++ = L2_BLANK;
- *pRight2++ = L3_BLANK;
-/* *pRight3++ = L4_BLANK; */
- *pRight3++ = '\0';
-/* *pRight4++ = '\0'; */
+ if (!len)
+ {
+ int *t_ctype0= t_ctype[p[0]];
+ *pRight1= t_ctype0[0];
+ if (*pRight1 != IGNORE)
+ pRight1++;
+ *pRight2= t_ctype0[1];
+ if (*pRight2 != IGNORE)
+ pRight2++;
+ *pRight3= t_ctype0[2];
+ if (*pRight3 != IGNORE)
+ pRight3++;
+ }
+ *pRight1++= L2_BLANK;
+ *pRight2++= L3_BLANK;
+ *pRight3++= '\0';
memcpy(pRight1, pLeft2, pRight2 - pLeft2);
- pRight1 += pRight2 - pLeft2;
+ pRight1+= pRight2 - pLeft2;
memcpy(pRight1, pLeft3, pRight3 - pLeft3);
-/* pRight1 += pRight3 - pLeft3; */
-/* memcpy(pRight1, pLeft4, pRight4 - pLeft4); */
- free(pLeft2);
- free(pLeft3);
-/* free(pLeft4); */
- return(outBuf);
+ return outBuf;
}
/* strncoll() replacement, compare 2 string, both are conveted to sortable string
@@ -543,12 +539,12 @@ int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
{
uchar *tc1, *tc2;
int i;
- tc1 = thai2sortable(s1, len1);
- tc2 = thai2sortable(s2, len2);
- i = strcmp((char*)tc1, (char*)tc2);
+ tc1= thai2sortable(s1, len1);
+ tc2= thai2sortable(s2, len2);
+ i= strcmp((char*)tc1, (char*)tc2);
free(tc1);
free(tc2);
- return(i);
+ return i;
}
static
@@ -572,12 +568,12 @@ int my_strnxfrm_tis620(CHARSET_INFO *cs __attribute__((unused)),
{
uint bufSize;
uchar *tmp;
- bufSize = (uint) buffsize((char*)src);
- tmp = thai2sortable(src,srclen);
+ bufSize= (uint) buffsize((char*)src);
+ tmp= thai2sortable(src,srclen);
set_if_smaller(bufSize,(uint) len);
memcpy((uchar *)dest, tmp, bufSize);
free(tmp);
- return (int) bufSize;
+ return (int)bufSize;
}
/* strcoll replacment, compare 2 strings
@@ -588,12 +584,12 @@ int my_strcoll_tis620(const uchar * s1, const uchar * s2)
{
uchar *tc1, *tc2;
int i;
- tc1 = thai2sortable(s1, (uint) strlen((char*)s1));
- tc2 = thai2sortable(s2, (uint) strlen((char*)s2));
- i = strcmp((char*)tc1, (char*)tc2);
+ tc1= thai2sortable(s1, (uint) strlen((char*)s1));
+ tc2= thai2sortable(s2, (uint) strlen((char*)s2));
+ i= strcmp((char*)tc1, (char*)tc2);
free(tc1);
free(tc2);
- return(i);
+ return i;
}
/* strxfrm replacment, convert Thai string to sortable string
@@ -605,9 +601,9 @@ int my_strxfrm_tis620(uchar * dest, const uchar * src, int len)
uint bufSize;
uchar *tmp;
- bufSize = (uint) buffsize((char*) src);
- tmp = thai2sortable(src, len);
- memcpy((uchar *) dest, tmp, bufSize);
+ bufSize= (uint)buffsize((char*) src);
+ tmp= thai2sortable(src, len);
+ memcpy((uchar *)dest, tmp, bufSize);
free(tmp);
return bufSize;
}
@@ -637,7 +633,7 @@ my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)),
if (*ptr == escape && ptr+1 != end)
{
ptr++; /* Skipp escape */
- *min_str++= *max_str++ = *ptr;
+ *min_str++ = *max_str++ = *ptr;
continue;
}
if (*ptr == w_one) /* '_' in SQL */
@@ -671,28 +667,24 @@ my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)),
*/
void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length)
{
- const uchar* fr = from;
- uchar* p = ptr;
+ const uchar* fr= from;
+ uchar* p= ptr;
+
+ if (length > field_length)
+ length= field_length;
- if(length > field_length) {
- length = field_length;
- }
while (length--)
- {
- if((istone(*fr) || isdiacrt1(*fr)) &&
+ if ((istone(*fr) || isdiacrt1(*fr)) &&
(islwrvowel(fr[1]) || isuprvowel(fr[1])))
{
- *p = fr[1];
- p[1] = *fr;
- fr += 2;
- p += 2;
+ *p= fr[1];
+ p[1]= *fr;
+ fr+= 2;
+ p+= 2;
length--;
}
else
- {
*p++ = *fr++;
- }
- }
}
diff --git a/support-files/MacOSX/Makefile.am b/support-files/MacOSX/Makefile.am
index d030ff39d84..b8047942190 100644
--- a/support-files/MacOSX/Makefile.am
+++ b/support-files/MacOSX/Makefile.am
@@ -34,7 +34,8 @@ CLEANFILES = Info.plist \
Description.plist \
StartupParameters.plist \
postinstall \
- preinstall
+ preinstall \
+ ReadMe.txt
SUFFIXES = .sh
diff --git a/support-files/MacOSX/ReadMe.txt b/support-files/MacOSX/ReadMe.txt
deleted file mode 100644
index a18c5f3aa41..00000000000
--- a/support-files/MacOSX/ReadMe.txt
+++ /dev/null
@@ -1,80 +0,0 @@
-Installation notes for MySQL on Mac OS X
-
-PLEASE READ!
-
-For more details about installing and running
-MySQL on Mac OS X, also refer to the manual,
-which is available online:
-
-http://www.mysql.com/doc/en/Mac_OS_X_installation.html
-
-NOTE: Before proceeding with the installation, please
-make sure that no other MySQL server is running!
-
-Please shut down all running MySQL instances before
-continuing by either using the MySQL Manager
-Application (on Mac OS X Server) or via "mysqladmin
-shutdown" on the command line.
-
-This MySQL package will be installed into
-"/usr/local/mysql-<version>" and will also create a
-symbolic link "/usr/local/mysql", pointing to the new
-location.
-
-A previously existing /usr/local/mysql directory will
-be renamed to /usr/local/mysql.bak before proceeding
-with the installation.
-
-Additionally, it will install the mysql grant tables by
-executing "mysql_install_db" after the installation.
-
-If you are running Mac OS X Server, you already have a
-version MySQL installed. Make sure to read Apple's help
-about installing MySQL (Run the "Help View" application,
-select "Mac OS X Server help", and do a search for MySQL
-and read the item entitled "Installing MySQL").
-
-If you previously used Marc Liyanage's MySQL packages
-for MacOS X from http://www.entropy.ch, you can simply
-follow the update instructions given on his pages.
-
-After the installation (and restoring the old database
-files, if necessary), you can start up MySQL by running
-the following commands in a terminal window:
-
- cd /usr/local/mysql
- sudo ./bin/mysqld_safe
- (Enter your password)
- (Press CTRL+Z)
- bg
- (Press CTRL+D to exit the shell)
-
-You should now be able to connect to the MySQL server,
-e.g. by running /usr/local/mysql/bin/mysql
-
-If you installed MySQL for the first time,
-PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER!
-This is done with the following two commands:
-
-/usr/local/mysql/bin/mysqladmin -u root password 'new-password'
-
-/usr/local/mysql/bin/mysqladmin -u root -h $hostname password 'new-password'
-
-Please note, that after upgrading from MySQL 3.23 to
-MySQL 4.0 it is recommended to convert the MySQL
-privilege tables using the mysql_fix_privilege_tables
-script, since some new security privileges have been
-added.
-
-Please see
-http://www.mysql.com/doc/en/Upgrading-from-3.23.html
-for more information on how to upgrade from MySQL 3.23.
-
-If you do not want to have to type the full path
-"/usr/local/mysql/bin" in front of every command, you
-can to add this directory to your PATH environment
-variable in your login script. For the default shell
-"tcsh", you can do this by running this command once:
-
-echo 'setenv PATH $PATH:/usr/local/mysql/bin' >> ~/.tcshrc
-
diff --git a/support-files/MacOSX/postinstall.sh b/support-files/MacOSX/postinstall.sh
index daaf10bda8f..f46f4480e3e 100644
--- a/support-files/MacOSX/postinstall.sh
+++ b/support-files/MacOSX/postinstall.sh
@@ -10,7 +10,7 @@
if cd @prefix@ ; then
if [ ! -f data/mysql/db.frm ] ; then
- ./scripts/mysql_install_db
+ ./scripts/mysql_install_db -IN-RPM
fi
if [ -d data ] ; then
diff --git a/support-files/Makefile.am b/support-files/Makefile.am
index ec88972c821..58808b5e255 100644
--- a/support-files/Makefile.am
+++ b/support-files/Makefile.am
@@ -25,7 +25,8 @@ EXTRA_DIST = mysql.spec.sh \
mysql-log-rotate.sh \
mysql.server.sh \
binary-configure.sh \
- magic
+ magic \
+ MySQL-shared-compat.spec.sh
SUBDIRS = MacOSX
@@ -34,7 +35,7 @@ pkgdata_DATA = my-small.cnf \
my-large.cnf \
my-huge.cnf \
mysql-log-rotate \
- mysql-@VERSION@.spec
+ MySQL-shared-compat.spec
pkgdata_SCRIPTS = mysql.server
@@ -46,7 +47,8 @@ CLEANFILES = my-small.cnf \
mysql-@VERSION@.spec \
mysql-log-rotate \
mysql.server \
- binary-configure
+ binary-configure \
+ MySQL-shared-compat.spec
mysql-@VERSION@.spec: mysql.spec
rm -f $@
diff --git a/support-files/MySQL-shared-compat.spec.sh b/support-files/MySQL-shared-compat.spec.sh
new file mode 100644
index 00000000000..f569dc20f42
--- /dev/null
+++ b/support-files/MySQL-shared-compat.spec.sh
@@ -0,0 +1,72 @@
+#
+# MySQL-shared-compat.spec
+#
+# RPM build instructions to create a "meta" package that includes two
+# versions of the MySQL shared libraries (for compatibility with
+# distributions that ship older versions of MySQL and do not provide a
+# separate "MySQL-shared" package. This spec file simply repackages two
+# already existing MySQL-shared RPMs into a single package.
+#
+# Copyright (C) 2003 MySQL AB
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; 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
+
+#
+# Change this to match the version of the shared libs you want to include
+#
+%define version4 @VERSION@
+%define version3 3.23.56
+
+Name: MySQL-shared-compat
+Packager: Lenz Grimmer <build@mysql.com>
+Vendor: MySQL AB
+License: GPL
+Group: Applications/Databases
+URL: http://www.mysql.com/
+Autoreqprov: on
+Version: %{version4}
+Release: 0
+BuildRoot: %{_tmppath}/%{name}-%{version}-build
+Obsoletes: MySQL-shared, mysql-shared
+Provides: MySQL-shared
+Summary: MySQL shared libraries for MySQL %{version4} and %{version3}
+Source0: MySQL-shared-%{version4}-0.i386.rpm
+Source1: MySQL-shared-%{version3}-1.i386.rpm
+# No need to include the RPMs once more - they can be downloaded seperately
+# if you want to rebuild this package
+NoSource: 0
+NoSource: 1
+BuildRoot: %{_tmppath}/%{name}-%{version}-build
+
+%description
+This package includes the shared libraries for both MySQL %{version3} and
+MySQL %{version4}. Install this package instead of "MySQL-shared", if you
+have applications installed that are dynamically linked against MySQL
+3.23.xx but you want to upgrade to MySQL 4.0.xx without breaking the library
+dependencies.
+
+%install
+[ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT;
+mkdir -p $RPM_BUILD_ROOT
+cd $RPM_BUILD_ROOT
+rpm2cpio %{SOURCE0} | cpio -iv --make-directories
+rpm2cpio %{SOURCE1} | cpio -iv --make-directories
+
+%clean
+[ "$RPM_BUILD_ROOT" != "/" ] && [ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT;
+
+%files
+%defattr(-, root, root)
+/usr/lib/libmysqlclient*
diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh
index 50a14b0fc96..18e926b1400 100644
--- a/support-files/my-huge.cnf.sh
+++ b/support-files/my-huge.cnf.sh
@@ -26,40 +26,96 @@ socket = @MYSQL_UNIX_ADDR@
port = @MYSQL_TCP_PORT@
socket = @MYSQL_UNIX_ADDR@
skip-locking
-set-variable = key_buffer=384M
-set-variable = max_allowed_packet=1M
-set-variable = table_cache=512
-set-variable = sort_buffer=2M
-set-variable = record_buffer=2M
-set-variable = thread_cache=8
+key_buffer = 384M
+max_allowed_packet = 1M
+table_cache = 512
+sort_buffer_size = 2M
+read_buffer_size = 2M
+myisam_sort_buffer_size = 64M
+thread_cache = 8
+query_cache_size = 32M
# Try number of CPU's*2 for thread_concurrency
-set-variable = thread_concurrency=8
-set-variable = myisam_sort_buffer_size=64M
+thread_concurrency = 8
+
+# Don't listen on a TCP/IP port at all. This can be a security enhancement,
+# if all processes that need to connect to mysqld run on the same host.
+# All interaction with mysqld must be made via Unix sockets or named pipes.
+# Note that using this option without enabling named pipes on Windows
+# (via the "enable-named-pipe" option) will render mysqld useless!
+#
+#skip-networking
# Replication Master Server (default)
-log-bin # required for replication
-server-id = 1 # required unique id between 1 and 2^32 - 1
- # defaults to 1 if master-host is not set
- # but will not function as a master if omitted
+# binary logging is required for replication
+log-bin
+
+# required unique id between 1 and 2^32 - 1
+# defaults to 1 if master-host is not set
+# but will not function as a master if omitted
+server-id = 1
-# Replication Slave Server (comment out master section to use this)
-#master-host = # MUST BE SET
-#master-user = # MUST BE SET
-#master-password = # MUST BE SET
-#master-port = # optional--defaults to 3306
-#log-bin # not required for slaves, but recommended
-#server-id = 2 # required unique id between 2 and 2^32 - 1
- # (and different from the master)
- # defaults to 2 if master-host is set
- # but will not function as a slave if omitted
+# Replication Slave (comment out master section to use this)
+#
+# To configure this host as a replication slave, you can choose between
+# two methods :
+#
+# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
+# the syntax is:
+#
+# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
+# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
+#
+# where you replace <host>, <user>, <password> by quoted strings and
+# <port> by the master's port number (3306 by default).
+#
+# Example:
+#
+# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
+# MASTER_USER='joe', MASTER_PASSWORD='secret';
+#
+# OR
+#
+# 2) Set the variables below. However, in case you choose this method, then
+# start replication for the first time (even unsuccessfully, for example
+# if you mistyped the password in master-password and the slave fails to
+# connect), the slave will create a master.info file, and any later
+# change in this file to the variables' values below will be ignored and
+# overridden by the content of the master.info file, unless you shutdown
+# the slave server, delete master.info and restart the slaver server.
+# For that reason, you may want to leave the lines below untouched
+# (commented) and instead use CHANGE MASTER TO (see above)
+#
+# required unique id between 2 and 2^32 - 1
+# (and different from the master)
+# defaults to 2 if master-host is set
+# but will not function as a slave if omitted
+#server-id = 2
+#
+# The replication master for this slave - required
+#master-host = <hostname>
+#
+# The username the slave will use for authentication when connecting
+# to the master - required
+#master-user = <username>
+#
+# The password the slave will authenticate with when connecting to
+# the master - required
+#master-password = <password>
+#
+# The port the master is listening on.
+# optional - defaults to 3306
+#master-port = <port>
+#
+# binary logging - not required for slaves, but recommended
+#log-bin
# Point the following paths to different dedicated disks
#tmpdir = /tmp/
#log-update = /path-to-dedicated-directory/hostname
# Uncomment the following if you are using BDB tables
-#set-variable = bdb_cache_size=384M
-#set-variable = bdb_max_lock=100000
+#bdb_cache_size = 384M
+#bdb_max_lock = 100000
# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = @localstatedir@/
@@ -68,17 +124,17 @@ server-id = 1 # required unique id between 1 and 2^32 - 1
#innodb_log_arch_dir = @localstatedir@/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
-#set-variable = innodb_buffer_pool_size=384M
-#set-variable = innodb_additional_mem_pool_size=20M
+#innodb_buffer_pool_size = 384M
+#innodb_additional_mem_pool_size = 20M
# Set .._log_file_size to 25 % of buffer pool size
-#set-variable = innodb_log_file_size=100M
-#set-variable = innodb_log_buffer_size=8M
-#innodb_flush_log_at_trx_commit=1
-#set-variable = innodb_lock_wait_timeout=50
+#innodb_log_file_size = 100M
+#innodb_log_buffer_size = 8M
+#innodb_flush_log_at_trx_commit = 1
+#innodb_lock_wait_timeout = 50
[mysqldump]
quick
-set-variable = max_allowed_packet=16M
+max_allowed_packet = 16M
[mysql]
no-auto-rehash
@@ -86,16 +142,16 @@ no-auto-rehash
#safe-updates
[isamchk]
-set-variable = key_buffer=256M
-set-variable = sort_buffer=256M
-set-variable = read_buffer=2M
-set-variable = write_buffer=2M
+key_buffer = 256M
+sort_buffer_size = 256M
+read_buffer = 2M
+write_buffer = 2M
[myisamchk]
-set-variable = key_buffer=256M
-set-variable = sort_buffer=256M
-set-variable = read_buffer=2M
-set-variable = write_buffer=2M
+key_buffer = 256M
+sort_buffer_size = 256M
+read_buffer = 2M
+write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh
index 3c388d611d8..2b92dc61053 100644
--- a/support-files/my-large.cnf.sh
+++ b/support-files/my-large.cnf.sh
@@ -26,21 +26,96 @@ socket = @MYSQL_UNIX_ADDR@
port = @MYSQL_TCP_PORT@
socket = @MYSQL_UNIX_ADDR@
skip-locking
-set-variable = key_buffer=256M
-set-variable = max_allowed_packet=1M
-set-variable = table_cache=256
-set-variable = sort_buffer=1M
-set-variable = record_buffer=1M
-set-variable = myisam_sort_buffer_size=64M
-set-variable = thread_cache=8
+key_buffer = 256M
+max_allowed_packet = 1M
+table_cache = 256
+sort_buffer_size = 1M
+read_buffer_size = 1M
+myisam_sort_buffer_size = 64M
+thread_cache = 8
+query_cache_size= 16M
# Try number of CPU's*2 for thread_concurrency
-set-variable = thread_concurrency=8
+thread_concurrency = 8
+
+# Don't listen on a TCP/IP port at all. This can be a security enhancement,
+# if all processes that need to connect to mysqld run on the same host.
+# All interaction with mysqld must be made via Unix sockets or named pipes.
+# Note that using this option without enabling named pipes on Windows
+# (via the "enable-named-pipe" option) will render mysqld useless!
+#
+#skip-networking
+
+# Replication Master Server (default)
+# binary logging is required for replication
log-bin
+
+# required unique id between 1 and 2^32 - 1
+# defaults to 1 if master-host is not set
+# but will not function as a master if omitted
server-id = 1
+# Replication Slave (comment out master section to use this)
+#
+# To configure this host as a replication slave, you can choose between
+# two methods :
+#
+# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
+# the syntax is:
+#
+# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
+# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
+#
+# where you replace <host>, <user>, <password> by quoted strings and
+# <port> by the master's port number (3306 by default).
+#
+# Example:
+#
+# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
+# MASTER_USER='joe', MASTER_PASSWORD='secret';
+#
+# OR
+#
+# 2) Set the variables below. However, in case you choose this method, then
+# start replication for the first time (even unsuccessfully, for example
+# if you mistyped the password in master-password and the slave fails to
+# connect), the slave will create a master.info file, and any later
+# change in this file to the variables' values below will be ignored and
+# overridden by the content of the master.info file, unless you shutdown
+# the slave server, delete master.info and restart the slaver server.
+# For that reason, you may want to leave the lines below untouched
+# (commented) and instead use CHANGE MASTER TO (see above)
+#
+# required unique id between 2 and 2^32 - 1
+# (and different from the master)
+# defaults to 2 if master-host is set
+# but will not function as a slave if omitted
+#server-id = 2
+#
+# The replication master for this slave - required
+#master-host = <hostname>
+#
+# The username the slave will use for authentication when connecting
+# to the master - required
+#master-user = <username>
+#
+# The password the slave will authenticate with when connecting to
+# the master - required
+#master-password = <password>
+#
+# The port the master is listening on.
+# optional - defaults to 3306
+#master-port = <port>
+#
+# binary logging - not required for slaves, but recommended
+#log-bin
+
+# Point the following paths to different dedicated disks
+#tmpdir = /tmp/
+#log-update = /path-to-dedicated-directory/hostname
+
# Uncomment the following if you are using BDB tables
-#set-variable = bdb_cache_size=64M
-#set-variable = bdb_max_lock=100000
+#bdb_cache_size = 64M
+#bdb_max_lock = 100000
# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = @localstatedir@/
@@ -49,21 +124,17 @@ server-id = 1
#innodb_log_arch_dir = @localstatedir@/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
-#set-variable = innodb_buffer_pool_size=256M
-#set-variable = innodb_additional_mem_pool_size=20M
+#innodb_buffer_pool_size = 256M
+#innodb_additional_mem_pool_size = 20M
# Set .._log_file_size to 25 % of buffer pool size
-#set-variable = innodb_log_file_size=64M
-#set-variable = innodb_log_buffer_size=8M
-#innodb_flush_log_at_trx_commit=1
-#set-variable = innodb_lock_wait_timeout=50
-
-# Point the following paths to different dedicated disks
-#tmpdir = /tmp/
-#log-update = /path-to-dedicated-directory/hostname
+#innodb_log_file_size = 64M
+#innodb_log_buffer_size = 8M
+#innodb_flush_log_at_trx_commit = 1
+#innodb_lock_wait_timeout = 50
[mysqldump]
quick
-set-variable = max_allowed_packet=16M
+max_allowed_packet = 16M
[mysql]
no-auto-rehash
@@ -71,16 +142,16 @@ no-auto-rehash
#safe-updates
[isamchk]
-set-variable = key_buffer=128M
-set-variable = sort_buffer=128M
-set-variable = read_buffer=2M
-set-variable = write_buffer=2M
+key_buffer = 128M
+sort_buffer_size = 128M
+read_buffer = 2M
+write_buffer = 2M
[myisamchk]
-set-variable = key_buffer=128M
-set-variable = sort_buffer=128M
-set-variable = read_buffer=2M
-set-variable = write_buffer=2M
+key_buffer = 128M
+sort_buffer_size = 128M
+read_buffer = 2M
+write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh
index a92494358cb..601ffc503c0 100644
--- a/support-files/my-medium.cnf.sh
+++ b/support-files/my-medium.cnf.sh
@@ -27,22 +27,92 @@ socket = @MYSQL_UNIX_ADDR@
port = @MYSQL_TCP_PORT@
socket = @MYSQL_UNIX_ADDR@
skip-locking
-set-variable = key_buffer=16M
-set-variable = max_allowed_packet=1M
-set-variable = table_cache=64
-set-variable = sort_buffer=512K
-set-variable = net_buffer_length=8K
-set-variable = myisam_sort_buffer_size=8M
+key_buffer = 16M
+max_allowed_packet = 1M
+table_cache = 64
+sort_buffer_size = 512K
+net_buffer_length = 8K
+myisam_sort_buffer_size = 8M
+
+# Don't listen on a TCP/IP port at all. This can be a security enhancement,
+# if all processes that need to connect to mysqld run on the same host.
+# All interaction with mysqld must be made via Unix sockets or named pipes.
+# Note that using this option without enabling named pipes on Windows
+# (via the "enable-named-pipe" option) will render mysqld useless!
+#
+#skip-networking
+
+# Replication Master Server (default)
+# binary logging is required for replication
log-bin
+
+# required unique id between 1 and 2^32 - 1
+# defaults to 1 if master-host is not set
+# but will not function as a master if omitted
server-id = 1
+# Replication Slave (comment out master section to use this)
+#
+# To configure this host as a replication slave, you can choose between
+# two methods :
+#
+# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
+# the syntax is:
+#
+# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
+# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
+#
+# where you replace <host>, <user>, <password> by quoted strings and
+# <port> by the master's port number (3306 by default).
+#
+# Example:
+#
+# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
+# MASTER_USER='joe', MASTER_PASSWORD='secret';
+#
+# OR
+#
+# 2) Set the variables below. However, in case you choose this method, then
+# start replication for the first time (even unsuccessfully, for example
+# if you mistyped the password in master-password and the slave fails to
+# connect), the slave will create a master.info file, and any later
+# change in this file to the variables' values below will be ignored and
+# overridden by the content of the master.info file, unless you shutdown
+# the slave server, delete master.info and restart the slaver server.
+# For that reason, you may want to leave the lines below untouched
+# (commented) and instead use CHANGE MASTER TO (see above)
+#
+# required unique id between 2 and 2^32 - 1
+# (and different from the master)
+# defaults to 2 if master-host is set
+# but will not function as a slave if omitted
+#server-id = 2
+#
+# The replication master for this slave - required
+#master-host = <hostname>
+#
+# The username the slave will use for authentication when connecting
+# to the master - required
+#master-user = <username>
+#
+# The password the slave will authenticate with when connecting to
+# the master - required
+#master-password = <password>
+#
+# The port the master is listening on.
+# optional - defaults to 3306
+#master-port = <port>
+#
+# binary logging - not required for slaves, but recommended
+#log-bin
+
# Point the following paths to different dedicated disks
#tmpdir = /tmp/
#log-update = /path-to-dedicated-directory/hostname
# Uncomment the following if you are using BDB tables
-#set-variable = bdb_cache_size=4M
-#set-variable = bdb_max_lock=10000
+#bdb_cache_size = 4M
+#bdb_max_lock = 10000
# Uncomment the following if you are using InnoDB tables
#innodb_data_home_dir = @localstatedir@/
@@ -51,17 +121,17 @@ server-id = 1
#innodb_log_arch_dir = @localstatedir@/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
-#set-variable = innodb_buffer_pool_size=16M
-#set-variable = innodb_additional_mem_pool_size=2M
+#innodb_buffer_pool_size = 16M
+#innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
-#set-variable = innodb_log_file_size=5M
-#set-variable = innodb_log_buffer_size=8M
-#innodb_flush_log_at_trx_commit=1
-#set-variable = innodb_lock_wait_timeout=50
+#innodb_log_file_size = 5M
+#innodb_log_buffer_size = 8M
+#innodb_flush_log_at_trx_commit = 1
+#innodb_lock_wait_timeout = 50
[mysqldump]
quick
-set-variable = max_allowed_packet=16M
+max_allowed_packet = 16M
[mysql]
no-auto-rehash
@@ -69,16 +139,16 @@ no-auto-rehash
#safe-updates
[isamchk]
-set-variable = key_buffer=20M
-set-variable = sort_buffer=20M
-set-variable = read_buffer=2M
-set-variable = write_buffer=2M
+key_buffer = 20M
+sort_buffer_size = 20M
+read_buffer = 2M
+write_buffer = 2M
[myisamchk]
-set-variable = key_buffer=20M
-set-variable = sort_buffer=20M
-set-variable = read_buffer=2M
-set-variable = write_buffer=2M
+key_buffer = 20M
+sort_buffer_size = 20M
+read_buffer = 2M
+write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
diff --git a/support-files/my-small.cnf.sh b/support-files/my-small.cnf.sh
index b8941184fe0..f9e30da78ac 100644
--- a/support-files/my-small.cnf.sh
+++ b/support-files/my-small.cnf.sh
@@ -27,12 +27,20 @@ socket = @MYSQL_UNIX_ADDR@
port = @MYSQL_TCP_PORT@
socket = @MYSQL_UNIX_ADDR@
skip-locking
-set-variable = key_buffer=16K
-set-variable = max_allowed_packet=1M
-set-variable = thread_stack=64K
-set-variable = table_cache=4
-set-variable = sort_buffer=64K
-set-variable = net_buffer_length=2K
+key_buffer = 16K
+max_allowed_packet = 1M
+table_cache = 4
+sort_buffer_size = 64K
+net_buffer_length = 2K
+thread_stack = 64K
+
+# Don't listen on a TCP/IP port at all. This can be a security enhancement,
+# if all processes that need to connect to mysqld run on the same host.
+# All interaction with mysqld must be made via Unix sockets or named pipes.
+# Note that using this option without enabling named pipes on Windows
+# (using the "enable-named-pipe" option) will render mysqld useless!
+#
+#skip-networking
server-id = 1
# Uncomment the following if you want to log updates
@@ -48,17 +56,17 @@ server-id = 1
#innodb_log_arch_dir = @localstatedir@/
# You can set .._buffer_pool_size up to 50 - 80 %
# of RAM but beware of setting memory usage too high
-#set-variable = innodb_buffer_pool_size=16M
-#set-variable = innodb_additional_mem_pool_size=2M
+#innodb_buffer_pool_size = 16M
+#innodb_additional_mem_pool_size = 2M
# Set .._log_file_size to 25 % of buffer pool size
-#set-variable = innodb_log_file_size=5M
-#set-variable = innodb_log_buffer_size=8M
-#innodb_flush_log_at_trx_commit=1
-#set-variable = innodb_lock_wait_timeout=50
+#innodb_log_file_size = 5M
+#innodb_log_buffer_size = 8M
+#innodb_flush_log_at_trx_commit = 1
+#innodb_lock_wait_timeout = 50
[mysqldump]
quick
-set-variable = max_allowed_packet=16M
+max_allowed_packet = 16M
[mysql]
no-auto-rehash
@@ -66,12 +74,12 @@ no-auto-rehash
#safe-updates
[isamchk]
-set-variable = key_buffer=8M
-set-variable = sort_buffer=8M
+key_buffer = 8M
+sort_buffer_size = 8M
[myisamchk]
-set-variable = key_buffer=8M
-set-variable = sort_buffer=8M
+key_buffer = 8M
+sort_buffer_size = 8M
[mysqlhotcopy]
interactive-timeout
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index 7340cff9cad..de01142beac 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -10,7 +10,7 @@
# started and shut down when the systems goes down.
# Comments to support chkconfig on RedHat Linux
-# chkconfig: 2345 90 90
+# chkconfig: 2345 90 20
# description: A very fast and reliable SQL database engine.
# Comments to support LSB init script conventions
@@ -18,8 +18,8 @@
# Provides: mysql
# Required-Start: $local_fs $network $remote_fs
# Required-Stop: $local_fs $network $remote_fs
-# Default-Start: 3 5
-# Default-Stop: 3 5
+# Default-Start: 2 3 4 5
+# Default-Stop: 2 3 4 5
# Short-Description: start and stop MySQL
# Description: MySQL is a very fast and reliable SQL database engine.
### END INIT INFO
@@ -118,7 +118,18 @@ else
test -z "$print_defaults" && print_defaults="my_print_defaults"
fi
-parse_arguments `$print_defaults mysqld mysql_server mysql.server`
+#
+# Test if someone changed datadir; In this case we should also read the
+# default arguments from this directory
+#
+
+extra_args=""
+if test "$datadir" != "@localstatedir@"
+then
+ extra_args="-e $datadir/my.cnf"
+fi
+
+parse_arguments `$print_defaults $extra_args mysqld mysql_server mysql.server`
# Safeguard (relative paths, core dumps..)
cd $basedir
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index 42d9ef5391c..11e850206c3 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -16,7 +16,7 @@ Copyright: GPL
Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz
Icon: mysql.gif
URL: http://www.mysql.com/
-Packager: Lenz Grimmer <lenz@mysql.com>
+Packager: Lenz Grimmer <build@mysql.com>
Vendor: MySQL AB
Requires: fileutils sh-utils
Provides: msqlormysql MySQL-server mysql
@@ -154,7 +154,7 @@ Requires: MySQL >= 4.0
%description Max
Optional MySQL server binary that supports additional features like
-Berkeley DB, OpenSSL, RAID and User Defined Functions (UDF).
+Berkeley DB, OpenSSL, RAID and User Defined Functions (UDFs).
To activate this binary, just install this package in addition to
the standard MySQL package.
@@ -536,6 +536,14 @@ fi
%attr(644, root, root) /usr/lib/mysql/libmysqld.a
%changelog
+* Fri May 16 2003 Lenz Grimmer <lenz@mysql.com>
+
+- re-enabled RAID again
+
+* Wed Apr 30 2003 Lenz Grimmer <lenz@mysql.com>
+
+- disabled MyISAM RAID (--with-raid) - it throws an assertion which
+ needs to be investigated first.
* Mon Mar 10 2003 Lenz Grimmer <lenz@mysql.com>
diff --git a/tests/big_record.pl b/tests/big_record.pl
index 08547b50823..fbe94e3540f 100755
--- a/tests/big_record.pl
+++ b/tests/big_record.pl
@@ -11,12 +11,13 @@ use Getopt::Long;
$opt_host="";
$opt_user=$opt_password="";
$opt_db="test";
-$opt_rows=200; # Test of blobs up to ($rows-1)*100000+1 bytes
+$opt_rows=20; # Test of blobs up to ($rows-1)*100000+1 bytes
$opt_compress=0;
$opt_table="test_big_record";
+$opt_loop_count=100000; # Change this to make test harder/easier
GetOptions("host=s","db=s","user=s", "password=s", "table=s", "rows=i",
- "compress") || die "Aborted";
+ "compress", "loop-count=i") || die "Aborted";
print "Connection to database $test_db\n";
@@ -42,12 +43,12 @@ $|=1; # Flush output to stdout to be able to monitor process
for ($i=0 ; $i < $opt_rows ; $i++)
{
$tmp= chr(65+($i % 16)) x ($i*100000+1);
- print $i," ",length($tmp),"\n";
$tmp= $dbh->quote($tmp);
$dbh->do("insert into $opt_table (test) values ($tmp)") or die $DBI::errstr;
+ print ".";
}
-print "Reading records\n";
+print "\nReading records\n";
$sth=$dbh->prepare("select * from $opt_table", { "mysql_use_result" => 1}) or die $dbh->errstr;
@@ -56,14 +57,40 @@ $sth->execute() or die $sth->errstr;
$i=0;
while (($row = $sth->fetchrow_arrayref))
{
- print $row->[0]," ",length($row->[1]),"\n";
die "Record $i had wrong data in blob" if ($row->[1] ne (chr(65+($i % 16)) x ($i*100000+1)));
$i++;
}
die "Didn't get all rows from server" if ($i != $opt_rows);
-$dbh->do("drop table $opt_table") or die $DBI::errstr;
+#
+# Test by insert/updating/deleting random rows for a while
+#
-print "Test ok\n";
+print "Testing insert/update/delete\n";
+
+$max_row_id= $rows;
+for ($i= 0 ; $i < $opt_loop_count ; $i++)
+{
+ $length= int(rand 65535);
+ $tmp= chr(65+($i % 16)) x $length;
+ $tmp= $dbh->quote($tmp);
+ $dbh->do("insert into $opt_table (test) values ($tmp)") or die $DBI::errstr;
+ $max_row_id++;
+ $length=int(rand 65535);
+ $tmp= chr(65+($i % 16)) x $length;
+ $tmp= $dbh->quote($tmp);
+ $id= int(rand $max_row_id);
+ $dbh->do("update $opt_table set test= $tmp where auto= $id") or die $DBI::errstr;
+ if (($i % 2) == 1)
+ {
+ $id= int(rand $max_row_id);
+ $dbh->do("delete from $opt_table where auto= $id") or die $DBI::errstr;
+ }
+ print "." if ($i % ($opt_loop_count/100) == 1);
+}
+
+# $dbh->do("drop table $opt_table") or die $DBI::errstr;
+
+print "\nTest ok\n";
exit 0;
diff --git a/tests/grant.pl b/tests/grant.pl
index 5a24127d79d..3146b7b6c25 100644
--- a/tests/grant.pl
+++ b/tests/grant.pl
@@ -63,6 +63,12 @@ user_connect(1);
#goto test;
#
+# Enable column grant code
+#
+safe_query("grant select(user) on mysql.user to $user");
+safe_query("revoke select(user) on mysql.user from $user");
+
+#
# Test grants on user level
#
@@ -76,6 +82,7 @@ user_query("select * from mysql.user where user = '$opt_user'");
user_query("select * from mysql.db where user = '$opt_user'");
safe_query("grant select on *.* to $user,$user");
safe_query("show grants for $user");
+user_connect(0);
# The following should fail
user_query("insert into mysql.user (host,user) values ('error','$opt_user')",1);
@@ -89,16 +96,21 @@ safe_query("grant select on $opt_database.not_exists to $opt_user",1);
safe_query("grant FILE on $opt_database.test to $opt_user",1);
safe_query("grant select on *.* to wrong___________user_name",1);
safe_query("grant select on $opt_database.* to wrong___________user_name",1);
+user_connect(0);
user_query("grant select on $opt_database.test to $opt_user with grant option",1);
safe_query("set password FOR ''\@''=''",1);
user_query("set password FOR root\@$opt_host = password('test')",1);
# Change privileges for user
safe_query("revoke select on *.* from $user");
-safe_query("grant create on *.* to $user");
+safe_query("grant create,update on *.* to $user");
user_connect(0);
+safe_query("flush privileges");
user_query("create table $opt_database.test (a int,b int)");
-
+user_query("update $opt_database.test set b=b+1 where a > 0",1);
+safe_query("show grants for $user");
+safe_query("revoke update on *.* from $user");
+user_connect(0);
safe_query("grant select(c) on $opt_database.test to $user",1);
safe_query("revoke select(c) on $opt_database.test from $user",1);
safe_query("grant select on $opt_database.test to wrong___________user_name",1);
@@ -217,8 +229,21 @@ user_query("update $opt_database.test set b=b+1",1);
safe_query("grant SELECT on *.* to $user");
user_connect(0);
user_query("update $opt_database.test set b=b+1");
+user_query("update $opt_database.test set b=b+1 where a > 0");
safe_query("revoke SELECT on *.* from $user");
+safe_query("grant SELECT on $opt_database.* to $user");
user_connect(0);
+user_query("update $opt_database.test set b=b+1");
+user_query("update $opt_database.test set b=b+1 where a > 0");
+safe_query("grant UPDATE on *.* to $user");
+user_connect(0);
+user_query("update $opt_database.test set b=b+1");
+user_query("update $opt_database.test set b=b+1 where a > 0");
+safe_query("revoke UPDATE on *.* from $user");
+safe_query("revoke SELECT on $opt_database.* from $user");
+user_connect(0);
+user_query("update $opt_database.test set b=b+1 where a > 0",1);
+user_query("update $opt_database.test set b=b+1",1);
# Add one privilege at a time until the user has all privileges
user_query("select * from test",1);
@@ -408,21 +433,29 @@ safe_query("grant ALL PRIVILEGES on $opt_database.test to $user identified by 'd
user_connect(0,"dummy");
safe_query("grant SELECT on $opt_database.* to $user identified by ''");
user_connect(0);
-safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user identified by ''");
+safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user identified by '', ${opt_user}\@127.0.0.1 identified by 'dummy2'");
safe_query("revoke ALL PRIVILEGES on $opt_database.* from $user identified by ''");
+
safe_query("show grants for $user");
#
# Test bug reported in SELECT INTO OUTFILE
#
-safe_query("create table $opt_database.test3 (a int)");
+safe_query("create table $opt_database.test3 (a int, b int)");
safe_query("grant SELECT on $opt_database.test3 to $user");
safe_query("grant FILE on *.* to $user");
-safe_query("insert into $opt_database.test3 values (1)");
+safe_query("insert into $opt_database.test3 values (1,1)");
user_connect(0);
user_query("select * into outfile '$tmp_table' from $opt_database.test3");
safe_query("revoke SELECT on $opt_database.test3 from $user");
+safe_query("grant SELECT(a) on $opt_database.test3 to $user");
+user_query("select a from $opt_database.test3");
+user_query("select * from $opt_database.test3",1);
+user_query("select a,b from $opt_database.test3",1);
+user_query("select b from $opt_database.test3",1);
+
+safe_query("revoke SELECT(a) on $opt_database.test3 from $user");
safe_query("revoke FILE on *.* from $user");
safe_query("drop table $opt_database.test3");
diff --git a/tests/grant.res b/tests/grant.res
index adb4494eb28..7b244f099f8 100644
--- a/tests/grant.res
+++ b/tests/grant.res
@@ -10,6 +10,8 @@ Error in execute: Can't drop database 'grant_test'. Database doesn't exist
create database grant_test
Connecting grant_user
Error on connect: Access denied for user: '@localhost' to database 'grant_test'
+grant select(user) on mysql.user to grant_user@localhost
+revoke select(user) on mysql.user from grant_user@localhost
grant select on *.* to grant_user@localhost
set password FOR grant_user2@localhost = password('test')
Error in execute: Can't find any matching row in the user table
@@ -26,6 +28,7 @@ grant select on *.* to grant_user@localhost,grant_user@localhost
show grants for grant_user@localhost
GRANT SELECT ON *.* TO 'grant_user'@'localhost'
+Connecting grant_user
insert into mysql.user (host,user) values ('error','grant_user')
Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql'
update mysql.user set host='error' WHERE user='grant_user'
@@ -48,6 +51,7 @@ grant select on *.* to wrong___________user_name
Error in execute: The host or user argument to GRANT is too long
grant select on grant_test.* to wrong___________user_name
Error in execute: The host or user argument to GRANT is too long
+Connecting grant_user
grant select on grant_test.test to grant_user with grant option
Error in execute: grant command denied to user: 'grant_user@localhost' for table 'test'
set password FOR ''@''=''
@@ -55,9 +59,17 @@ Error in execute: Can't find any matching row in the user table
set password FOR root@localhost = password('test')
Error in execute: Access denied for user: 'grant_user@localhost' to database 'mysql'
revoke select on *.* from grant_user@localhost
-grant create on *.* to grant_user@localhost
+grant create,update on *.* to grant_user@localhost
Connecting grant_user
+flush privileges
create table grant_test.test (a int,b int)
+update grant_test.test set b=b+1 where a > 0
+Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'a' in table 'test'
+show grants for grant_user@localhost
+GRANT UPDATE, CREATE ON *.* TO 'grant_user'@'localhost'
+
+revoke update on *.* from grant_user@localhost
+Connecting grant_user
grant select(c) on grant_test.test to grant_user@localhost
Error in execute: Unknown column 'c' in 'test'
revoke select(c) on grant_test.test from grant_user@localhost
@@ -198,9 +210,24 @@ Error in execute: SELECT command denied to user: 'grant_user@localhost' for colu
grant SELECT on *.* to grant_user@localhost
Connecting grant_user
update grant_test.test set b=b+1
+update grant_test.test set b=b+1 where a > 0
revoke SELECT on *.* from grant_user@localhost
+grant SELECT on grant_test.* to grant_user@localhost
+Connecting grant_user
+update grant_test.test set b=b+1
+update grant_test.test set b=b+1 where a > 0
+grant UPDATE on *.* to grant_user@localhost
Connecting grant_user
-lect * from test
+update grant_test.test set b=b+1
+update grant_test.test set b=b+1 where a > 0
+revoke UPDATE on *.* from grant_user@localhost
+revoke SELECT on grant_test.* from grant_user@localhost
+Connecting grant_user
+update grant_test.test set b=b+1 where a > 0
+Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'a' in table 'test'
+update grant_test.test set b=b+1
+Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'b' in table 'test'
+select * from test
Error in execute: select command denied to user: 'grant_user@localhost' for table 'test'
grant select on grant_test.test to grant_user@localhost
delete from grant_test.test where a=1
@@ -448,21 +475,34 @@ grant ALL PRIVILEGES on grant_test.test to grant_user@localhost identified by 'd
Connecting grant_user
grant SELECT on grant_test.* to grant_user@localhost identified by ''
Connecting grant_user
-revoke ALL PRIVILEGES on grant_test.test from grant_user@localhost identified by ''
+revoke ALL PRIVILEGES on grant_test.test from grant_user@localhost identified by '', grant_user@127.0.0.1 identified by 'dummy2'
revoke ALL PRIVILEGES on grant_test.* from grant_user@localhost identified by ''
show grants for grant_user@localhost
-create table grant_test.test3 (a int)
+GRANT USAGE ON *.* TO 'grant_user'@'localhost'
+
+create table grant_test.test3 (a int, b int)
grant SELECT on grant_test.test3 to grant_user@localhost
grant FILE on *.* to grant_user@localhost
-insert into grant_test.test3 values (1)
+insert into grant_test.test3 values (1,1)
Connecting grant_user
select * into outfile '/tmp/mysql-grant.test' from grant_test.test3
revoke SELECT on grant_test.test3 from grant_user@localhost
+grant SELECT(a) on grant_test.test3 to grant_user@localhost
+select a from grant_test.test3
+1
+
+select * from grant_test.test3
+Error in execute: select command denied to user: 'grant_user@localhost' for column 'b' in table 'test3'
+select a,b from grant_test.test3
+Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'b' in table 'test3'
+select b from grant_test.test3
+Error in execute: SELECT command denied to user: 'grant_user@localhost' for column 'b' in table 'test3'
+revoke SELECT(a) on grant_test.test3 from grant_user@localhost
revoke FILE on *.* from grant_user@localhost
drop table grant_test.test3
create table grant_test.test3 (a int)
Connecting grant_user
-Access denied for user: 'grant_user@localhost' to database 'grant_test'
+Error on connect: Access denied for user: 'grant_user@localhost' to database 'grant_test'
grant INSERT on grant_test.test3 to grant_user@localhost
Connecting grant_user
select * into outfile '/tmp/mysql-grant.test' from grant_test.test3
@@ -474,7 +514,7 @@ Error in execute: Access denied for user: 'grant_user@localhost' to database 'gr
grant LOCK TABLES on *.* to grant_user@localhost
show grants for grant_user@localhost
GRANT LOCK TABLES ON *.* TO 'grant_user'@'localhost'
-GRANT SELECT, INSERT ON grant_test.test3 TO 'grant_user'@'localhost'
+GRANT SELECT, INSERT ON `grant_test`.`test3` TO 'grant_user'@'localhost'
select * from mysql.user where user='grant_user'
127.0.0.1 grant_user *042a99b3d247ae587783f647f2d69496d390aa71eab3 N N N N N N N N N N N N N N N N N N N N N 0 0 0
@@ -487,9 +527,11 @@ revoke SELECT,INSERT,UPDATE,DELETE on grant_test.test3 from grant_user@localhost
Connecting grant_user
revoke LOCK TABLES on *.* from grant_user@localhost
Connecting grant_user
-Access denied for user: 'grant_user@localhost' to database 'grant_test'
+Error on connect: Access denied for user: 'grant_user@localhost' to database 'grant_test'
drop table grant_test.test3
show grants for grant_user@localhost
+GRANT USAGE ON *.* TO 'grant_user'@'localhost'
+
grant all on *.* to grant_user@localhost WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 2 MAX_CONNECTIONS_PER_HOUR 3
show grants for grant_user@localhost
GRANT ALL PRIVILEGES ON *.* TO 'grant_user'@'localhost' WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 2 MAX_CONNECTIONS_PER_HOUR 3
@@ -501,6 +543,8 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, F
revoke ALL PRIVILEGES on *.* from grant_user@localhost
show grants for grant_user@localhost
+GRANT USAGE ON *.* TO 'grant_user'@'localhost' WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 2 MAX_CONNECTIONS_PER_HOUR 3
+
drop database grant_test
delete from user where user='grant_user'
delete from db where user='grant_user'
diff --git a/tests/table_types.pl b/tests/table_types.pl
index 8198cd9ba86..4dbcdcb975c 100755
--- a/tests/table_types.pl
+++ b/tests/table_types.pl
@@ -66,13 +66,6 @@ $dbh = $server->connect();
####
$table_name="bench1";
-<<<<<<< table_types.pl
-||||||| 1.2
-test("n","type=isam","char"); test("m","type=myisam pack_keys=1","char"); exit(1);
-
-=======
-
->>>>>>> /tmp/T4a17019
test($table_name,"type=isam","char");
test($table_name,"type=myisam pack_keys=0","char");
test($table_name,"type=myisam pack_keys=0","char");
@@ -91,7 +84,7 @@ exit (0);
sub test {
my ($name,$options,$chartype)=@_;
-
+
print "\nTesting with options: '$options'\n";
$dbh->do("drop table $name");
do_many($dbh,$server->create("$name",
@@ -102,23 +95,23 @@ sub test {
["primary key (id,id2)",
"index index_id3 (id3)"],
$options));
-
+
if ($opt_lock_tables)
{
$sth = $dbh->do("LOCK TABLES $name WRITE") || die $DBI::errstr;
}
-
+
if ($opt_fast && defined($server->{vacuum}))
{
$server->vacuum(\$dbh,1);
}
-
+
####
#### Insert $total_rows records in order, in reverse order and random.
####
-
+
$loop_time=new Benchmark;
-
+
if ($opt_fast_insert)
{
$query="insert into $name values ";
@@ -127,11 +120,11 @@ sub test {
{
$query="insert into $name (id,id2,id3,dummy1) values ";
}
-
+
if (($opt_fast || $opt_fast_insert) && $limits->{'multi_value_insert'})
{
$query_size=$server->{'limits'}->{'query_size'};
-
+
print "Inserting $opt_loop_count multiple-value rows in order\n";
$res=$query;
for ($i=0 ; $i < $opt_loop_count ; $i++)
@@ -186,7 +179,7 @@ sub test {
{
$sth = $dbh->do($query . "($i,$i,$i,'ABCDEFGHIJ')") or die $DBI::errstr;
}
-
+
print "Inserting $opt_loop_count rows in reverse order\n";
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
@@ -195,25 +188,25 @@ sub test {
($total_rows-1-$i) . ",'BCDEFGHIJK')")
or die $DBI::errstr;
}
-
+
print "Inserting $opt_loop_count rows in random order\n";
-
+
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
$sth = $dbh->do($query . "(". $random[$i] . "," . $random[$i] .
"," . $random[$i] . ",'CDEFGHIJKL')") or die $DBI::errstr;
}
}
-
+
$end_time=new Benchmark;
print "Time for insert (" . ($total_rows) . "): " .
timestr(timediff($end_time, $loop_time),"all") . "\n\n";
-
+
if ($opt_fast && defined($server->{vacuum}))
{
$server->vacuum(\$dbh,1);
}
-
+
$sth=$dbh->prepare("show table status like '$name'");
$sth->execute || die "Show table status returned error: $DBI::errstr\n";
while (@row = $sth->fetchrow_array)
diff --git a/vio/viossl.c b/vio/viossl.c
index cf1c98b5382..834343a77d9 100644
--- a/vio/viossl.c
+++ b/vio/viossl.c
@@ -212,13 +212,14 @@ my_socket vio_ssl_fd(Vio* vio)
}
-my_bool vio_ssl_peer_addr(Vio * vio, char *buf)
+my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port)
{
DBUG_ENTER("vio_ssl_peer_addr");
DBUG_PRINT("enter", ("sd=%d", vio->sd));
if (vio->localhost)
{
strmov(buf,"127.0.0.1");
+ *port=0;
}
else
{
@@ -229,8 +230,13 @@ my_bool vio_ssl_peer_addr(Vio * vio, char *buf)
DBUG_PRINT("exit", ("getpeername, error: %d", socket_errno));
DBUG_RETURN(1);
}
- /* FIXME */
-/* my_inet_ntoa(vio->remote.sin_addr,buf); */
+#ifdef TO_BE_FIXED
+ my_inet_ntoa(vio->remote.sin_addr,buf);
+ *port= 0;
+#else
+ strmov(buf, "unknown");
+ *port= 0;
+#endif
}
DBUG_PRINT("exit", ("addr=%s", buf));
DBUG_RETURN(0);
@@ -281,7 +287,8 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
SSL_SESSION_set_timeout(SSL_get_session(vio->ssl_), timeout);
SSL_set_fd(vio->ssl_,vio->sd);
SSL_set_accept_state(vio->ssl_);
- if (SSL_do_handshake(vio->ssl_) < 1)
+ if (SSL_do_handshake(vio->ssl_) < 1 ||
+ SSL_get_verify_result(vio->ssl_) != X509_V_OK)
{
DBUG_PRINT("error", ("SSL_do_handshake failure"));
report_errors();
@@ -354,7 +361,8 @@ 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_);
- if (SSL_do_handshake(vio->ssl_) < 1)
+ if (SSL_do_handshake(vio->ssl_) < 1 ||
+ SSL_get_verify_result(vio->ssl_) != X509_V_OK)
{
DBUG_PRINT("error", ("SSL_do_handshake failure"));
report_errors();